From aa3f0610d0af6e07b8ddcb0c6bbcd9673ac1efbd Mon Sep 17 00:00:00 2001 From: "Maaike Zijderveld, iolar" Date: Mon, 5 Aug 2024 18:59:05 +0200 Subject: [PATCH 01/12] Change init device model db so you can update all components and not only evse and connector. Signed-off-by: Maaike Zijderveld, iolar --- include/ocpp/v201/init_device_model_db.hpp | 37 ++--- lib/ocpp/v201/init_device_model_db.cpp | 146 +++--------------- .../standardized/UnitTestCtrlr.json | 14 -- .../ocpp/v201/test_init_device_model_db.cpp | 15 +- 4 files changed, 41 insertions(+), 171 deletions(-) diff --git a/include/ocpp/v201/init_device_model_db.hpp b/include/ocpp/v201/init_device_model_db.hpp index 10a285d1a..87b68e25f 100644 --- a/include/ocpp/v201/init_device_model_db.hpp +++ b/include/ocpp/v201/init_device_model_db.hpp @@ -213,7 +213,7 @@ class InitDeviceModelDb : public common::DatabaseHandlerCommon { /// \throw InitDeviceModelDbError When component could not be inserted /// void insert_components(const std::map>& components, - const std::vector& existing_components); + const std::map>& existing_components); /// /// \brief Insert a single component with its variables, characteristics and attributes. @@ -368,14 +368,6 @@ class InitDeviceModelDb : public common::DatabaseHandlerCommon { const VariableAttributeKey& variable_attribute_key, const bool warn_source_not_default); - /// - /// \brief Get all components from the db that are either EVSE or Connector. - /// \return EVSE and Connector components. - /// - /// \throws InitDeviceModelDbError When getting components from db failed. - /// - std::vector get_all_connector_and_evse_components_from_db(); - /// /// \brief Get all components with its variables (and characteristics / attributes) from the database. /// \return A map of Components with it Variables. @@ -388,8 +380,9 @@ class InitDeviceModelDb : public common::DatabaseHandlerCommon { /// \param component The component to check against. /// \return The component from the database if it exists. /// - std::optional component_exists_in_db(const std::vector& db_components, - const ComponentKey& component); + std::optional>> + component_exists_in_db(const std::map>& db_components, + const ComponentKey& component); /// /// \brief Check if a component exist in the component schema. @@ -409,7 +402,7 @@ class InitDeviceModelDb : public common::DatabaseHandlerCommon { /// void remove_not_existing_components_from_db( const std::map>& component_schemas, - const std::vector& db_components); + const std::map>& db_components); /// /// \brief Remove a component from the database. @@ -421,22 +414,14 @@ class InitDeviceModelDb : public common::DatabaseHandlerCommon { bool remove_component_from_db(const ComponentKey& component); /// - /// \brief Update variables of a component in the database. - /// - /// \param db_component The component that currently exists in the database and needs updating. - /// \param variables The variables of the component. - /// - void update_component_variables(const ComponentKey& db_component, - const std::vector& variables); - - /// - /// \brief Get variables belonging to a specific component from the database. - /// \param db_component The component to get the variables from. - /// \return The variables that belong to the given component. + /// \brief Update component_variables of a component in the database. /// - /// \throw InitDeviceModelDbError When variables could not be retrieved from the database. + /// \param db_component_variables The component that currently exists in the database and needs updating. + /// \param component_variables The component_variables of the component. /// - std::vector get_variables_from_component_from_db(const ComponentKey& db_component); + void + update_component_variables(const std::pair>& db_component_variables, + const std::vector& variables); /// /// \brief Get variable attributes belonging to a specific variable from the database. diff --git a/lib/ocpp/v201/init_device_model_db.cpp b/lib/ocpp/v201/init_device_model_db.cpp index df5a36963..f2b0989a4 100644 --- a/lib/ocpp/v201/init_device_model_db.cpp +++ b/lib/ocpp/v201/init_device_model_db.cpp @@ -53,10 +53,10 @@ void InitDeviceModelDb::initialize_database(const std::filesystem::path& schemas execute_init_sql(delete_db_if_exists); // Get existing EVSE and Connector components from the database. - std::vector existing_components; + std::map> existing_components; DeviceModelMap device_model; if (this->database_exists) { - existing_components = get_all_connector_and_evse_components_from_db(); + existing_components = get_all_components_from_db(); } // Get component schemas from the filesystem. @@ -214,16 +214,17 @@ InitDeviceModelDb::get_all_component_schemas(const std::filesystem::path& direct return components; } -void InitDeviceModelDb::insert_components(const std::map>& components, - const std::vector& existing_components) { - for (std::pair> component : components) { +void InitDeviceModelDb::insert_components( + const std::map>& components, + const std::map>& existing_components) { + for (auto& component : components) { // Check if component already exists in the database. - std::optional component_db; - if (this->database_exists && (component.first.name == "EVSE" || component.first.name == "Connector") && + std::optional>> component_db; + if (this->database_exists && (component_db = component_exists_in_db(existing_components, component.first)).has_value()) { // Component exists in the database, update component if necessary. update_component_variables(component_db.value(), component.second); - } else if (!this->database_exists || (component.first.name == "EVSE" || component.first.name == "Connector")) { + } else { // Database is new or component is evse or connector and component does not exist. Insert component. insert_component(component.first, component.second); } @@ -833,44 +834,6 @@ bool InitDeviceModelDb::insert_variable_attribute_value(const ComponentKey& comp return true; } -std::vector InitDeviceModelDb::get_all_connector_and_evse_components_from_db() { - std::vector components; - - const std::string statement = "SELECT ID, NAME, INSTANCE, EVSE_ID, CONNECTOR_ID FROM COMPONENT " - "WHERE NAME == 'EVSE' COLLATE NOCASE OR NAME == 'Connector' COLLATE NOCASE "; - - std::unique_ptr select_statement; - try { - select_statement = this->database->new_statement(statement); - } catch (const common::QueryExecutionException&) { - throw InitDeviceModelDbError("Could not create statement " + statement); - } - - int status; - while ((status = select_statement->step()) == SQLITE_ROW) { - ComponentKey component_key; - component_key.db_id = select_statement->column_int(0); - component_key.name = select_statement->column_text(1); - component_key.instance = select_statement->column_text_nullable(2); - if (select_statement->column_type(3) != SQLITE_NULL) { - component_key.evse_id = select_statement->column_int(3); - } - - if (select_statement->column_type(4) != SQLITE_NULL) { - component_key.connector_id = select_statement->column_int(4); - } - - components.push_back(component_key); - } - - if (status != SQLITE_DONE) { - throw InitDeviceModelDbError("Could not get all connector and evse components from the database: " + - std::string(this->database->get_error_message())); - } - - return components; -} - std::map> InitDeviceModelDb::get_all_components_from_db() { /* clang-format off */ const std::string statement = @@ -984,10 +947,11 @@ std::map> InitDeviceModelDb::get_ return components; } -std::optional InitDeviceModelDb::component_exists_in_db(const std::vector& db_components, - const ComponentKey& component) { - for (const ComponentKey& db_component : db_components) { - if (is_same_component_key(db_component, component)) { +std::optional>> +InitDeviceModelDb::component_exists_in_db(const std::map>& db_components, + const ComponentKey& component) { + for (const auto& db_component : db_components) { + if (is_same_component_key(db_component.first, component)) { return db_component; } } @@ -1008,10 +972,10 @@ bool InitDeviceModelDb::component_exists_in_schemas( void InitDeviceModelDb::remove_not_existing_components_from_db( const std::map>& component_schemas, - const std::vector& db_components) { - for (const ComponentKey& component : db_components) { - if (!component_exists_in_schemas(component_schemas, component)) { - remove_component_from_db(component); + const std::map>& db_components) { + for (const auto& component : db_components) { + if (!component_exists_in_schemas(component_schemas, component.first)) { + remove_component_from_db(component.first); } } } @@ -1040,15 +1004,17 @@ bool InitDeviceModelDb::remove_component_from_db(const ComponentKey& component) return true; } -void InitDeviceModelDb::update_component_variables(const ComponentKey& db_component, - const std::vector& variables) { +void InitDeviceModelDb::update_component_variables( + const std::pair>& db_component_variables, + const std::vector& variables) { + const std::vector& db_variables = db_component_variables.second; + const ComponentKey& db_component = db_component_variables.first; + if (!db_component.db_id.has_value()) { EVLOG_error << "Can not update component " << db_component.name << ", because database id is unknown."; return; } - const std::vector db_variables = get_variables_from_component_from_db(db_component); - // Check for variables that do exist in the database but do not exist in the config. They should be removed. for (const DeviceModelVariable& db_variable : db_variables) { auto it = std::find_if(variables.begin(), variables.end(), [&db_variable](const DeviceModelVariable& variable) { @@ -1080,70 +1046,6 @@ void InitDeviceModelDb::update_component_variables(const ComponentKey& db_compon } } -std::vector -InitDeviceModelDb::get_variables_from_component_from_db(const ComponentKey& db_component) { - if (!db_component.db_id.has_value()) { - EVLOG_error << "Can not update component " << db_component.name << ", because database id is unknown."; - return {}; - } - - std::vector variables; - - static const std::string select_variable_statement = - "SELECT v.ID, v.NAME, v.INSTANCE, v.REQUIRED, vc.ID, vc.DATATYPE_ID, vc.MAX_LIMIT, vc.MIN_LIMIT, " - "vc.SUPPORTS_MONITORING, vc.UNIT, vc.VALUES_LIST FROM VARIABLE v LEFT JOIN VARIABLE_CHARACTERISTICS vc " - "ON v.ID=vc.VARIABLE_ID WHERE v.COMPONENT_ID=@component_id"; - - std::unique_ptr select_statement; - try { - select_statement = this->database->new_statement(select_variable_statement); - } catch (const common::QueryExecutionException&) { - throw InitDeviceModelDbError("Could not create statement " + select_variable_statement); - } - - select_statement->bind_int("@component_id", static_cast(db_component.db_id.value())); - - int status; - while ((status = select_statement->step()) == SQLITE_ROW) { - DeviceModelVariable variable; - variable.db_id = select_statement->column_int(0); - variable.name = select_statement->column_text(1); - if (select_statement->column_type(2) != SQLITE_NULL) { - variable.instance = select_statement->column_text(2); - } - variable.required = (select_statement->column_int(3) == 1 ? true : false); - variable.variable_characteristics_db_id = select_statement->column_int(4); - variable.characteristics.dataType = static_cast(select_statement->column_int(5)); - if (select_statement->column_type(6) != SQLITE_NULL) { - variable.characteristics.maxLimit = select_statement->column_double(6); - } - if (select_statement->column_type(7) != SQLITE_NULL) { - variable.characteristics.minLimit = select_statement->column_double(7); - } - variable.characteristics.supportsMonitoring = (select_statement->column_int(8) == 1 ? true : false); - if (select_statement->column_type(9) != SQLITE_NULL) { - variable.characteristics.unit = select_statement->column_text(9); - } - if (select_statement->column_type(10) != SQLITE_NULL) { - variable.characteristics.valuesList = select_statement->column_text(10); - } - - variables.push_back(variable); - } - - if (status != SQLITE_DONE) { - throw InitDeviceModelDbError("Could not get variables from component " + db_component.name + - "from db: " + std::string(this->database->get_error_message())); - } - - for (DeviceModelVariable& variable : variables) { - std::vector attributes = get_variable_attributes_from_db(variable.db_id.value()); - variable.attributes = attributes; - } - - return variables; -} - std::vector InitDeviceModelDb::get_variable_attributes_from_db(const uint64_t& variable_id) { std::vector attributes; diff --git a/tests/config/v201/resources_changed/component_schemas/standardized/UnitTestCtrlr.json b/tests/config/v201/resources_changed/component_schemas/standardized/UnitTestCtrlr.json index 47658b7f3..8627dae06 100644 --- a/tests/config/v201/resources_changed/component_schemas/standardized/UnitTestCtrlr.json +++ b/tests/config/v201/resources_changed/component_schemas/standardized/UnitTestCtrlr.json @@ -34,20 +34,6 @@ } ], "type": "string" - }, - "UnitTestPropertyC": { - "variable_name": "UnitTestPropertyCName", - "characteristics": { - "supportsMonitoring": false, - "dataType": "decimal" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "type": "number" } }, "required": [ diff --git a/tests/lib/ocpp/v201/test_init_device_model_db.cpp b/tests/lib/ocpp/v201/test_init_device_model_db.cpp index 045e242d4..87225b4cd 100644 --- a/tests/lib/ocpp/v201/test_init_device_model_db.cpp +++ b/tests/lib/ocpp/v201/test_init_device_model_db.cpp @@ -341,17 +341,16 @@ TEST_F(InitDeviceModelDbTest, init_db) { EXPECT_TRUE(attribute_exists("EVSE", std::nullopt, 1, std::nullopt, "Power", std::nullopt, MutabilityEnum::ReadWrite, AttributeEnum::Target)); - // Characteristics changed from not EVSE or Connector (should not change in db) - EXPECT_TRUE(characteristics_exists("UnitTestCtrlr", std::nullopt, 2, 3, "UnitTestPropertyAName", std::nullopt, - DataEnum::boolean, std::nullopt, std::nullopt, true, std::nullopt, - std::nullopt)); + // Characteristics changed from not EVSE or Connector EXPECT_FALSE(characteristics_exists("UnitTestCtrlr", std::nullopt, 2, 3, "UnitTestPropertyAName", std::nullopt, - DataEnum::string, std::nullopt, std::nullopt, true, std::nullopt, + DataEnum::boolean, std::nullopt, std::nullopt, true, std::nullopt, std::nullopt)); + EXPECT_TRUE(characteristics_exists("UnitTestCtrlr", std::nullopt, 2, 3, "UnitTestPropertyAName", std::nullopt, + DataEnum::string, std::nullopt, std::nullopt, true, std::nullopt, std::nullopt)); - // No change, because this is not a Connector or EVSE + // Removed UnitTestPropertyCName EXPECT_TRUE(variable_exists("UnitTestCtrlr", std::nullopt, 2, 3, "UnitTestPropertyBName", std::nullopt)); - EXPECT_TRUE(variable_exists("UnitTestCtrlr", std::nullopt, 2, 3, "UnitTestPropertyCName", std::nullopt)); + EXPECT_FALSE(variable_exists("UnitTestCtrlr", std::nullopt, 2, 3, "UnitTestPropertyCName", std::nullopt)); } TEST_F(InitDeviceModelDbTest, insert_values) { @@ -902,6 +901,4 @@ void InitDeviceModelDbTest::set_attribute_source(const std::string& component_na } } -// TODO tests with non existing paths - } // namespace ocpp::v201 From 737b6d39efdf211dc945bf65126f2c49f71d8e8f Mon Sep 17 00:00:00 2001 From: "Maaike Zijderveld, iolar" Date: Tue, 6 Aug 2024 18:28:19 +0200 Subject: [PATCH 02/12] Change init device model db so that it does not need a config file anymore but only schema's, in which the config values are set. Signed-off-by: Maaike Zijderveld, iolar --- config/v201/CMakeLists.txt | 13 +- .../custom/Connector_1_1.json | 0 .../custom/Connector_2_1.json | 0 .../custom/EVSE_1.json | 0 .../custom/EVSE_2.json | 0 .../standardized/AlignedDataCtrlr.json | 0 .../standardized/AuthCacheCtrlr.json | 0 .../standardized/AuthCtrlr.json | 0 .../standardized/ChargingStation.json | 0 .../standardized/ChargingStatusIndicator.json | 0 .../standardized/ClockCtrlr.json | 0 .../standardized/CustomizationCtrlr.json | 0 .../standardized/DeviceDataCtrlr.json | 0 .../standardized/DisplayMessageCtrlr.json | 0 .../standardized/ISO15118Ctrlr.json | 0 .../standardized/InternalCtrlr.json | 0 .../standardized/LocalAuthListCtrlr.json | 0 .../standardized/MonitoringCtrlr.json | 0 .../standardized/OCPPCommCtrlr.json | 0 .../standardized/ReservationCtrlr.json | 0 .../standardized/SampledDataCtrlr.json | 0 .../standardized/SecurityCtrlr.json | 0 .../standardized/SmartChargingCtrlr.json | 0 .../standardized/TariffCostCtrlr.json | 0 .../standardized/TxCtrlr.json | 0 doc/ocpp_201_device_model_initialization.md | 20 +- include/ocpp/v201/charge_point.hpp | 7 +- .../ocpp/v201/device_model_storage_sqlite.hpp | 4 +- include/ocpp/v201/init_device_model_db.hpp | 98 ++-- lib/ocpp/v201/charge_point.cpp | 12 +- lib/ocpp/v201/device_model_storage_sqlite.cpp | 8 +- lib/ocpp/v201/init_device_model_db.cpp | 451 +++--------------- lib/ocpp/v201/ocpp_types.cpp | 22 +- src/code_generator/README.md | 14 +- ...chemas.py => generate_component_config.py} | 0 tests/CMakeLists.txt | 7 +- .../custom/Connector_1_1.json | 93 ++++ .../custom/Connector_2_1.json | 94 ++++ .../component_config/custom/EVSE_1.json | 134 ++++++ .../component_config/custom/EVSE_2.json | 133 ++++++ .../standardized/UnitTestCtrlr.json | 57 +++ .../custom/Connector_1_1.json | 111 +++++ .../custom/Connector_2_2.json | 46 ++ .../component_config/custom/EVSE_1.json | 120 +++++ .../component_config/custom/EVSE_2.json | 129 +++++ .../component_config/custom/EVSE_3.json | 130 +++++ .../standardized/UnitTestCtrlr.json | 42 ++ .../config/v201/test_init_device_model_db.py | 180 ------- .../ocpp/v201/test_init_device_model_db.cpp | 270 +++++------ .../ocpp/v201/test_smart_charging_handler.cpp | 4 +- 50 files changed, 1391 insertions(+), 808 deletions(-) rename config/v201/{component_schemas => component_config}/custom/Connector_1_1.json (100%) rename config/v201/{component_schemas => component_config}/custom/Connector_2_1.json (100%) rename config/v201/{component_schemas => component_config}/custom/EVSE_1.json (100%) rename config/v201/{component_schemas => component_config}/custom/EVSE_2.json (100%) rename config/v201/{component_schemas => component_config}/standardized/AlignedDataCtrlr.json (100%) rename config/v201/{component_schemas => component_config}/standardized/AuthCacheCtrlr.json (100%) rename config/v201/{component_schemas => component_config}/standardized/AuthCtrlr.json (100%) rename config/v201/{component_schemas => component_config}/standardized/ChargingStation.json (100%) rename config/v201/{component_schemas => component_config}/standardized/ChargingStatusIndicator.json (100%) rename config/v201/{component_schemas => component_config}/standardized/ClockCtrlr.json (100%) rename config/v201/{component_schemas => component_config}/standardized/CustomizationCtrlr.json (100%) rename config/v201/{component_schemas => component_config}/standardized/DeviceDataCtrlr.json (100%) rename config/v201/{component_schemas => component_config}/standardized/DisplayMessageCtrlr.json (100%) rename config/v201/{component_schemas => component_config}/standardized/ISO15118Ctrlr.json (100%) rename config/v201/{component_schemas => component_config}/standardized/InternalCtrlr.json (100%) rename config/v201/{component_schemas => component_config}/standardized/LocalAuthListCtrlr.json (100%) rename config/v201/{component_schemas => component_config}/standardized/MonitoringCtrlr.json (100%) rename config/v201/{component_schemas => component_config}/standardized/OCPPCommCtrlr.json (100%) rename config/v201/{component_schemas => component_config}/standardized/ReservationCtrlr.json (100%) rename config/v201/{component_schemas => component_config}/standardized/SampledDataCtrlr.json (100%) rename config/v201/{component_schemas => component_config}/standardized/SecurityCtrlr.json (100%) rename config/v201/{component_schemas => component_config}/standardized/SmartChargingCtrlr.json (100%) rename config/v201/{component_schemas => component_config}/standardized/TariffCostCtrlr.json (100%) rename config/v201/{component_schemas => component_config}/standardized/TxCtrlr.json (100%) rename src/code_generator/v201/{generate_component_schemas.py => generate_component_config.py} (100%) create mode 100644 tests/config/v201/resources/component_config/custom/Connector_1_1.json create mode 100644 tests/config/v201/resources/component_config/custom/Connector_2_1.json create mode 100644 tests/config/v201/resources/component_config/custom/EVSE_1.json create mode 100644 tests/config/v201/resources/component_config/custom/EVSE_2.json create mode 100644 tests/config/v201/resources/component_config/standardized/UnitTestCtrlr.json create mode 100644 tests/config/v201/resources_changed/component_config/custom/Connector_1_1.json create mode 100644 tests/config/v201/resources_changed/component_config/custom/Connector_2_2.json create mode 100644 tests/config/v201/resources_changed/component_config/custom/EVSE_1.json create mode 100644 tests/config/v201/resources_changed/component_config/custom/EVSE_2.json create mode 100644 tests/config/v201/resources_changed/component_config/custom/EVSE_3.json create mode 100644 tests/config/v201/resources_changed/component_config/standardized/UnitTestCtrlr.json delete mode 100644 tests/config/v201/test_init_device_model_db.py diff --git a/config/v201/CMakeLists.txt b/config/v201/CMakeLists.txt index 98b4cb98f..60fef10b8 100644 --- a/config/v201/CMakeLists.txt +++ b/config/v201/CMakeLists.txt @@ -34,17 +34,12 @@ install( if (LIBOCPP_INSTALL_DEVICE_MODEL_DATABASE) - if(NOT LIBOCPP_V201_CONFIG_FILE) - set(LIBOCPP_V201_CONFIG_FILE "${CMAKE_CURRENT_SOURCE_DIR}/config.json") - endif() - - if (NOT LIBOCPP_COMPONENT_SCHEMAS_PATH) - set(LIBOCPP_COMPONENT_SCHEMAS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/component_schemas") + if (NOT LIBOCPP_COMPONENT_CONFIG_PATH) + set(LIBOCPP_COMPONENT_CONFIG_PATH "${CMAKE_CURRENT_SOURCE_DIR}/component_config") endif() - message(STATUS "Using ocpp v201 config file path: ${LIBOCPP_V201_CONFIG_FILE}") + message(STATUS "Using ocpp v201 component config file path: ${LIBOCPP_COMPONENT_CONFIG_PATH}") - install(FILES ${LIBOCPP_V201_CONFIG_FILE} DESTINATION ${CMAKE_INSTALL_DATADIR}/everest/modules/OCPP201) - install(DIRECTORY ${LIBOCPP_COMPONENT_SCHEMAS_PATH} DESTINATION ${CMAKE_INSTALL_DATADIR}/everest/modules/OCPP201) + install(DIRECTORY ${LIBOCPP_COMPONENT_CONFIG_PATH} DESTINATION ${CMAKE_INSTALL_DATADIR}/everest/modules/OCPP201) endif() diff --git a/config/v201/component_schemas/custom/Connector_1_1.json b/config/v201/component_config/custom/Connector_1_1.json similarity index 100% rename from config/v201/component_schemas/custom/Connector_1_1.json rename to config/v201/component_config/custom/Connector_1_1.json diff --git a/config/v201/component_schemas/custom/Connector_2_1.json b/config/v201/component_config/custom/Connector_2_1.json similarity index 100% rename from config/v201/component_schemas/custom/Connector_2_1.json rename to config/v201/component_config/custom/Connector_2_1.json diff --git a/config/v201/component_schemas/custom/EVSE_1.json b/config/v201/component_config/custom/EVSE_1.json similarity index 100% rename from config/v201/component_schemas/custom/EVSE_1.json rename to config/v201/component_config/custom/EVSE_1.json diff --git a/config/v201/component_schemas/custom/EVSE_2.json b/config/v201/component_config/custom/EVSE_2.json similarity index 100% rename from config/v201/component_schemas/custom/EVSE_2.json rename to config/v201/component_config/custom/EVSE_2.json diff --git a/config/v201/component_schemas/standardized/AlignedDataCtrlr.json b/config/v201/component_config/standardized/AlignedDataCtrlr.json similarity index 100% rename from config/v201/component_schemas/standardized/AlignedDataCtrlr.json rename to config/v201/component_config/standardized/AlignedDataCtrlr.json diff --git a/config/v201/component_schemas/standardized/AuthCacheCtrlr.json b/config/v201/component_config/standardized/AuthCacheCtrlr.json similarity index 100% rename from config/v201/component_schemas/standardized/AuthCacheCtrlr.json rename to config/v201/component_config/standardized/AuthCacheCtrlr.json diff --git a/config/v201/component_schemas/standardized/AuthCtrlr.json b/config/v201/component_config/standardized/AuthCtrlr.json similarity index 100% rename from config/v201/component_schemas/standardized/AuthCtrlr.json rename to config/v201/component_config/standardized/AuthCtrlr.json diff --git a/config/v201/component_schemas/standardized/ChargingStation.json b/config/v201/component_config/standardized/ChargingStation.json similarity index 100% rename from config/v201/component_schemas/standardized/ChargingStation.json rename to config/v201/component_config/standardized/ChargingStation.json diff --git a/config/v201/component_schemas/standardized/ChargingStatusIndicator.json b/config/v201/component_config/standardized/ChargingStatusIndicator.json similarity index 100% rename from config/v201/component_schemas/standardized/ChargingStatusIndicator.json rename to config/v201/component_config/standardized/ChargingStatusIndicator.json diff --git a/config/v201/component_schemas/standardized/ClockCtrlr.json b/config/v201/component_config/standardized/ClockCtrlr.json similarity index 100% rename from config/v201/component_schemas/standardized/ClockCtrlr.json rename to config/v201/component_config/standardized/ClockCtrlr.json diff --git a/config/v201/component_schemas/standardized/CustomizationCtrlr.json b/config/v201/component_config/standardized/CustomizationCtrlr.json similarity index 100% rename from config/v201/component_schemas/standardized/CustomizationCtrlr.json rename to config/v201/component_config/standardized/CustomizationCtrlr.json diff --git a/config/v201/component_schemas/standardized/DeviceDataCtrlr.json b/config/v201/component_config/standardized/DeviceDataCtrlr.json similarity index 100% rename from config/v201/component_schemas/standardized/DeviceDataCtrlr.json rename to config/v201/component_config/standardized/DeviceDataCtrlr.json diff --git a/config/v201/component_schemas/standardized/DisplayMessageCtrlr.json b/config/v201/component_config/standardized/DisplayMessageCtrlr.json similarity index 100% rename from config/v201/component_schemas/standardized/DisplayMessageCtrlr.json rename to config/v201/component_config/standardized/DisplayMessageCtrlr.json diff --git a/config/v201/component_schemas/standardized/ISO15118Ctrlr.json b/config/v201/component_config/standardized/ISO15118Ctrlr.json similarity index 100% rename from config/v201/component_schemas/standardized/ISO15118Ctrlr.json rename to config/v201/component_config/standardized/ISO15118Ctrlr.json diff --git a/config/v201/component_schemas/standardized/InternalCtrlr.json b/config/v201/component_config/standardized/InternalCtrlr.json similarity index 100% rename from config/v201/component_schemas/standardized/InternalCtrlr.json rename to config/v201/component_config/standardized/InternalCtrlr.json diff --git a/config/v201/component_schemas/standardized/LocalAuthListCtrlr.json b/config/v201/component_config/standardized/LocalAuthListCtrlr.json similarity index 100% rename from config/v201/component_schemas/standardized/LocalAuthListCtrlr.json rename to config/v201/component_config/standardized/LocalAuthListCtrlr.json diff --git a/config/v201/component_schemas/standardized/MonitoringCtrlr.json b/config/v201/component_config/standardized/MonitoringCtrlr.json similarity index 100% rename from config/v201/component_schemas/standardized/MonitoringCtrlr.json rename to config/v201/component_config/standardized/MonitoringCtrlr.json diff --git a/config/v201/component_schemas/standardized/OCPPCommCtrlr.json b/config/v201/component_config/standardized/OCPPCommCtrlr.json similarity index 100% rename from config/v201/component_schemas/standardized/OCPPCommCtrlr.json rename to config/v201/component_config/standardized/OCPPCommCtrlr.json diff --git a/config/v201/component_schemas/standardized/ReservationCtrlr.json b/config/v201/component_config/standardized/ReservationCtrlr.json similarity index 100% rename from config/v201/component_schemas/standardized/ReservationCtrlr.json rename to config/v201/component_config/standardized/ReservationCtrlr.json diff --git a/config/v201/component_schemas/standardized/SampledDataCtrlr.json b/config/v201/component_config/standardized/SampledDataCtrlr.json similarity index 100% rename from config/v201/component_schemas/standardized/SampledDataCtrlr.json rename to config/v201/component_config/standardized/SampledDataCtrlr.json diff --git a/config/v201/component_schemas/standardized/SecurityCtrlr.json b/config/v201/component_config/standardized/SecurityCtrlr.json similarity index 100% rename from config/v201/component_schemas/standardized/SecurityCtrlr.json rename to config/v201/component_config/standardized/SecurityCtrlr.json diff --git a/config/v201/component_schemas/standardized/SmartChargingCtrlr.json b/config/v201/component_config/standardized/SmartChargingCtrlr.json similarity index 100% rename from config/v201/component_schemas/standardized/SmartChargingCtrlr.json rename to config/v201/component_config/standardized/SmartChargingCtrlr.json diff --git a/config/v201/component_schemas/standardized/TariffCostCtrlr.json b/config/v201/component_config/standardized/TariffCostCtrlr.json similarity index 100% rename from config/v201/component_schemas/standardized/TariffCostCtrlr.json rename to config/v201/component_config/standardized/TariffCostCtrlr.json diff --git a/config/v201/component_schemas/standardized/TxCtrlr.json b/config/v201/component_config/standardized/TxCtrlr.json similarity index 100% rename from config/v201/component_schemas/standardized/TxCtrlr.json rename to config/v201/component_config/standardized/TxCtrlr.json diff --git a/doc/ocpp_201_device_model_initialization.md b/doc/ocpp_201_device_model_initialization.md index 6111c3ab7..b7edcdd11 100644 --- a/doc/ocpp_201_device_model_initialization.md +++ b/doc/ocpp_201_device_model_initialization.md @@ -35,20 +35,16 @@ accordingly. Only the initial values will be set to the values in the config fil value, it will not be updated to the value from the config file. -## Update component schemas +## Update component config -It is only possible to update the component schemas for `EVSE`'s and `Connector`s. All other components can not be updated. - -To update an `EVSE` or `Connector` component, just place the correct `EVSE` / `Connector` json schema in the -`component_schemas/custom` folder. When restarting the software, it will: -- Check if there are `EVSE`'s or `Connector`s in the database that are not in the component schema's. Those will be - removed. -- Check if there are `EVSE`'s er `Connectors` in the component schema's that are not in the database. Those will be - added. -- Check if anything has changed inside the `EVSE`'s or `Connectors` (`Variable`, `Characteristics` or `Attributes`). +To update a component, just place the correct json schema in the `component_config/custom` folder. When restarting the +software, it will: +- Check if there are Components in the database that are not in the component config's. Those will be removed. +- Check if there are Components in the component config's that are not in the database. Those will be added. +- Check if anything has changed inside the Component (`Variable`, `Characteristics` or `Attributes`). Those will be removed, changed or added. Those will be removed, changed or added to the database as well. -Note: When the id of an `EVSE` Component is changed, this is seen as the removal of an `EVSE` and addition of a new -`EVSE`. The same applies to the `evse_id` or `connector_id` of a `Connector` component. +Note: When the `evse_id` or `connector_id` of a component is changed, this is seen as the removal of a Component and +addition of a new one. Note: OCPP requires EVSE and Connector numbering starting from 1 counting upwards. diff --git a/include/ocpp/v201/charge_point.hpp b/include/ocpp/v201/charge_point.hpp index 441291bf5..a77f01d72 100644 --- a/include/ocpp/v201/charge_point.hpp +++ b/include/ocpp/v201/charge_point.hpp @@ -787,8 +787,7 @@ class ChargePoint : public ChargePointInterface, private ocpp::ChargingStationBa /// \param device_model_storage_address address to device model storage (e.g. location of SQLite database) /// \param initialize_device_model Set to true to initialize the device model database /// \param device_model_migration_path Path to the device model database migration files - /// \param device_model_schemas_path Path to the device model schemas - /// \param config_path Path to the chargepoint configuration + /// \param device_model_config_path Path to the device model config /// \param ocpp_main_path Path where utility files for OCPP are read and written to /// \param core_database_path Path to directory where core database is located /// \param message_log_path Path to where logfiles are written to @@ -799,8 +798,8 @@ class ChargePoint : public ChargePointInterface, private ocpp::ChargingStationBa /// implementation ChargePoint(const std::map& evse_connector_structure, const std::string& device_model_storage_address, const bool initialize_device_model, - const std::string& device_model_migration_path, const std::string& device_model_schemas_path, - const std::string& config_path, const std::string& ocpp_main_path, + const std::string& device_model_migration_path, const std::string& device_model_config_path, + const std::string& ocpp_main_path, const std::string& core_database_path, const std::string& sql_init_path, const std::string& message_log_path, const std::shared_ptr evse_security, const Callbacks& callbacks); diff --git a/include/ocpp/v201/device_model_storage_sqlite.hpp b/include/ocpp/v201/device_model_storage_sqlite.hpp index b868fa9c3..dd52d7e46 100644 --- a/include/ocpp/v201/device_model_storage_sqlite.hpp +++ b/include/ocpp/v201/device_model_storage_sqlite.hpp @@ -31,12 +31,10 @@ class DeviceModelStorageSqlite : public DeviceModelStorage { /// \param db_path Path to database /// \param migration_files_path Path to the migration files to initialize the database (only needs to be set if /// `init_db` is true) - /// \param schemas_path Path to the device model schemas (only needs to be set if `init_db` is true) - /// \param config_path Path to the configuration file (only needs to be set if `init_db` is true) + /// \param config_path Path to the device model schemas (only needs to be set if `init_db` is true) /// \param init_db True to initialize the database /// explicit DeviceModelStorageSqlite(const fs::path& db_path, const std::filesystem::path& migration_files_path = "", - const std::filesystem::path& schemas_path = "", const std::filesystem::path& config_path = "", const bool init_db = false); ~DeviceModelStorageSqlite() = default; diff --git a/include/ocpp/v201/init_device_model_db.hpp b/include/ocpp/v201/init_device_model_db.hpp index 87b68e25f..794d7ab26 100644 --- a/include/ocpp/v201/init_device_model_db.hpp +++ b/include/ocpp/v201/init_device_model_db.hpp @@ -11,8 +11,8 @@ /// /// This class will read the device model schemas and config file and put them in the device model database. /// -/// If the database already exists and there are some changes on the Connector and / or EVSE components, this class -/// will make the changes in the database accordingly. For other components, no changes will be made. +/// If the database already exists and there are some changes on components, this class will make the changes in the +/// database accordingly. /// /// It will also re-apply the config file. Config items will only be replaced if they are changed and the value in the /// database is not set by an external source, like the CSMS. @@ -93,16 +93,6 @@ struct DeviceModelVariable { std::optional default_actual_value; }; -/// -/// \brief Struct holding a config item value. -/// -struct VariableAttributeKey { - std::string name; ///< \brief Variable name - std::optional instance; ///< \brief Variable instance - AttributeEnum attribute_type; ///< \brief Attribute type - std::string value; ///< \brief Attribute value -}; - /// \brief Convert from json to a ComponentKey struct. /// The to_json is not implemented as we don't need to write the schema to a json file. void from_json(const json& j, ComponentKey& c); @@ -152,7 +142,7 @@ class InitDeviceModelDb : public common::DatabaseHandlerCommon { /// /// \brief Initialize the database schema. - /// \param schemas_path Path to the database schemas. + /// \param config_path Path to the database schemas. /// \param delete_db_if_exists Set to true to delete the database if it already exists. /// /// \throws InitDeviceModelDbError - When database could not be initialized or @@ -164,18 +154,7 @@ class InitDeviceModelDb : public common::DatabaseHandlerCommon { /// \throws std::filesystem::filesystem_error If the schemas path does not exist /// /// - void initialize_database(const std::filesystem::path& schemas_path, const bool delete_db_if_exists); - - /// - /// \brief Insert database configuration and default values. - /// \param schemas_path Path to the database schemas. - /// \param config_path Path to the database config. - /// \return True on success. False if at least one of the items could not be set. - /// - /// \throws InitDeviceModelDbError When config and default values could not be set - /// - bool insert_config_and_default_values(const std::filesystem::path& schemas_path, - const std::filesystem::path& config_path); + void initialize_database(const std::filesystem::path& config_path, const bool delete_db_if_exists); private: // Functions /// @@ -191,11 +170,11 @@ class InitDeviceModelDb : public common::DatabaseHandlerCommon { void execute_init_sql(const bool delete_db_if_exists); /// - /// \brief Get all paths to the component schemas (*.json) in the given directory. - /// \param directory Parent directory holding the standardized and component schema's. - /// \return All path to the component schema's json files in the given directory. + /// \brief Get all paths to the component configs (*.json) in the given directory. + /// \param directory Parent directory holding the standardized and component config's. + /// \return All path to the component config's json files in the given directory. /// - std::vector get_component_schemas_from_directory(const std::filesystem::path& directory); + std::vector get_component_config_from_directory(const std::filesystem::path& directory); /// /// \brief Read all component schema's from the given directory and create a map holding the structure. @@ -203,12 +182,12 @@ class InitDeviceModelDb : public common::DatabaseHandlerCommon { /// \return A map with the device model components, variables, characteristics and attributes. /// std::map> - get_all_component_schemas(const std::filesystem::path& directory); + get_all_component_configs(const std::filesystem::path& directory); /// /// \brief Insert components, including variables, characteristics and attributes, to the database. /// \param components The map with all components, variables, characteristics and attributes. - /// \param existing_components Vector with components that already exist in the database (Connector and EVSE). + /// \param existing_components Vector with components that already exist in the database. /// /// \throw InitDeviceModelDbError When component could not be inserted /// @@ -229,7 +208,7 @@ class InitDeviceModelDb : public common::DatabaseHandlerCommon { /// \return A map holding the components with its variables, characteristics and attributes. /// std::map> - read_component_schemas(const std::vector& components_schema_path); + read_component_config(const std::vector& components_schema_path); /// /// \brief Get all component properties (variables) from the given (component) json. @@ -292,19 +271,23 @@ class InitDeviceModelDb : public common::DatabaseHandlerCommon { /// \brief Insert a variable attribute into the database. /// \param attribute The attribute to insert. /// \param variable_id The variable id the attribute belongs to. + /// \param default_actual_value The default value for the 'Actual' attribute. /// /// \throws InitDeviceModelDbError If attribute could not be inserted /// - void insert_attribute(const VariableAttribute& attribute, const uint64_t& variable_id); + void insert_attribute(const VariableAttribute& attribute, const uint64_t& variable_id, + const std::optional& default_actual_value); /// /// \brief Insert variable attributes into the database. /// \param attributes The attributes to insert. /// \param variable_id The variable id the attributes belong to. + /// \param default_actual_value The default value for the 'Actual' attribute. /// /// \throws InitDeviceModelDbError If one of the attributes could not be inserted or updated /// - void insert_attributes(const std::vector& attributes, const uint64_t& variable_id); + void insert_attributes(const std::vector& attributes, const uint64_t& variable_id, + const std::optional& default_actual_value); /// /// \brief Update variable attributes in the database. @@ -315,20 +298,24 @@ class InitDeviceModelDb : public common::DatabaseHandlerCommon { /// \param new_attributes The attributes information with the new values. /// \param db_attributes The attributes currently in the database that needs updating. /// \param variable_id The variable id the attributes belong to. + /// \param default_actual_value The default value for the 'Actual' attribute. /// /// \throws InitDeviceModelDbError If one of the attributes could not be updated /// void update_attributes(const std::vector& new_attributes, - const std::vector& db_attributes, const uint64_t& variable_id); + const std::vector& db_attributes, const uint64_t& variable_id, + const std::optional& default_actual_value); /// /// \brief Update a single attribute /// \param attribute The attribute with the new values /// \param db_attribute The attribute currently in the database, that needs updating. + /// \param default_actual_value The default value for the 'Actual' attribute. /// /// \throws InitDeviceModelDbError If the attribute could not be updated /// - void update_attribute(const VariableAttribute& attribute, const DbVariableAttribute& db_attribute); + void update_attribute(const VariableAttribute& attribute, const DbVariableAttribute& db_attribute, + const std::optional& default_actual_value); /// /// \brief Delete an attribute from the database. @@ -339,33 +326,18 @@ class InitDeviceModelDb : public common::DatabaseHandlerCommon { void delete_attribute(const DbVariableAttribute& attribute); /// - /// \brief Get default values of all variable attribute of a component. - /// \param schemas_path The path of the schema holding the default values. - /// \return A map with default variable attribute values per component. - /// - std::map> - get_component_default_values(const std::filesystem::path& schemas_path); - - /// - /// \brief Get config values. - /// \param config_file_path The path to the config file. - /// \return A map with variable attribute values per component. - /// - std::map> - get_config_values(const std::filesystem::path& config_file_path); - - /// - /// \brief Insert variable attribute value - /// \param component_key Component the variable attribute belongs to. - /// \param variable_attribute_key Variable attribute including value to insert. - /// \param warn_source_not_default Put a warning in the log if the variable could not be added because the - /// value source is not 'default'. + /// \brief Insert varaible attribute value + /// \param variable_attribute_id Variable attribute id + /// \param variable_attribute_value Attribute value + /// \param warn_source_not_default Put a warning in the log if the value could not be added because the value + /// source + /// is not 'default' /// \return true on success /// - /// \throws InitDeviceModelDbError When inserting failed. + /// \throws InitDeviceModelDbError When inserting failed /// - bool insert_variable_attribute_value(const ComponentKey& component_key, - const VariableAttributeKey& variable_attribute_key, + bool insert_variable_attribute_value(const int64_t& variable_attribute_id, + const std::string& variable_attribute_value, const bool warn_source_not_default); /// @@ -394,14 +366,14 @@ class InitDeviceModelDb : public common::DatabaseHandlerCommon { const ComponentKey& component); /// - /// \brief Remove components from db that do not exist in the component schemas. - /// \param component_schemas The component schemas. + /// \brief Remove components from db that do not exist in the component config. + /// \param component_config The component config. /// \param db_components The components in the database. /// /// \throws InitDeviceModelDbError When one of the components could not be removed from the db. /// void remove_not_existing_components_from_db( - const std::map>& component_schemas, + const std::map>& component_config, const std::map>& db_components); /// diff --git a/lib/ocpp/v201/charge_point.cpp b/lib/ocpp/v201/charge_point.cpp index 3c9ec43a3..51e9ab402 100644 --- a/lib/ocpp/v201/charge_point.cpp +++ b/lib/ocpp/v201/charge_point.cpp @@ -64,15 +64,13 @@ bool Callbacks::all_callbacks_valid() const { ChargePoint::ChargePoint(const std::map& evse_connector_structure, const std::string& device_model_storage_address, const bool initialize_device_model, - const std::string& device_model_migration_path, const std::string& device_model_schemas_path, - const std::string& config_path, const std::string& ocpp_main_path, - const std::string& core_database_path, const std::string& sql_init_path, - const std::string& message_log_path, const std::shared_ptr evse_security, - const Callbacks& callbacks) : + const std::string& device_model_migration_path, const std::string& device_model_config_path, + const std::string& ocpp_main_path, const std::string& core_database_path, + const std::string& sql_init_path, const std::string& message_log_path, + const std::shared_ptr evse_security, const Callbacks& callbacks) : ChargePoint(evse_connector_structure, std::make_unique(device_model_storage_address, device_model_migration_path, - device_model_schemas_path, config_path, - initialize_device_model), + device_model_config_path, initialize_device_model), ocpp_main_path, core_database_path, sql_init_path, message_log_path, evse_security, callbacks) { } diff --git a/lib/ocpp/v201/device_model_storage_sqlite.cpp b/lib/ocpp/v201/device_model_storage_sqlite.cpp index ea16285b8..90aff34e9 100644 --- a/lib/ocpp/v201/device_model_storage_sqlite.cpp +++ b/lib/ocpp/v201/device_model_storage_sqlite.cpp @@ -19,16 +19,14 @@ extern void filter_criteria_monitors(const std::vector& std::vector& monitors); DeviceModelStorageSqlite::DeviceModelStorageSqlite(const fs::path& db_path, const fs::path& migration_files_path, - const fs::path& schemas_path, const fs::path& config_path, - const bool init_db) { + const fs::path& config_path, const bool init_db) { if (init_db) { - if (db_path.empty() || migration_files_path.empty() || schemas_path.empty() || config_path.empty()) { + if (db_path.empty() || migration_files_path.empty() || config_path.empty()) { EVLOG_AND_THROW( DeviceModelStorageError("Can not initialize device model storage: one of the paths is empty.")); } InitDeviceModelDb init_device_model_db(db_path, migration_files_path); - init_device_model_db.initialize_database(schemas_path, false); - init_device_model_db.insert_config_and_default_values(schemas_path, config_path); + init_device_model_db.initialize_database(config_path, false); } db = std::make_unique(db_path); diff --git a/lib/ocpp/v201/init_device_model_db.cpp b/lib/ocpp/v201/init_device_model_db.cpp index f2b0989a4..8071f9254 100644 --- a/lib/ocpp/v201/init_device_model_db.cpp +++ b/lib/ocpp/v201/init_device_model_db.cpp @@ -10,15 +10,17 @@ #include -const static std::string STANDARDIZED_COMPONENT_SCHEMAS_DIR = "standardized"; -const static std::string CUSTOM_COMPONENT_SCHEMAS_DIR = "custom"; +const static std::string STANDARDIZED_COMPONENT_CONFIG_DIR = "standardized"; +const static std::string CUSTOM_COMPONENT_CONFIG_DIR = "custom"; + +// TODO mz change EverestEnvironmentOCPPConfiguration in everest_environment_setup.py in everest-utils +// TODO mz search for component_schemas and config_file etc to remove or change paths +// TODO mz should there be any changes in the types or interfaces? namespace ocpp::v201 { // Forward declarations. static bool is_same_component_key(const ComponentKey& component_key1, const ComponentKey& component_key2); -static bool is_same_variable_attribute_key(const VariableAttributeKey& attribute_key1, - const VariableAttributeKey& attribute_key2); static bool is_same_attribute_type(const VariableAttribute attribute1, const VariableAttribute& attribute2); static bool is_attribute_different(const VariableAttribute& attribute1, const VariableAttribute& attribute2); static bool variable_has_same_attributes(const std::vector& attributes1, @@ -27,14 +29,7 @@ static bool is_characteristics_different(const VariableCharacteristics& c1, cons static bool is_same_variable(const DeviceModelVariable& v1, const DeviceModelVariable& v2); static bool is_variable_different(const DeviceModelVariable& v1, const DeviceModelVariable& v2); static std::string get_string_value_from_json(const json& value); -static std::vector -check_config_integrity(const std::map>& database_components, - const std::map>& config); -static std::string check_config_variable_integrity(const std::vector& database_variables, - const VariableAttributeKey& config_attribute_key, - const ComponentKey& config_component); static std::string get_component_name_for_logging(const ComponentKey& component); -static std::string get_variable_name_for_logging(const VariableAttributeKey& variable); InitDeviceModelDb::InitDeviceModelDb(const std::filesystem::path& database_path, const std::filesystem::path& migration_files_path) : @@ -48,11 +43,10 @@ InitDeviceModelDb::~InitDeviceModelDb() { close_connection(); } -void InitDeviceModelDb::initialize_database(const std::filesystem::path& schemas_path, - bool delete_db_if_exists = true) { +void InitDeviceModelDb::initialize_database(const std::filesystem::path& config_path, bool delete_db_if_exists = true) { execute_init_sql(delete_db_if_exists); - // Get existing EVSE and Connector components from the database. + // Get existing components from the database. std::map> existing_components; DeviceModelMap device_model; if (this->database_exists) { @@ -60,97 +54,18 @@ void InitDeviceModelDb::initialize_database(const std::filesystem::path& schemas } // Get component schemas from the filesystem. - std::map> component_schemas = - get_all_component_schemas(schemas_path); + std::map> component_configs = get_all_component_configs(config_path); // Remove components from db if they do not exist in the component schemas if (this->database_exists) { - remove_not_existing_components_from_db(component_schemas, existing_components); + remove_not_existing_components_from_db(component_configs, existing_components); } // Starting a transaction makes this a lot faster (inserting all components takes a few seconds without it and a // few milliseconds if it is done inside a transaction). std::unique_ptr transaction = database->begin_transaction(); - insert_components(component_schemas, existing_components); - transaction->commit(); -} - -bool InitDeviceModelDb::insert_config_and_default_values(const std::filesystem::path& schemas_path, - const std::filesystem::path& config_path) { - bool success = true; - std::map> components = get_all_components_from_db(); - - std::map> default_values = - get_component_default_values(schemas_path); - std::map> config_values = get_config_values(config_path); - - const std::vector errors = check_config_integrity(components, config_values); - - if (!errors.empty()) { - const std::string output = std::accumulate(++errors.begin(), errors.end(), *errors.begin(), - [](auto& a, auto& b) { return a + "\n" + b; }); - EVLOG_AND_THROW( - InitDeviceModelDbError("Config not consistent with device model component schema's: \n" + output)); - } - - std::unique_ptr transaction = database->begin_transaction(); - for (const auto& component_variables : config_values) { - for (const VariableAttributeKey& attribute_key : component_variables.second) { - if (!insert_variable_attribute_value(component_variables.first, attribute_key, true)) { - success = false; - } - } - } - - for (const auto& component_variables : default_values) { - // Compare with config_values if the value is already added. If it is, don't add the default value, - // otherwise add the default value. - const auto& it = std::find_if( - config_values.begin(), config_values.end(), - [&component_variables](const std::pair> config_value) { - if (is_same_component_key(config_value.first, component_variables.first)) { - return true; - } - - return false; - }); - bool component_found = true; - std::vector config_attribute_keys; - if (it == config_values.end()) { - // Not found, add all default values of this component. - component_found = false; - } else { - config_attribute_keys = it->second; - } - - for (const VariableAttributeKey& attribute_key : component_variables.second) { - if (component_found) { - auto attribute_key_it = - std::find_if(config_attribute_keys.begin(), config_attribute_keys.end(), - [attribute_key](const VariableAttributeKey& config_attribute_key) { - if (is_same_variable_attribute_key(attribute_key, config_attribute_key)) { - return true; - } - return false; - }); - - if (attribute_key_it != config_attribute_keys.end()) { - // Attribute key is found in config, so we should not add a default value to the database. - continue; - } - } - - // Whole component is not found, or component is found but attribute is not found. Add default value to - // database. Do not warn if default value could not be set. - if (!insert_variable_attribute_value(component_variables.first, attribute_key, false)) { - success = false; - } - } - } - + insert_components(component_configs, existing_components); transaction->commit(); - - return success; } void InitDeviceModelDb::execute_init_sql(const bool delete_db_if_exists) { @@ -183,7 +98,7 @@ void InitDeviceModelDb::execute_init_sql(const bool delete_db_if_exists) { } std::vector -InitDeviceModelDb::get_component_schemas_from_directory(const std::filesystem::path& directory) { +InitDeviceModelDb::get_component_config_from_directory(const std::filesystem::path& directory) { std::vector component_schema_files; for (const auto& p : std::filesystem::directory_iterator(directory)) { if (p.path().extension() == ".json") { @@ -195,16 +110,16 @@ InitDeviceModelDb::get_component_schemas_from_directory(const std::filesystem::p } std::map> -InitDeviceModelDb::get_all_component_schemas(const std::filesystem::path& directory) { +InitDeviceModelDb::get_all_component_configs(const std::filesystem::path& directory) { const std::vector standardized_component_schema_files = - get_component_schemas_from_directory(directory / STANDARDIZED_COMPONENT_SCHEMAS_DIR); + get_component_config_from_directory(directory / STANDARDIZED_COMPONENT_CONFIG_DIR); const std::vector custom_component_schema_files = - get_component_schemas_from_directory(directory / CUSTOM_COMPONENT_SCHEMAS_DIR); + get_component_config_from_directory(directory / CUSTOM_COMPONENT_CONFIG_DIR); std::map> standardized_components_map = - read_component_schemas(standardized_component_schema_files); + read_component_config(standardized_component_schema_files); std::map> components = - read_component_schemas(custom_component_schema_files); + read_component_config(custom_component_schema_files); // Merge the two maps so they can be used for the insert_component function with a single iterator. This will use // the custom components map as base and add not existing standardized components to the components map. So if the @@ -225,7 +140,7 @@ void InitDeviceModelDb::insert_components( // Component exists in the database, update component if necessary. update_component_variables(component_db.value(), component.second); } else { - // Database is new or component is evse or connector and component does not exist. Insert component. + // Database is new or component does not exist. Insert component. insert_component(component.first, component.second); } } @@ -282,7 +197,7 @@ void InitDeviceModelDb::insert_component(const ComponentKey& component_key, } std::map> -InitDeviceModelDb::read_component_schemas(const std::vector& components_schema_path) { +InitDeviceModelDb::read_component_config(const std::vector& components_schema_path) { std::map> components; for (const std::filesystem::path& path : components_schema_path) { std::ifstream schema_file(path); @@ -466,7 +381,7 @@ void InitDeviceModelDb::insert_variable(const DeviceModelVariable& variable, con const int64_t variable_id = this->database->get_last_inserted_rowid(); insert_variable_characteristics(variable.characteristics, variable_id); - insert_attributes(variable.attributes, static_cast(variable_id)); + insert_attributes(variable.attributes, static_cast(variable_id), variable.default_actual_value); } void InitDeviceModelDb::update_variable(const DeviceModelVariable& variable, const DeviceModelVariable& db_variable, @@ -513,7 +428,8 @@ void InitDeviceModelDb::update_variable(const DeviceModelVariable& variable, con } if (!variable_has_same_attributes(variable.attributes, db_variable.attributes)) { - update_attributes(variable.attributes, db_variable.attributes, db_variable.db_id.value()); + update_attributes(variable.attributes, db_variable.attributes, db_variable.db_id.value(), + variable.default_actual_value); } } @@ -542,7 +458,8 @@ void InitDeviceModelDb::delete_variable(const DeviceModelVariable& variable) { } } -void InitDeviceModelDb::insert_attribute(const VariableAttribute& attribute, const uint64_t& variable_id) { +void InitDeviceModelDb::insert_attribute(const VariableAttribute& attribute, const uint64_t& variable_id, + const std::optional& default_actual_value) { static const std::string statement = "INSERT OR REPLACE INTO VARIABLE_ATTRIBUTE (VARIABLE_ID, MUTABILITY_ID, PERSISTENT, CONSTANT, TYPE_ID) " "VALUES(@variable_id, @mutability_id, @persistent, @constant, @type_id)"; @@ -571,18 +488,30 @@ void InitDeviceModelDb::insert_attribute(const VariableAttribute& attribute, con if (insert_attributes_statement->step() != SQLITE_DONE) { throw InitDeviceModelDbError("Could not insert attribute: " + std::string(this->database->get_error_message())); } + + const int64_t attribute_id = this->database->get_last_inserted_rowid(); + + if (attribute.value.has_value() || + (attribute.type.has_value() && (attribute.type.value() == AttributeEnum::Actual) && + default_actual_value.has_value())) { + insert_variable_attribute_value( + attribute_id, (attribute.value.has_value() ? attribute.value.value().get() : default_actual_value.value()), + true); + } } void InitDeviceModelDb::insert_attributes(const std::vector& attributes, - const uint64_t& variable_id) { + const uint64_t& variable_id, + const std::optional& default_actual_value) { for (const DbVariableAttribute& attribute : attributes) { - insert_attribute(attribute.variable_attribute, variable_id); + insert_attribute(attribute.variable_attribute, variable_id, default_actual_value); } } void InitDeviceModelDb::update_attributes(const std::vector& new_attributes, const std::vector& db_attributes, - const uint64_t& variable_id) { + const uint64_t& variable_id, + const std::optional& default_actual_value) { // First check if there are attributes in the database that are not in the config. They should be removed. for (const DbVariableAttribute& db_attribute : db_attributes) { const auto& it = std::find_if( @@ -604,16 +533,17 @@ void InitDeviceModelDb::update_attributes(const std::vector if (it == db_attributes.end()) { // Variable attribute does not exist in the db, add to db. - insert_attribute(new_attribute.variable_attribute, variable_id); + insert_attribute(new_attribute.variable_attribute, variable_id, default_actual_value); } else { if (is_attribute_different(new_attribute.variable_attribute, it->variable_attribute)) { - update_attribute(new_attribute.variable_attribute, *it); + update_attribute(new_attribute.variable_attribute, *it, default_actual_value); } } } } -void InitDeviceModelDb::update_attribute(const VariableAttribute& attribute, const DbVariableAttribute& db_attribute) { +void InitDeviceModelDb::update_attribute(const VariableAttribute& attribute, const DbVariableAttribute& db_attribute, + const std::optional& default_actual_value) { if (!db_attribute.db_id.has_value()) { EVLOG_error << "Can not update attribute: id not found"; return; @@ -666,6 +596,17 @@ void InitDeviceModelDb::update_attribute(const VariableAttribute& attribute, con EVLOG_error << "Could not update variable attribute: " << this->database->get_error_message(); throw InitDeviceModelDbError("Could not update attribute: " + std::string(this->database->get_error_message())); } + + if (attribute.value.has_value() || + (attribute.type.has_value() && (attribute.type.value() == AttributeEnum::Actual) && + default_actual_value.has_value())) { + if (!insert_variable_attribute_value( + static_cast(db_attribute.db_id.value()), + (attribute.value.has_value() ? attribute.value.value().get() : default_actual_value.value()), false)) { + EVLOG_error << "Can not update variable attribute (" << db_attribute.db_id.value() + << ") value: " << attribute.value.value(); + } + } } void InitDeviceModelDb::delete_attribute(const DbVariableAttribute& attribute) { @@ -690,73 +631,8 @@ void InitDeviceModelDb::delete_attribute(const DbVariableAttribute& attribute) { } } -std::map> -InitDeviceModelDb::get_component_default_values(const std::filesystem::path& schemas_path) { - std::map> components = get_all_component_schemas(schemas_path); - - std::map> component_default_values; - for (auto const& [componentKey, variables] : components) { - std::vector variable_attribute_keys; - for (const DeviceModelVariable& variable : variables) { - if (variable.default_actual_value.has_value()) { - VariableAttributeKey key; - key.name = variable.name; - if (variable.instance.has_value()) { - key.instance = variable.instance.value(); - } - key.attribute_type = AttributeEnum::Actual; - key.value = variable.default_actual_value.value(); - variable_attribute_keys.push_back(key); - } - } - - component_default_values.insert({componentKey, variable_attribute_keys}); - } - - return component_default_values; -} - -std::map> -InitDeviceModelDb::get_config_values(const std::filesystem::path& config_file_path) { - std::map> config_values; - std::ifstream config_file(config_file_path); - try { - json config_json = json::parse(config_file); - for (const auto& j : config_json.items()) { - ComponentKey p = j.value(); - std::vector attribute_keys; - for (const auto& variable : j.value().at("variables").items()) { - for (const auto& attributes : variable.value().at("attributes").items()) { - VariableAttributeKey key; - key.name = variable.value().at("variable_name"); - try { - key.attribute_type = conversions::string_to_attribute_enum(attributes.key()); - } catch (const std::out_of_range& /* e*/) { - EVLOG_error << "Could not find type " << attributes.key() << " of component " << p.name - << " and variable " << key.name; - throw InitDeviceModelDbError("Could not find type " + attributes.key() + " of component " + - p.name + " and variable " + key.name); - } - - key.value = get_string_value_from_json(attributes.value()); - if (variable.value().contains("instance")) { - key.instance = variable.value().at("instance"); - } - attribute_keys.push_back(key); - } - } - - config_values.insert({p, attribute_keys}); - } - return config_values; - } catch (const json::parse_error& e) { - EVLOG_error << "Error while parsing OCPP config file: " << config_file_path; - throw; - } -} - -bool InitDeviceModelDb::insert_variable_attribute_value(const ComponentKey& component_key, - const VariableAttributeKey& variable_attribute_key, +bool InitDeviceModelDb::insert_variable_attribute_value(const int64_t& variable_attribute_id, + const std::string& variable_attribute_value, const bool warn_source_not_default) { // Insert variable statement. // Use 'IS' when value can also be NULL @@ -764,17 +640,7 @@ bool InitDeviceModelDb::insert_variable_attribute_value(const ComponentKey& comp // we don't overwrite that. static const std::string statement = "UPDATE VARIABLE_ATTRIBUTE " "SET VALUE = @value, VALUE_SOURCE = 'default' " - "WHERE VARIABLE_ID = (" - "SELECT VARIABLE.ID " - "FROM VARIABLE " - "JOIN COMPONENT ON COMPONENT.ID = VARIABLE.COMPONENT_ID " - "WHERE COMPONENT.NAME = @component_name " - "AND COMPONENT.INSTANCE IS @component_instance " - "AND COMPONENT.EVSE_ID IS @evse_id " - "AND COMPONENT.CONNECTOR_ID IS @connector_id " - "AND VARIABLE.NAME = @variable_name " - "AND VARIABLE.INSTANCE IS @variable_instance) " - "AND TYPE_ID = @type_id " + "WHERE ID = @variable_attribute_id " "AND (VALUE_SOURCE = 'default' OR VALUE_SOURCE = '' OR VALUE_SOURCE IS NULL)"; std::unique_ptr insert_variable_attribute_statement; @@ -784,51 +650,18 @@ bool InitDeviceModelDb::insert_variable_attribute_value(const ComponentKey& comp throw InitDeviceModelDbError("Could not create statement " + statement); } - insert_variable_attribute_statement->bind_text("@value", variable_attribute_key.value, + insert_variable_attribute_statement->bind_int("@variable_attribute_id", + static_cast(variable_attribute_id)); + insert_variable_attribute_statement->bind_text("@value", variable_attribute_value, ocpp::common::SQLiteString::Transient); - insert_variable_attribute_statement->bind_text("@component_name", component_key.name, - ocpp::common::SQLiteString::Transient); - if (component_key.instance.has_value()) { - insert_variable_attribute_statement->bind_text("@component_instance", component_key.instance.value(), - ocpp::common::SQLiteString::Transient); - } else { - insert_variable_attribute_statement->bind_null("@component_instance"); - } - - if (component_key.evse_id.has_value()) { - insert_variable_attribute_statement->bind_int("@evse_id", component_key.evse_id.value()); - } else { - insert_variable_attribute_statement->bind_null("@evse_id"); - } - - if (component_key.connector_id.has_value()) { - insert_variable_attribute_statement->bind_int("@connector_id", component_key.connector_id.value()); - } else { - insert_variable_attribute_statement->bind_null("@connector_id"); - } - - insert_variable_attribute_statement->bind_text("@variable_name", variable_attribute_key.name, - ocpp::common::SQLiteString::Transient); - - if (variable_attribute_key.instance.has_value()) { - insert_variable_attribute_statement->bind_text("@variable_instance", variable_attribute_key.instance.value(), - ocpp::common::SQLiteString::Transient); - } else { - insert_variable_attribute_statement->bind_null("@variable_instance"); - } - - insert_variable_attribute_statement->bind_int("@type_id", static_cast(variable_attribute_key.attribute_type)); if (insert_variable_attribute_statement->step() != SQLITE_DONE) { - throw InitDeviceModelDbError("Could not set value of variable " + variable_attribute_key.name + - " (component: " + component_key.name + ") attribute " + - conversions::attribute_enum_to_string(variable_attribute_key.attribute_type) + - ": " + std::string(this->database->get_error_message())); + throw InitDeviceModelDbError("Could not set value '" + variable_attribute_value + + "' of variable attribute id " + std::to_string(variable_attribute_id) + ": " + + std::string(this->database->get_error_message())); } else if ((insert_variable_attribute_statement->changes() < 1) && warn_source_not_default) { - EVLOG_debug << "Could not set value of variable " + get_variable_name_for_logging(variable_attribute_key) + - " (Component: " + get_component_name_for_logging(component_key) + ") attribute " + - conversions::attribute_enum_to_string(variable_attribute_key.attribute_type) + - ": value has already changed by other source"; + EVLOG_debug << "Could not set value '" + variable_attribute_value + "' of variable attribute id " + + std::to_string(variable_attribute_id) + ": value has already changed by other source"; } return true; @@ -940,7 +773,7 @@ std::map> InitDeviceModelDb::get_ } if (status != SQLITE_DONE) { - throw InitDeviceModelDbError("Could not get all connector and evse components from the database: " + + throw InitDeviceModelDbError("Could not get all components from the database: " + std::string(this->database->get_error_message())); } @@ -971,10 +804,10 @@ bool InitDeviceModelDb::component_exists_in_schemas( } void InitDeviceModelDb::remove_not_existing_components_from_db( - const std::map>& component_schemas, + const std::map>& component_config, const std::map>& db_components) { for (const auto& component : db_components) { - if (!component_exists_in_schemas(component_schemas, component.first)) { + if (!component_exists_in_schemas(component_config, component.first)) { remove_component_from_db(component.first); } } @@ -1161,30 +994,12 @@ void from_json(const json& j, DeviceModelVariable& c) { // I want the default value as string here as it is stored in the db as a string as well. const json& default_value = j.at("default"); c.default_actual_value = get_string_value_from_json(default_value); - if (default_value.is_string()) { - c.default_actual_value = default_value; - } else if (default_value.is_boolean()) { - if (default_value.get()) { - // Convert to lower case if that is not the case currently. - c.default_actual_value = "true"; - } else { - // Convert to lower case if that is not the case currently. - c.default_actual_value = "false"; - } - } else if (default_value.is_array() || default_value.is_object()) { - EVLOG_warning << "Trying to get default value of variable " << c.name - << " from json, but value is array or object: " << default_value.dump(); - // Maybe this is correct and is just a string (json value string), so just return the string. - c.default_actual_value = default_value.dump(); - } else { - c.default_actual_value = default_value.dump(); - } } } -/* Below functions check if components, attributes, variables, characteristics are the same / equal in the schema and - * database. The 'is_same' functions check if two objects are the same, comparing their unique properties. - * The is_..._different functions check if the objects properties are different (and as a result should be changed in +/* Below functions check if components, attributes, variables, characteristics are the same / equal in the schema + * and database. The 'is_same' functions check if two objects are the same, comparing their unique properties. The + * is_..._different functions check if the objects properties are different (and as a result should be changed in * the database). */ @@ -1206,25 +1021,6 @@ static bool is_same_component_key(const ComponentKey& component_key1, const Comp return false; } -/// -/// \brief Check if the variable attribute is the same given their unique properties (type, variable instance and -/// variable name) -/// \param attribute_key1 Attribute key 1 -/// \param attribute_key2 Attribute key 2 -/// \return True if they are the same. -/// -static bool is_same_variable_attribute_key(const VariableAttributeKey& attribute_key1, - const VariableAttributeKey& attribute_key2) { - if ((attribute_key1.attribute_type == attribute_key2.attribute_type) && - (attribute_key1.instance == attribute_key2.instance) && (attribute_key1.name == attribute_key2.name)) { - // We did not compare the 'value' here as we want to check if the attribute is the same and not the value of the - // attribute. - return true; - } - - return false; -} - /// /// \brief Check if the two given attributes are the same given their unique properties (type) /// \param attribute1 Attribute 1 @@ -1247,14 +1043,16 @@ static bool is_same_attribute_type(const VariableAttribute attribute1, const Var static bool is_attribute_different(const VariableAttribute& attribute1, const VariableAttribute& attribute2) { // Constant and persistent are currently not set in the json file. if ((attribute1.type == attribute2.type) && /*(attribute1.constant == attribute2.constant) &&*/ - (attribute1.mutability == attribute2.mutability) /* && (attribute1.persistent == attribute2.persistent)*/) { + (attribute1.mutability == attribute2.mutability) && (attribute1.value == attribute2.value) + /* && (attribute1.persistent == attribute2.persistent)*/) { return false; } return true; } /// -/// \brief Check if a variable has the same attributes, or if there is for example an extra attribute added, removed or +/// \brief Check if a variable has the same attributes, or if there is for example an extra attribute added, removed +/// or /// changed. /// \param attributes1 Attributes 1 /// \param attributes2 Attributes 2 @@ -1345,90 +1143,10 @@ static std::string get_string_value_from_json(const json& value) { } else if (value.is_array() || value.is_object()) { EVLOG_warning << "String value " << value.dump() << " from config is an object or array, but config values should be from a primitive type."; - return ""; - } else { + // TODO mz throw here or is this ok? return value.dump(); - } -} - -/// -/// \brief Check if the config is correct compared with the database. -/// \param database_components The components from the database. -/// \param config The configuration. -/// \return A list of components / variables / attributes that have errors, or an empty vector if there are none. -/// -static std::vector -check_config_integrity(const std::map>& database_components, - const std::map>& config) { - std::vector errors; - // Loop over all components from the configuration files and compare it with components from the database. - for (const auto& [config_component, config_variable_attributes] : config) { - bool component_found = false; - // Loop over database components to check if the component in the config exists and if so, check the - // variable and attribute that needs to be changed. - for (const auto& [database_component, database_variables] : database_components) { - if (is_same_component_key(config_component, database_component)) { - component_found = true; - // The component is found. Now compoare all variables of this component with the variables of the - // component in the database. So loop over the config variables. - for (const VariableAttributeKey& config_attribute_key : config_variable_attributes) { - // And find the same variable in the database components variable list. - const std::string error = - check_config_variable_integrity(database_variables, config_attribute_key, config_component); - if (!error.empty()) { - errors.push_back(error); - } - } - } - } - - if (!component_found) { - errors.push_back("Component: " + get_component_name_for_logging(config_component)); - } - } - - return errors; -} - -/// -/// \brief Check if config variable attribute (of a component) is correct compared with the database. -/// \param database_variables Variable from the database -/// \param config_attribute_key Configuration variable / attribute combination -/// \param config_component Config component (only used for logging) -/// \return The component / variable / attribute string if there is an error, otherwise an empty string. -/// -static std::string check_config_variable_integrity(const std::vector& database_variables, - const VariableAttributeKey& config_attribute_key, - const ComponentKey& config_component) { - const auto& it_db_variables = std::find_if( - database_variables.begin(), database_variables.end(), [&config_attribute_key](const DeviceModelVariable& v) { - if (v.name == config_attribute_key.name && v.instance == config_attribute_key.instance) { - return true; - } - return false; - }); - if (it_db_variables != database_variables.end()) { - // Variable is found! - // Now the variable is found, check the attribute whose value needs to change. Loop over all - // database attributes to check if it is the same attribute is the one from the config. - const auto& it_db_attributes = - std::find_if(it_db_variables->attributes.begin(), it_db_variables->attributes.end(), - [&config_attribute_key](const DbVariableAttribute& attribute) { - return (attribute.variable_attribute.type == config_attribute_key.attribute_type); - }); - if (it_db_attributes != it_db_variables->attributes.end()) { - // Attribute is found! No need to search any further. - return ""; - } else { - // Attribute not found. - return "Attribute: " + conversions::attribute_enum_to_string(config_attribute_key.attribute_type) + - " (of Component: " + get_component_name_for_logging(config_component) + - " and Variable: " + get_variable_name_for_logging(config_attribute_key) + ")"; - } } else { - // Variable not found. - return "Variable: " + get_variable_name_for_logging(config_attribute_key) + - " (of Component: " + get_component_name_for_logging(config_component) + ")"; + return value.dump(); } } @@ -1449,19 +1167,4 @@ static std::string get_component_name_for_logging(const ComponentKey& component) return component_name; } -/// -/// \brief Get a string that describes the variable, used for logging. -/// -/// This includes the name and the instance of the variable -/// -/// \param variable The variable to get the string from. -/// \return The logging string. -/// - -static std::string get_variable_name_for_logging(const VariableAttributeKey& variable) { - const std::string variable_name = - variable.name + (variable.instance.has_value() ? ", instance " + variable.instance.value() : ""); - return variable_name; -} - } // namespace ocpp::v201 diff --git a/lib/ocpp/v201/ocpp_types.cpp b/lib/ocpp/v201/ocpp_types.cpp index f00f48225..534bfe05f 100644 --- a/lib/ocpp/v201/ocpp_types.cpp +++ b/lib/ocpp/v201/ocpp_types.cpp @@ -1864,9 +1864,29 @@ void from_json(const json& j, VariableAttribute& k) { if (j.contains("type")) { k.type.emplace(conversions::string_to_attribute_enum(j.at("type"))); } + + // TODO mz change this in the generator (if everyone agrees)!! if (j.contains("value")) { - k.value.emplace(j.at("value")); + const json& value = j.at("value"); + if (value.is_string()) { + k.value = value; + } else if (value.is_boolean()) { + if (value.get()) { + // Convert to lower case if that is not the case currently. + k.value = "true"; + } else { + // Convert to lower case if that is not the case currently. + k.value = "false"; + } + } else if (value.is_array() || value.is_object()) { + // TODO mz throw here or is this ok? + // Maybe this is correct and is just a string (json value string), so just return the string. + k.value = value.dump(); + } else { + k.value = value.dump(); + } } + if (j.contains("mutability")) { k.mutability.emplace(conversions::string_to_mutability_enum(j.at("mutability"))); } diff --git a/src/code_generator/README.md b/src/code_generator/README.md index 83d8e1c85..efdadd6a9 100644 --- a/src/code_generator/README.md +++ b/src/code_generator/README.md @@ -19,18 +19,18 @@ python3 generate_cpp.py --schemas ~/ocpp-schemas/v201/ --out ~/checkout/everest- ``` ## JSON schema generator for v201 component schemas -The script [generate_component_schemas.py](v201/generate_component_schemas.py) generates component schemas for v201 based on -a modified version of the dm_component_vars.csv appendix of the OCPP2.0.1 specification. These component schema files can then +The script [generate_component_config.py](v201/generate_component_config.py) generates component config files for v201 based on +a modified version of the dm_component_vars.csv appendix of the OCPP2.0.1 specification. These component config files can then be used to initialize the device model storage database. ```bash -python3 generate_component_schemas.py --csv --out +python3 generate_component_config.py --csv --out ``` e.g. ```bash -python3 generate_component_schemas.py --csv ~/ocpp-v201-specification/appendix/dm_component_vars.csv --out ~/checkout/everest-workspace/libocpp/config/v201/component_schemas/standardized +python3 generate_component_config.py --csv ~/ocpp-v201-specification/appendix/dm_component_vars.csv --out ~/checkout/everest-workspace/libocpp/config/v201/component_config/standardized ``` ## C++ Code generator for ControllerComponentVariables @@ -40,7 +40,7 @@ These files provide access to ComponentVariables with a role standardized in the ```bash python3 generate_ctrlr_component_vars.py --csv --out ``` -component_schemas/standardized +component_config/standardized e.g. ```bash @@ -58,5 +58,5 @@ python3 generate_ctrlr_component_vars.py --schemas sqlite3.Cursor: - con = sqlite3.connect(db_file) - cur = con.cursor() - try: - yield cur - cur.close() - finally: - con.close() - - def _read_table(self, db_file: Path, table: str): - with self._connect(db_file) as cur: - query = f"SELECT * FROM {table}" # nosec - cur.execute(query) - rows = cur.fetchall() - - # Get column names - col_names = [description[0] for description in cur.description] - row_dicts = [] - for row in rows: - row_dict = {col_name: value for col_name, value in zip(col_names, row)} - row_dicts.append(row_dict) - return row_dicts - - def _assert_database_tables_as_expected(self, db_file): - assert self._read_table(db_file, "VARIABLE") == [{'COMPONENT_ID': 1, - 'ID': 1, - 'INSTANCE': None, - 'NAME': 'UnitTestPropertyAName', - 'REQUIRED': 1, - 'VARIABLE_CHARACTERISTICS_ID': 1}, - {'COMPONENT_ID': 1, - 'ID': 2, - 'INSTANCE': None, - 'NAME': 'UnitTestPropertyBName', - 'REQUIRED': 0, - 'VARIABLE_CHARACTERISTICS_ID': 2}, - {'COMPONENT_ID': 1, - 'ID': 3, - 'INSTANCE': None, - 'NAME': 'UnitTestPropertyCName', - 'REQUIRED': 0, - 'VARIABLE_CHARACTERISTICS_ID': 3}] - assert self._read_table(db_file, "VARIABLE_MONITORING") == [] - assert self._read_table(db_file, "VARIABLE_CHARACTERISTICS") == [{'DATATYPE_ID': 4, - 'ID': 1, - 'MAX_LIMIT': None, - 'MIN_LIMIT': None, - 'SUPPORTS_MONITORING': 1, - 'UNIT': None, - 'VALUES_LIST': None}, - {'DATATYPE_ID': 0, - 'ID': 2, - 'MAX_LIMIT': None, - 'MIN_LIMIT': None, - 'SUPPORTS_MONITORING': 0, - 'UNIT': None, - 'VALUES_LIST': None}, - {'DATATYPE_ID': None, - 'ID': 3, - 'MAX_LIMIT': None, - 'MIN_LIMIT': None, - 'SUPPORTS_MONITORING': 0, - 'UNIT': None, - 'VALUES_LIST': None}] - - assert self._read_table(db_file, "VARIABLE_ATTRIBUTE_TYPE") == [{'ID': 0, 'TYPE': 'Actual'}, - {'ID': 1, 'TYPE': 'Target'}, - {'ID': 2, 'TYPE': 'MinSet'}, - {'ID': 3, 'TYPE': 'MaxSet'}] - assert self._read_table(db_file, "COMPONENT") == [{'CONNECTOR_ID': 3, - 'EVSE_ID': 2, - 'ID': 1, - 'INSTANCE': None, - 'NAME': 'UnitTestCtrlr'}] - assert self._read_table(db_file, "SEVERITY") == [{'ID': 0, 'SEVERITY': 'Danger'}, - {'ID': 1, 'SEVERITY': 'HardwareFailure'}, - {'ID': 2, 'SEVERITY': 'SystemFailure'}, - {'ID': 3, 'SEVERITY': 'Critical'}, - {'ID': 4, 'SEVERITY': 'Error'}, - {'ID': 5, 'SEVERITY': 'Alert'}, - {'ID': 6, 'SEVERITY': 'Warning'}, - {'ID': 7, 'SEVERITY': 'Notice'}, - {'ID': 8, 'SEVERITY': 'Informational'}, - {'ID': 9, 'SEVERITY': 'Debug'}] - assert self._read_table(db_file, "MONITOR") == [{'ID': 0, 'TYPE': 'UpperThreshold'}, - {'ID': 1, 'TYPE': 'LowerThreshold'}, - {'ID': 2, 'TYPE': 'Delta'}, - {'ID': 3, 'TYPE': 'Periodic'}, - {'ID': 4, 'TYPE': 'PeriodicClockAligned'}] - assert self._read_table(db_file, "DATATYPE") == [{'DATATYPE': 'string', 'ID': 0}, - {'DATATYPE': 'decimal', 'ID': 1}, - {'DATATYPE': 'integer', 'ID': 2}, - {'DATATYPE': 'dateTime', 'ID': 3}, - {'DATATYPE': 'boolean', 'ID': 4}, - {'DATATYPE': 'OptionList', 'ID': 5}, - {'DATATYPE': 'SequenceList', 'ID': 6}, - {'DATATYPE': 'MemberList', 'ID': 7}] - assert self._read_table(db_file, "MUTABILITY") == [{'ID': 0, 'MUTABILITY': 'ReadOnly'}, - {'ID': 1, 'MUTABILITY': 'WriteOnly'}, - {'ID': 2, 'MUTABILITY': 'ReadWrite'}] - - def test_init(self, db_file): - database_initializer = DeviceModelDatabaseInitializer(db_file) - - schema_base = Path(__file__).parent / "resources" / "component_schemas" - database_initializer.initialize_database(schema_base) - - self._assert_database_tables_as_expected(db_file) - - assert self._read_table(db_file, "VARIABLE_ATTRIBUTE") == [{'CONSTANT': 0, - 'ID': 1, - 'MUTABILITY_ID': 2, - 'PERSISTENT': 1, - 'TYPE_ID': 0, - 'VALUE': None, - 'VARIABLE_ID': 1}, - {'CONSTANT': 0, - 'ID': 2, - 'MUTABILITY_ID': 0, - 'PERSISTENT': 1, - 'TYPE_ID': 0, - 'VALUE': None, - 'VARIABLE_ID': 2}, - {'CONSTANT': 0, - 'ID': 3, - 'MUTABILITY_ID': 0, - 'PERSISTENT': 1, - 'TYPE_ID': 0, - 'VALUE': None, - 'VARIABLE_ID': 3}] - - def test_insert(self, db_file): - - database_initializer = DeviceModelDatabaseInitializer(db_file) - - schema_base = Path(__file__).parent / "resources" / "component_schemas" - database_initializer.initialize_database(schema_base) - - database_initializer.insert_config_and_default_values(Path(__file__).parent / "resources/config.json", - schema_base) - - self._assert_database_tables_as_expected(db_file) - - assert self._read_table(db_file, "VARIABLE_ATTRIBUTE") == [{'CONSTANT': 0, - 'ID': 1, - 'MUTABILITY_ID': 2, - 'PERSISTENT': 1, - 'TYPE_ID': 0, - 'VALUE': "1", # default value - 'VARIABLE_ID': 1}, - {'CONSTANT': 0, - 'ID': 2, - 'MUTABILITY_ID': 0, - 'PERSISTENT': 1, - 'TYPE_ID': 0, - 'VALUE': "test_value", - 'VARIABLE_ID': 2}, - {'CONSTANT': 0, - 'ID': 3, - 'MUTABILITY_ID': 0, - 'PERSISTENT': 1, - 'TYPE_ID': 0, - 'VALUE': None, - 'VARIABLE_ID': 3}] diff --git a/tests/lib/ocpp/v201/test_init_device_model_db.cpp b/tests/lib/ocpp/v201/test_init_device_model_db.cpp index 87225b4cd..e424458ac 100644 --- a/tests/lib/ocpp/v201/test_init_device_model_db.cpp +++ b/tests/lib/ocpp/v201/test_init_device_model_db.cpp @@ -13,22 +13,17 @@ #include +// TODO mz add removed tests with config: add component config for this and check if they also fail +// TODO mz remove config.json for tests: not needed anymore + namespace ocpp::v201 { class InitDeviceModelDbTest : public DatabaseTestingUtils { protected: const std::string DATABASE_PATH = "file::memory:?cache=shared"; const std::string MIGRATION_FILES_PATH = "./resources/v201/device_model_migration_files"; - const std::string SCHEMAS_PATH = "./resources/config/v201/component_schemas"; - const std::string SCHEMAS_PATH_CHANGED = "./resources/config/v201/changed/component_schemas"; - const std::string CONFIG_PATH = "./resources/config/v201/config.json"; - const std::string CONFIG_PATH_CHANGED = "./resources/config/v201/changed/config.json"; - const std::string CONFIG_PATH_WRONG_ATTRIBUTE = "./resources/config/v201/config_wrong_attribute.json"; - const std::string CONFIG_PATH_NOT_EXISTING_ATTRIBUTE = "./resources/config/v201/config_not_existing_attribute.json"; - const std::string CONFIG_PATH_WRONG_COMPONENT = "./resources/config/v201/config_wrong_component.json"; - const std::string CONFIG_PATH_WRONG_COMPONENT_CONNECTORID = - "./resources/config/v201/config_wrong_component_connectorid.json"; - const std::string CONFIG_PATH_WRONG_VARIABLE = "./resources/config/v201/config_wrong_variable.json"; + const std::string SCHEMAS_PATH = "./resources/config/v201/component_config"; + const std::string SCHEMAS_PATH_CHANGED = "./resources/config/v201/changed/component_config"; public: InitDeviceModelDbTest() { @@ -193,7 +188,7 @@ TEST_F(InitDeviceModelDbTest, init_db) { // Database should not exist yet. But since it does a filesystem check and we have an in memory database, we // explicitly set the variable here. db.database_exists = false; - EXPECT_NO_THROW(db.initialize_database(std::filesystem::path(SCHEMAS_PATH), true)); + ASSERT_NO_THROW(db.initialize_database(std::filesystem::path(SCHEMAS_PATH), true)); // Tables should have been created now. EXPECT_TRUE(check_all_tables_exist({"COMPONENT", "VARIABLE", "DATATYPE", "MONITOR", "MUTABILITY", "SEVERITY", @@ -252,13 +247,52 @@ TEST_F(InitDeviceModelDbTest, init_db) { EXPECT_TRUE(variable_exists("UnitTestCtrlr", std::nullopt, 2, 3, "UnitTestPropertyBName", std::nullopt)); EXPECT_TRUE(variable_exists("UnitTestCtrlr", std::nullopt, 2, 3, "UnitTestPropertyCName", std::nullopt)); + // Test some values. + EXPECT_TRUE(attribute_has_value("UnitTestCtrlr", std::nullopt, 2, 3, "UnitTestPropertyBName", std::nullopt, + AttributeEnum::Actual, "test_value")); + // Test some not default values. + EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "Available", std::nullopt, + AttributeEnum::Actual, "false")); + EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "Power", std::nullopt, AttributeEnum::MaxSet, + "44000")); + EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "Power", std::nullopt, AttributeEnum::Actual, + "2000")); + EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "SupplyPhases", std::nullopt, + AttributeEnum::Actual, "6")); + EXPECT_TRUE( + attribute_has_value("Connector", std::nullopt, 2, 1, "Available", std::nullopt, AttributeEnum::Actual, "true")); + EXPECT_TRUE(attribute_has_value("Connector", std::nullopt, 2, 1, "ConnectorType", std::nullopt, + AttributeEnum::Actual, "cChaoJi")); + EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "Available", std::nullopt, + AttributeEnum::Actual, "false")); + EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 2, std::nullopt, "Available", std::nullopt, + AttributeEnum::Actual, "true")); + EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 2, std::nullopt, "Power", std::nullopt, AttributeEnum::MaxSet, + "22000")); + EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 2, std::nullopt, "AvailabilityState", std::nullopt, + AttributeEnum::Actual, "Faulted")); + EXPECT_TRUE(attribute_has_value("Connector", std::nullopt, 1, 1, "ConnectorType", std::nullopt, + AttributeEnum::Actual, "cGBT")); + + // Default value + EXPECT_TRUE(attribute_has_value("Connector", std::nullopt, 1, 1, "Available", std::nullopt, AttributeEnum::Actual, + "false")); + EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "AvailabilityState", std::nullopt, + AttributeEnum::Actual, "Unavailable")); + EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 2, std::nullopt, "SupplyPhases", std::nullopt, + AttributeEnum::Actual, "0")); + // So now we have made some changes and added a new EVSE and changed the connector. The database should be changed // accordingly. + + // First set the source of an attribute to something else than 'default' + set_attribute_source("Connector", std::nullopt, 1, 1, "ConnectorType", std::nullopt, AttributeEnum::Actual, "test"); + InitDeviceModelDb db2 = InitDeviceModelDb(DATABASE_PATH, MIGRATION_FILES_PATH); // This time, the database does exist (again: std::filesystem::exists, which is automatically used, will not work // here because we use an in memory database, so we set the member ourselves). db2.database_exists = true; - EXPECT_NO_THROW(db2.initialize_database(SCHEMAS_PATH_CHANGED, false)); + ASSERT_NO_THROW(db2.initialize_database(SCHEMAS_PATH_CHANGED, false)); // So now some records should have been changed ! EXPECT_TRUE(attribute_exists("EVSE", std::nullopt, 1, std::nullopt, "AllowReset", std::nullopt, @@ -351,67 +385,10 @@ TEST_F(InitDeviceModelDbTest, init_db) { // Removed UnitTestPropertyCName EXPECT_TRUE(variable_exists("UnitTestCtrlr", std::nullopt, 2, 3, "UnitTestPropertyBName", std::nullopt)); EXPECT_FALSE(variable_exists("UnitTestCtrlr", std::nullopt, 2, 3, "UnitTestPropertyCName", std::nullopt)); -} - -TEST_F(InitDeviceModelDbTest, insert_values) { - /* This test will test if the config and default values are correctly set. We test this twice: first an initial - * config, then a changed configuration. - */ - - InitDeviceModelDb db(DATABASE_PATH, MIGRATION_FILES_PATH); - - // Database should not exist yet. But since it does a filesystem check and we have an in memory database, we - // explicitly set the variable here. - db.database_exists = false; - // First create the database. - EXPECT_NO_THROW(db.initialize_database(SCHEMAS_PATH, true)); - // Then insert the config and default values. - EXPECT_TRUE(db.insert_config_and_default_values(SCHEMAS_PATH, CONFIG_PATH)); - - // Test some values. - EXPECT_TRUE(attribute_has_value("UnitTestCtrlr", std::nullopt, 2, 3, "UnitTestPropertyBName", std::nullopt, - AttributeEnum::Actual, "test_value")); - // Test some not default values. - EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "Available", std::nullopt, - AttributeEnum::Actual, "false")); - EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "Power", std::nullopt, AttributeEnum::MaxSet, - "44000")); - EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "Power", std::nullopt, AttributeEnum::Actual, - "2000")); - EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "SupplyPhases", std::nullopt, - AttributeEnum::Actual, "6")); - EXPECT_TRUE( - attribute_has_value("Connector", std::nullopt, 2, 1, "Available", std::nullopt, AttributeEnum::Actual, "true")); - EXPECT_TRUE(attribute_has_value("Connector", std::nullopt, 2, 1, "ConnectorType", std::nullopt, - AttributeEnum::Actual, "cChaoJi")); - EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "Available", std::nullopt, - AttributeEnum::Actual, "false")); - EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 2, std::nullopt, "Available", std::nullopt, - AttributeEnum::Actual, "true")); - EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 2, std::nullopt, "Power", std::nullopt, AttributeEnum::MaxSet, - "22000")); - EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 2, std::nullopt, "AvailabilityState", std::nullopt, - AttributeEnum::Actual, "Faulted")); - - // Default value - EXPECT_TRUE(attribute_has_value("Connector", std::nullopt, 1, 1, "Available", std::nullopt, AttributeEnum::Actual, - "false")); - EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "AvailabilityState", std::nullopt, - AttributeEnum::Actual, "Unavailable")); - EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 2, std::nullopt, "SupplyPhases", std::nullopt, - AttributeEnum::Actual, "0")); - EXPECT_TRUE( - attribute_has_value("Connector", std::nullopt, 1, 1, "ConnectorType", std::nullopt, AttributeEnum::Actual, "")); - - // Insert new config. - // First set the source of an attribute to something else than 'default' - set_attribute_source("Connector", std::nullopt, 2, 1, "ConnectorType", std::nullopt, AttributeEnum::Actual, "test"); - - EXPECT_TRUE(db.insert_config_and_default_values(SCHEMAS_PATH, CONFIG_PATH_CHANGED)); // Source was not 'default', connector type not changed. - EXPECT_TRUE(attribute_has_value("Connector", std::nullopt, 2, 1, "ConnectorType", std::nullopt, - AttributeEnum::Actual, "cChaoJi")); + EXPECT_TRUE(attribute_has_value("Connector", std::nullopt, 1, 1, "ConnectorType", std::nullopt, + AttributeEnum::Actual, "cGBT")); // Check changed values. EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 2, std::nullopt, "Available", std::nullopt, @@ -430,6 +407,92 @@ TEST_F(InitDeviceModelDbTest, insert_values) { // EXPECT_FALSE(component_exists("UnitTestCtrlr", std::nullopt, 1, 5)); } +// TEST_F(InitDeviceModelDbTest, insert_values) { +// /* This test will test if the config and default values are correctly set. We test this twice: first an initial +// * config, then a changed configuration. +// */ + +// InitDeviceModelDb db(DATABASE_PATH, MIGRATION_FILES_PATH); + +// // Database should not exist yet. But since it does a filesystem check and we have an in memory database, we +// // explicitly set the variable here. +// db.database_exists = false; +// // First create the database. +// EXPECT_NO_THROW(db.initialize_database(SCHEMAS_PATH, true)); +// // Then insert the config and default values. +// EXPECT_TRUE(db.insert_config_and_default_values(SCHEMAS_PATH, CONFIG_PATH)); + +// // Test some values. +// EXPECT_TRUE(attribute_has_value("UnitTestCtrlr", std::nullopt, 2, 3, "UnitTestPropertyBName", std::nullopt, +// AttributeEnum::Actual, "test_value")); +// // Test some not default values. +// EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "Available", std::nullopt, +// AttributeEnum::Actual, "false")); +// EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "Power", std::nullopt, +// AttributeEnum::MaxSet, +// "44000")); +// EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "Power", std::nullopt, +// AttributeEnum::Actual, +// "2000")); +// EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "SupplyPhases", std::nullopt, +// AttributeEnum::Actual, "6")); +// EXPECT_TRUE( +// attribute_has_value("Connector", std::nullopt, 2, 1, "Available", std::nullopt, AttributeEnum::Actual, +// "true")); +// EXPECT_TRUE(attribute_has_value("Connector", std::nullopt, 2, 1, "ConnectorType", std::nullopt, +// AttributeEnum::Actual, "cChaoJi")); +// EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "Available", std::nullopt, +// AttributeEnum::Actual, "false")); +// EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 2, std::nullopt, "Available", std::nullopt, +// AttributeEnum::Actual, "true")); +// EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 2, std::nullopt, "Power", std::nullopt, +// AttributeEnum::MaxSet, +// "22000")); +// EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 2, std::nullopt, "AvailabilityState", std::nullopt, +// AttributeEnum::Actual, "Faulted")); + +// // Default value +// EXPECT_TRUE(attribute_has_value("Connector", std::nullopt, 1, 1, "Available", std::nullopt, +// AttributeEnum::Actual, +// "false")); +// EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "AvailabilityState", std::nullopt, +// AttributeEnum::Actual, "Unavailable")); +// EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 2, std::nullopt, "SupplyPhases", std::nullopt, +// AttributeEnum::Actual, "0")); +// EXPECT_TRUE( +// attribute_has_value("Connector", std::nullopt, 1, 1, "ConnectorType", std::nullopt, AttributeEnum::Actual, +// "")); + +// // Insert new config. +// // First set the source of an attribute to something else than 'default' +// set_attribute_source("Connector", std::nullopt, 2, 1, "ConnectorType", std::nullopt, AttributeEnum::Actual, +// "test"); + +// EXPECT_TRUE(db.insert_config_and_default_values(SCHEMAS_PATH, CONFIG_PATH_CHANGED)); + +// // Source was not 'default', connector type not changed. +// EXPECT_TRUE(attribute_has_value("Connector", std::nullopt, 2, 1, "ConnectorType", std::nullopt, +// AttributeEnum::Actual, "cChaoJi")); + +// // Check changed values. +// EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 2, std::nullopt, "Available", std::nullopt, +// AttributeEnum::Actual, "false")); +// EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "SupplyPhases", std::nullopt, +// AttributeEnum::Actual, "2")); +// // // Variable does not exist so it could not set the value. +// // EXPECT_FALSE(variable_exists("EVSE", std::nullopt, 1, std::nullopt, "AvalableEVSEThingie", std::nullopt)); +// // Variable was removed, so it will be set to the default value again. +// EXPECT_TRUE( +// attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "Power", std::nullopt, AttributeEnum::Actual, +// "0")); +// // Default value only applies to 'Actual', not 'MaxSet' +// EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "Power", std::nullopt, +// AttributeEnum::MaxSet, +// "44000")); +// // // Component does not exist so it could not set anything. +// // EXPECT_FALSE(component_exists("UnitTestCtrlr", std::nullopt, 1, 5)); +// } + TEST_F(InitDeviceModelDbTest, wrong_migration_file_path) { InitDeviceModelDb db(DATABASE_PATH, "/tmp/thisdoesnotexisthopefully"); // The migration script is not correct (there is none in the given folder), this should throw an exception. @@ -442,75 +505,12 @@ TEST_F(InitDeviceModelDbTest, wrong_schemas_path) { EXPECT_THROW(db.initialize_database("/tmp/thisdoesnotexisthopefully", true), std::filesystem::filesystem_error); } -TEST_F(InitDeviceModelDbTest, wrong_schemas_path2) { - // Wrong schemas path to insert config and default values. - InitDeviceModelDb db(DATABASE_PATH, MIGRATION_FILES_PATH); - db.initialize_database(SCHEMAS_PATH, true); - EXPECT_THROW(db.insert_config_and_default_values("/tmp/wrongschemaspath", CONFIG_PATH), - std::filesystem::filesystem_error); -} - -TEST_F(InitDeviceModelDbTest, wrong_config_path) { - // Wrong config file path - InitDeviceModelDb db(DATABASE_PATH, MIGRATION_FILES_PATH); - EXPECT_NO_THROW(db.initialize_database(SCHEMAS_PATH, true)); - EXPECT_THROW(db.insert_config_and_default_values(SCHEMAS_PATH, "/tmp/wrongconfigpath"), - nlohmann::detail::parse_error); -} - -TEST_F(InitDeviceModelDbTest, no_initialization) { - // Try to insert config and default values while the schemas are not inserted yet. - InitDeviceModelDb db(DATABASE_PATH, MIGRATION_FILES_PATH); - EXPECT_THROW(db.insert_config_and_default_values(SCHEMAS_PATH, CONFIG_PATH), InitDeviceModelDbError); -} - -TEST_F(InitDeviceModelDbTest, config_wrong_attribute) { - // Try to insert attribute that is not existing (not one of 'Actual', 'MinSet', 'MaxSet' or 'Target') - InitDeviceModelDb db(DATABASE_PATH, MIGRATION_FILES_PATH); - EXPECT_NO_THROW(db.initialize_database(SCHEMAS_PATH, true)); - EXPECT_THROW(db.insert_config_and_default_values(SCHEMAS_PATH, CONFIG_PATH_WRONG_ATTRIBUTE), - InitDeviceModelDbError); -} - -TEST_F(InitDeviceModelDbTest, config_not_existing_attribute) { - // Try to insert attribute that is not set in the component schema. - InitDeviceModelDb db(DATABASE_PATH, MIGRATION_FILES_PATH); - EXPECT_NO_THROW(db.initialize_database(SCHEMAS_PATH, true)); - EXPECT_THROW(db.insert_config_and_default_values(SCHEMAS_PATH, CONFIG_PATH_NOT_EXISTING_ATTRIBUTE), - InitDeviceModelDbError); -} - -TEST_F(InitDeviceModelDbTest, config_wrong_component) { - // Try to set value of attribute of component that does not exist in the component schema. - InitDeviceModelDb db(DATABASE_PATH, MIGRATION_FILES_PATH); - db.initialize_database(SCHEMAS_PATH, true); - EXPECT_THROW(db.insert_config_and_default_values(SCHEMAS_PATH, CONFIG_PATH_WRONG_COMPONENT), - InitDeviceModelDbError); -} - -TEST_F(InitDeviceModelDbTest, config_wrong_variable) { - // Try to set value of attribute of variable that does not exist in the component schema. - InitDeviceModelDb db(DATABASE_PATH, MIGRATION_FILES_PATH); - db.initialize_database(SCHEMAS_PATH, true); - EXPECT_THROW(db.insert_config_and_default_values(SCHEMAS_PATH, CONFIG_PATH_WRONG_VARIABLE), InitDeviceModelDbError); -} - -TEST_F(InitDeviceModelDbTest, config_wrong_component_connectorid) { - // Try to set attribute value of component with a not existing connector id in the component schema. - InitDeviceModelDb db(DATABASE_PATH, MIGRATION_FILES_PATH); - db.initialize_database(SCHEMAS_PATH, true); - EXPECT_THROW(db.insert_config_and_default_values(SCHEMAS_PATH, CONFIG_PATH_WRONG_COMPONENT_CONNECTORID), - InitDeviceModelDbError); -} - TEST_F(InitDeviceModelDbTest, default_device_model_config) { // Test if the default device model config is correct and will create a valid database with valid values. const static std::string MIGRATION_FILES_PATH_DEFAULT = "./resources/v201/device_model_migration_files"; - const static std::string SCHEMAS_PATH_DEFAULT = "./resources/example_config/v201/component_schemas"; - const static std::string CONFIG_PATH_DEFAULT = "./resources/example_config/v201/config.json"; + const static std::string SCHEMAS_PATH_DEFAULT = "./resources/example_config/v201/component_config"; InitDeviceModelDb db(DATABASE_PATH, MIGRATION_FILES_PATH_DEFAULT); EXPECT_NO_THROW(db.initialize_database(SCHEMAS_PATH_DEFAULT, true)); - EXPECT_NO_THROW(db.insert_config_and_default_values(SCHEMAS_PATH_DEFAULT, CONFIG_PATH_DEFAULT)); } // Helper functions diff --git a/tests/lib/ocpp/v201/test_smart_charging_handler.cpp b/tests/lib/ocpp/v201/test_smart_charging_handler.cpp index ee15fbb67..e1e5ea677 100644 --- a/tests/lib/ocpp/v201/test_smart_charging_handler.cpp +++ b/tests/lib/ocpp/v201/test_smart_charging_handler.cpp @@ -46,8 +46,7 @@ static const int DEFAULT_PROFILE_ID = 1; static const int DEFAULT_STACK_LEVEL = 1; static const std::string DEFAULT_TX_ID = "10c75ff7-74f5-44f5-9d01-f649f3ac7b78"; const static std::string MIGRATION_FILES_PATH = "./resources/v201/device_model_migration_files"; -const static std::string SCHEMAS_PATH = "./resources/example_config/v201/component_schemas"; -const static std::string CONFIG_PATH = "./resources/example_config/v201/config.json"; +const static std::string SCHEMAS_PATH = "./resources/example_config/v201/component_config"; const static std::string DEVICE_MODEL_DB_IN_MEMORY_PATH = "file::memory:?cache=shared"; class TestSmartChargingHandler : public SmartChargingHandler { @@ -167,7 +166,6 @@ class ChargepointTestFixtureV201 : public DatabaseTestingUtils { void create_device_model_db(const std::string& path) { InitDeviceModelDb db(path, MIGRATION_FILES_PATH); db.initialize_database(SCHEMAS_PATH, true); - db.insert_config_and_default_values(SCHEMAS_PATH, CONFIG_PATH); } std::shared_ptr From 80b75ef9e09ddf77ab6a839ddecf30222abc73f2 Mon Sep 17 00:00:00 2001 From: "Maaike Zijderveld, iolar" Date: Tue, 6 Aug 2024 18:33:42 +0200 Subject: [PATCH 03/12] Just add another todo Signed-off-by: Maaike Zijderveld, iolar --- lib/ocpp/v201/init_device_model_db.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/ocpp/v201/init_device_model_db.cpp b/lib/ocpp/v201/init_device_model_db.cpp index 8071f9254..167003484 100644 --- a/lib/ocpp/v201/init_device_model_db.cpp +++ b/lib/ocpp/v201/init_device_model_db.cpp @@ -16,6 +16,7 @@ const static std::string CUSTOM_COMPONENT_CONFIG_DIR = "custom"; // TODO mz change EverestEnvironmentOCPPConfiguration in everest_environment_setup.py in everest-utils // TODO mz search for component_schemas and config_file etc to remove or change paths // TODO mz should there be any changes in the types or interfaces? +// TODO mz copy config to schema's in default schema and remove config file namespace ocpp::v201 { From 22704c80567715c13c5413aaf1b41f4e059b5e3d Mon Sep 17 00:00:00 2001 From: "Maaike Zijderveld, iolar" Date: Wed, 7 Aug 2024 12:11:15 +0200 Subject: [PATCH 04/12] Set config values in component config files and remove unneeded files. Signed-off-by: Maaike Zijderveld, iolar --- config/v201/CMakeLists.txt | 1 - .../custom/Connector_1_1.json | 9 +- .../custom/Connector_2_1.json | 9 +- .../v201/component_config/custom/EVSE_1.json | 6 +- .../v201/component_config/custom/EVSE_2.json | 6 +- .../standardized/AlignedDataCtrlr.json | 18 +- .../standardized/AuthCacheCtrlr.json | 6 +- .../standardized/AuthCtrlr.json | 15 +- .../standardized/ChargingStation.json | 12 +- .../standardized/ChargingStatusIndicator.json | 6 +- .../standardized/ClockCtrlr.json | 9 +- .../standardized/DeviceDataCtrlr.json | 28 +- .../standardized/DisplayMessageCtrlr.json | 12 +- .../standardized/ISO15118Ctrlr.json | 9 +- .../standardized/InternalCtrlr.json | 39 +- .../standardized/LocalAuthListCtrlr.json | 12 +- .../standardized/MonitoringCtrlr.json | 9 +- .../standardized/OCPPCommCtrlr.json | 42 +- .../standardized/SampledDataCtrlr.json | 18 +- .../standardized/SecurityCtrlr.json | 24 +- .../standardized/SmartChargingCtrlr.json | 18 +- .../standardized/TariffCostCtrlr.json | 12 +- .../standardized/TxCtrlr.json | 18 +- config/v201/config.json | 812 ------------------ include/ocpp/v201/device_model.hpp | 2 +- lib/ocpp/v201/init_device_model_db.cpp | 2 - .../custom/Connector_1_1.json | 92 -- .../custom/Connector_2_1.json | 92 -- .../component_schemas/custom/EVSE_1.json | 130 --- .../component_schemas/custom/EVSE_2.json | 130 --- .../standardized/UnitTestCtrlr.json | 56 -- tests/config/v201/resources/config.json | 83 -- .../config_not_existing_attribute.json | 15 - .../resources/config_wrong_attribute.json | 14 - .../resources/config_wrong_component.json | 14 - .../config_wrong_component_connectorid.json | 15 - .../v201/resources/config_wrong_variable.json | 14 - .../custom/Connector_1_1.json | 110 --- .../custom/Connector_2_2.json | 46 - .../component_schemas/custom/EVSE_1.json | 119 --- .../component_schemas/custom/EVSE_2.json | 126 --- .../component_schemas/custom/EVSE_3.json | 130 --- .../standardized/UnitTestCtrlr.json | 42 - .../config/v201/resources_changed/config.json | 57 -- .../ocpp/v201/test_init_device_model_db.cpp | 8 +- 45 files changed, 228 insertions(+), 2219 deletions(-) delete mode 100644 config/v201/config.json delete mode 100644 tests/config/v201/resources/component_schemas/custom/Connector_1_1.json delete mode 100644 tests/config/v201/resources/component_schemas/custom/Connector_2_1.json delete mode 100644 tests/config/v201/resources/component_schemas/custom/EVSE_1.json delete mode 100644 tests/config/v201/resources/component_schemas/custom/EVSE_2.json delete mode 100644 tests/config/v201/resources/component_schemas/standardized/UnitTestCtrlr.json delete mode 100644 tests/config/v201/resources/config.json delete mode 100644 tests/config/v201/resources/config_not_existing_attribute.json delete mode 100644 tests/config/v201/resources/config_wrong_attribute.json delete mode 100644 tests/config/v201/resources/config_wrong_component.json delete mode 100644 tests/config/v201/resources/config_wrong_component_connectorid.json delete mode 100644 tests/config/v201/resources/config_wrong_variable.json delete mode 100644 tests/config/v201/resources_changed/component_schemas/custom/Connector_1_1.json delete mode 100644 tests/config/v201/resources_changed/component_schemas/custom/Connector_2_2.json delete mode 100644 tests/config/v201/resources_changed/component_schemas/custom/EVSE_1.json delete mode 100644 tests/config/v201/resources_changed/component_schemas/custom/EVSE_2.json delete mode 100644 tests/config/v201/resources_changed/component_schemas/custom/EVSE_3.json delete mode 100644 tests/config/v201/resources_changed/component_schemas/standardized/UnitTestCtrlr.json delete mode 100644 tests/config/v201/resources_changed/config.json diff --git a/config/v201/CMakeLists.txt b/config/v201/CMakeLists.txt index 60fef10b8..5c45ded90 100644 --- a/config/v201/CMakeLists.txt +++ b/config/v201/CMakeLists.txt @@ -23,7 +23,6 @@ set(MIGRATION_FILES_DEVICE_MODEL_SOURCE_DIR_V201 ${MIGRATION_FILES_DEVICE_MODEL_ option(LIBOCPP_INSTALL_DEVICE_MODEL_DATABASE "Install device model database for OCPP201" ON) list(APPEND CONFIGS - config.json ../logging.ini ) diff --git a/config/v201/component_config/custom/Connector_1_1.json b/config/v201/component_config/custom/Connector_1_1.json index cfa28ebf6..77e745289 100644 --- a/config/v201/component_config/custom/Connector_1_1.json +++ b/config/v201/component_config/custom/Connector_1_1.json @@ -30,7 +30,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": true } ], "description": "Component exists", @@ -60,7 +61,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": "sType2" } ], "description": "A value of ConnectorEnumType (See part 2) plus additionally: cGBT, cChaoJi, OppCharge. Specific type of connector, including sub-variant information. Note: Distinct and orthogonal to Charging Protocol, Power Type, Phases.", @@ -76,7 +78,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": 3 } ], "description": "Number of alternating current phases connected/available.", diff --git a/config/v201/component_config/custom/Connector_2_1.json b/config/v201/component_config/custom/Connector_2_1.json index 876238977..2559c4f2a 100644 --- a/config/v201/component_config/custom/Connector_2_1.json +++ b/config/v201/component_config/custom/Connector_2_1.json @@ -30,7 +30,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": true } ], "description": "Component exists", @@ -60,7 +61,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": "sType2" } ], "description": "A value of ConnectorEnumType (See part 2) plus additionally: cGBT, cChaoJi, OppCharge. Specific type of connector, including sub-variant information. Note: Distinct and orthogonal to Charging Protocol, Power Type, Phases.", @@ -76,7 +78,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": 3 } ], "description": "Number of alternating current phases connected/available.", diff --git a/config/v201/component_config/custom/EVSE_1.json b/config/v201/component_config/custom/EVSE_1.json index 2686ea3c9..a7022e185 100644 --- a/config/v201/component_config/custom/EVSE_1.json +++ b/config/v201/component_config/custom/EVSE_1.json @@ -46,7 +46,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": true } ], "description": "Component exists", @@ -98,7 +99,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": 3 } ], "description": "Number of alternating current phases connected/available.", diff --git a/config/v201/component_config/custom/EVSE_2.json b/config/v201/component_config/custom/EVSE_2.json index 58ba4a477..25d859aff 100644 --- a/config/v201/component_config/custom/EVSE_2.json +++ b/config/v201/component_config/custom/EVSE_2.json @@ -46,7 +46,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": true } ], "description": "Component exists", @@ -98,7 +99,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": 3 } ], "description": "Number of alternating current phases connected/available.", diff --git a/config/v201/component_config/standardized/AlignedDataCtrlr.json b/config/v201/component_config/standardized/AlignedDataCtrlr.json index 2de04e957..81f340379 100644 --- a/config/v201/component_config/standardized/AlignedDataCtrlr.json +++ b/config/v201/component_config/standardized/AlignedDataCtrlr.json @@ -13,7 +13,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": true } ], "default": true, @@ -45,7 +46,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": 900 } ], "description": "Size (in seconds) of the clock-aligned data interval, intended to be transmitted in the MeterValuesRequest message.", @@ -62,7 +64,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": "Energy.Active.Import.Register,Voltage,Frequency" } ], "description": "Clock-aligned measurand(s) to be included in MeterValuesRequest, every AlignedDataInterval seconds.", @@ -78,7 +81,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": false } ], "description": "If set to true, the Charging Station SHALL NOT send clock aligned meter values when a transaction is ongoing.", @@ -110,7 +114,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": 60 } ], "description": "Size (in seconds) of the clock-aligned data interval, intended to be transmitted in the TransactionEventRequest (eventType = Ended) message.", @@ -127,7 +132,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": "Energy.Active.Import.Register,Voltage" } ], "description": "Clock-aligned measurands to be included in the meterValues element of TransactionEventRequest (eventType = Ended), every SampledDataTxEndedInterval seconds from the start of the transaction.", diff --git a/config/v201/component_config/standardized/AuthCacheCtrlr.json b/config/v201/component_config/standardized/AuthCacheCtrlr.json index 0bb151df4..5e9d16c46 100644 --- a/config/v201/component_config/standardized/AuthCacheCtrlr.json +++ b/config/v201/component_config/standardized/AuthCacheCtrlr.json @@ -13,7 +13,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": true } ], "description": "Authorization caching is available, but not necessarily enabled.", @@ -29,7 +30,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": true } ], "description": "If set to true, Authorization caching is enabled.", diff --git a/config/v201/component_config/standardized/AuthCtrlr.json b/config/v201/component_config/standardized/AuthCtrlr.json index 52c60ca79..2f40ac5d2 100644 --- a/config/v201/component_config/standardized/AuthCtrlr.json +++ b/config/v201/component_config/standardized/AuthCtrlr.json @@ -13,7 +13,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": true } ], "default": true, @@ -43,7 +44,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": true } ], "description": "Whether a remote request to start a transaction in the form of RequestStartTransactionRequest message should be authorized beforehand like a local action to start a transaction.", @@ -59,7 +61,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": true } ], "description": "Whether the Charging Station, when Offline, will start a transaction for locally-authorized identifiers,", @@ -75,7 +78,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": true } ], "description": "Whether the Charging Station, when online, will start a transaction for locally-authorized identifiers without waiting for or requesting an AuthorizeResponse from the CSMS.", @@ -91,7 +95,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": "123" } ], "description": "IdTokens that have this id as groupId belong to the Master Pass Group. Meaning they can stop any ongoing transaction, but cannot start transactions.", diff --git a/config/v201/component_config/standardized/ChargingStation.json b/config/v201/component_config/standardized/ChargingStation.json index a01f2aaa6..3e8e3897f 100644 --- a/config/v201/component_config/standardized/ChargingStation.json +++ b/config/v201/component_config/standardized/ChargingStation.json @@ -46,7 +46,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": "RST" } ], "description": "This variable describes the phase rotation of a Component relative to its parent Component, using a three letter string consisting of the letters: R, S, T and x.", @@ -61,7 +62,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": true } ], "description": "Component exists", @@ -90,7 +92,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": 3 } ], "description": "Number of alternating current phases connected/available.", @@ -119,7 +122,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": false } ], "description": "Some problem/fault exists", diff --git a/config/v201/component_config/standardized/ChargingStatusIndicator.json b/config/v201/component_config/standardized/ChargingStatusIndicator.json index 7dd4bdfde..5c1a2d604 100644 --- a/config/v201/component_config/standardized/ChargingStatusIndicator.json +++ b/config/v201/component_config/standardized/ChargingStatusIndicator.json @@ -13,7 +13,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": false } ], "description": "Lighted", @@ -28,7 +29,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": "FFFF00" } ], "description": "Displayed color", diff --git a/config/v201/component_config/standardized/ClockCtrlr.json b/config/v201/component_config/standardized/ClockCtrlr.json index 8d08cb1c5..795f1116a 100644 --- a/config/v201/component_config/standardized/ClockCtrlr.json +++ b/config/v201/component_config/standardized/ClockCtrlr.json @@ -13,7 +13,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": true } ], "type": "boolean" @@ -27,7 +28,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": "" } ], "description": "Contains the current date and time,", @@ -135,7 +137,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": "Heartbeat" } ], "description": "Via this variable, the Charging Station provides the CSMS with the option to configure multiple clock sources", diff --git a/config/v201/component_config/standardized/DeviceDataCtrlr.json b/config/v201/component_config/standardized/DeviceDataCtrlr.json index ea4b91543..e35dce6b9 100644 --- a/config/v201/component_config/standardized/DeviceDataCtrlr.json +++ b/config/v201/component_config/standardized/DeviceDataCtrlr.json @@ -13,7 +13,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": true } ], "type": "boolean" @@ -27,7 +28,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": 2048 } ], "instance": "GetReport", @@ -43,7 +45,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": 2048 } ], "instance": "GetVariables", @@ -59,7 +62,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": 2048 } ], "instance": "SetVariables", @@ -90,7 +94,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": 100 } ], "instance": "GetReport", @@ -106,7 +111,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": 100 } ], "instance": "GetVariables", @@ -122,7 +128,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": 100 } ], "instance": "SetVariables", @@ -138,7 +145,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": 2500 } ], "description": "The limit to the following fields: GetVariableResult.attributeValue, VariableAttribute.value and EventData.actualValue. The max size of these values will always remain equal.", @@ -152,7 +160,9 @@ }, "attributes": [ { - "type": "Actual" + "mutability": "ReadOnly", + "type": "Actual", + "value": 2500 } ], "description": "Can be used to limit the following fields: SetVariableData.attributeValue, GetVariableResult.attributeValue, VariableAttribute.value, VariableCharacteristics.valueList and EventData.actualValue.", diff --git a/config/v201/component_config/standardized/DisplayMessageCtrlr.json b/config/v201/component_config/standardized/DisplayMessageCtrlr.json index 77546946d..3e1e002a7 100644 --- a/config/v201/component_config/standardized/DisplayMessageCtrlr.json +++ b/config/v201/component_config/standardized/DisplayMessageCtrlr.json @@ -28,7 +28,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": 42 } ], "description": "Amount of different messages that are currently configured in this Charging Station, via SetDisplayMessageRequest", @@ -43,7 +44,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": true } ], "description": "Whether display messages are enabled.", @@ -73,7 +75,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": "UTF8,ASCII,URI" } ], "description": "List of message formats supported by this Charging Station.", @@ -89,7 +92,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": "NormalCycle" } ], "description": "List of the priorities supported by this Charging Station.", diff --git a/config/v201/component_config/standardized/ISO15118Ctrlr.json b/config/v201/component_config/standardized/ISO15118Ctrlr.json index 108691151..2f1a0ff12 100644 --- a/config/v201/component_config/standardized/ISO15118Ctrlr.json +++ b/config/v201/component_config/standardized/ISO15118Ctrlr.json @@ -13,7 +13,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": true } ], "type": "boolean" @@ -42,7 +43,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": true } ], "description": "If this variable is true, then Charging Station will try to validate a contract certificate when it is offline", @@ -146,7 +148,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": true } ], "description": "If this variable is true, then ISO 15118 plug and charge as described by use case C07 - Authorization using Contract Certificates is enabled. If this variable is false, then ISO 15118 plug and charge as described by use case C07 - Authorization using Contract Certificates is disabled.", diff --git a/config/v201/component_config/standardized/InternalCtrlr.json b/config/v201/component_config/standardized/InternalCtrlr.json index b41a070e6..9818c313b 100644 --- a/config/v201/component_config/standardized/InternalCtrlr.json +++ b/config/v201/component_config/standardized/InternalCtrlr.json @@ -28,7 +28,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": "cp001" } ], "minLength": 1, @@ -43,7 +44,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": "[{\"configurationSlot\": 1, \"connectionData\": {\"messageTimeout\": 30, \"ocppCsmsUrl\": \"ws://localhost:9000\", \"ocppInterface\": \"Wired0\", \"ocppTransport\": \"JSON\", \"ocppVersion\": \"OCPP20\", \"securityProfile\": 1}}]" } ], "description": "List of NetworkConnectionProfiles that define the functional and technical parameters of a communication link. Must be a (JSON) string with the format of SetNetworkProfileRequest", @@ -59,7 +61,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": "012345678" } ], "minLength": 1, @@ -75,7 +78,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": "EVerestModel" } ], "minLength": 1, @@ -107,7 +111,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": "EVerestVendor" } ], "minLength": 1, @@ -123,7 +128,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": "1.0" } ], "minLength": 1, @@ -204,7 +210,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-GCM-SHA384" } ], "default": "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-GCM-SHA384", @@ -221,7 +228,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": "TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256" } ], "default": "TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256", @@ -268,7 +276,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": "log,html,security" } ], "description": "Supported log formats are console, log, html, console_detailed, callback and security. \"security\" logs security events into a seperate logfile", @@ -317,7 +326,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": 1 } ], "minimum": 1, @@ -556,7 +566,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": false } ], "default": false, @@ -607,7 +618,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": "Enabled,Active,Available,Problem" } ], "description": "List of criteria supported for a get custom report. Enabled,Active,Problem,Available", @@ -623,7 +635,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": false } ], "description": "If enabled the metervalues configured with the AlignedDataCtrlr will be rounded to the exact time intervals", diff --git a/config/v201/component_config/standardized/LocalAuthListCtrlr.json b/config/v201/component_config/standardized/LocalAuthListCtrlr.json index 45d337058..ae1e14321 100644 --- a/config/v201/component_config/standardized/LocalAuthListCtrlr.json +++ b/config/v201/component_config/standardized/LocalAuthListCtrlr.json @@ -29,7 +29,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": 4096 } ], "description": "Maximum number of bytes in a SendLocalList message.", @@ -44,7 +45,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": true } ], "description": "If this variable exists and reports a value of true, Local Authorization List is enabled.", @@ -60,7 +62,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": 0 } ], "description": "Amount of IdTokens currently in the Local Authorization List", @@ -75,7 +78,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": 250 } ], "description": "Maximum number of records in SendLocalList", diff --git a/config/v201/component_config/standardized/MonitoringCtrlr.json b/config/v201/component_config/standardized/MonitoringCtrlr.json index 741d11f8d..4d6541a5d 100644 --- a/config/v201/component_config/standardized/MonitoringCtrlr.json +++ b/config/v201/component_config/standardized/MonitoringCtrlr.json @@ -13,7 +13,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": false } ], "description": "Whether monitoring is enabled.", @@ -93,7 +94,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": 4000 } ], "instance": "SetVariableMonitoring", @@ -125,7 +127,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": 250 } ], "instance": "SetVariableMonitoring", diff --git a/config/v201/component_config/standardized/OCPPCommCtrlr.json b/config/v201/component_config/standardized/OCPPCommCtrlr.json index 1401a42f9..7cdeef36b 100644 --- a/config/v201/component_config/standardized/OCPPCommCtrlr.json +++ b/config/v201/component_config/standardized/OCPPCommCtrlr.json @@ -13,7 +13,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": true } ], "type": "boolean" @@ -44,7 +45,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": "FTP" } ], "description": "List of supported file transfer protocols", @@ -77,7 +79,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": 60 } ], "instance": "Default", @@ -95,7 +98,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": 10 } ], "instance": "TransactionEvent", @@ -112,7 +116,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": 5 } ], "instance": "TransactionEvent", @@ -130,7 +135,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": 1 } ], "description": "A comma separated ordered list of the priority of the possible Network Connection Profiles.", @@ -146,7 +152,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": 3 } ], "description": "Specifies the number of connection attempts the Charging Station executes before switching to a different profile.", @@ -163,7 +170,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": 60 } ], "description": "When the offline period of a Charging Station exceeds the OfflineThreshold it is recommended to send a StatusNotificationRequest for all its Connectors.", @@ -210,7 +218,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": 3 } ], "description": "Number of times to retry a reset of the Charging Station when a reset was unsuccessful", @@ -226,7 +235,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": 2 } ], "description": "When the Charging Station is reconnecting, after a connection loss, it will use this variable as the maximum value for the random part of the back-off time", @@ -242,7 +252,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": 2 } ], "description": "When the Charging Station is reconnecting, after a connection loss, it will use this variable for the amount of times it will double the previous back-off time.", @@ -258,7 +269,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": 1 } ], "description": "When the Charging Station is reconnecting, after a connection loss, it will use this variable as the minimum back-off time, the first time it tries to reconnect.", @@ -274,7 +286,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": true } ], "description": "When set to true, the Charging Station SHALL unlock the cable on the Charging Station side when the cable is unplugged at the EV. For an EVSE with only fixed cables, the mutability SHALL be ReadOnly and the actual value SHALL be false. For a charging station with fixed cables and sockets, the variable is only applicable to the sockets.", @@ -291,7 +304,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": 10 } ], "description": "0 disables client side websocket Ping/Pong. In this case there is either no ping/pong or the server initiates the ping and client responds with Pong. Positive values are interpreted as number of seconds between pings. Negative values are not allowed.", diff --git a/config/v201/component_config/standardized/SampledDataCtrlr.json b/config/v201/component_config/standardized/SampledDataCtrlr.json index c960e94e5..caa17278f 100644 --- a/config/v201/component_config/standardized/SampledDataCtrlr.json +++ b/config/v201/component_config/standardized/SampledDataCtrlr.json @@ -29,7 +29,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": true } ], "description": "If this variable reports a value of true, Sampled Data is enabled.", @@ -61,7 +62,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": 60 } ], "description": "Interval between sampling of metering (or other) data, intended to be transmitted in the TransactionEventRequest (eventType = Ended) message.", @@ -78,7 +80,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": "Energy.Active.Import.Register,Current.Import" } ], "description": "Sampled measurands to be included in the meterValues element of TransactionEventRequest (eventType = Ended), every SampledDataTxEndedInterval seconds from the start of the transaction.", @@ -95,7 +98,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": "Energy.Active.Import.Register,Current.Import" } ], "description": "Sampled measurand(s) to be taken at the start of any transaction to be included in the meterValues field of the first TransactionEventRequest message send at the start of a transaction (eventType = Started)", @@ -112,7 +116,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": 120 } ], "description": "Interval between sampling of metering (or other) data, intended to be transmitted via TransactionEventRequest (eventType = Updated) messages", @@ -129,7 +134,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": "Energy.Active.Import.Register,Current.Import,Voltage,Power.Active.Import,Power.Reactive.Import,Frequency,SoC" } ], "description": "Sampled measurands to be included in the meterValues element of TransactionEventRequest (eventType = Ended)", diff --git a/config/v201/component_config/standardized/SecurityCtrlr.json b/config/v201/component_config/standardized/SecurityCtrlr.json index 0f9ad6848..ab13d92f4 100644 --- a/config/v201/component_config/standardized/SecurityCtrlr.json +++ b/config/v201/component_config/standardized/SecurityCtrlr.json @@ -13,7 +13,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": false } ], "default": true, @@ -46,7 +47,8 @@ "attributes": [ { "type": "Actual", - "mutability": "WriteOnly" + "mutability": "WriteOnly", + "value": "DEADBEEFDEADBEEF" } ], "description": "The basic authentication password is used for HTTP Basic Authentication.", @@ -64,7 +66,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": 100 } ], "description": "Amount of Certificates currently installed on the Charging Station", @@ -79,7 +82,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": 2 } ], "description": "Number of times to resend a SignCertificateRequest when CSMS does nor return a signed certificate.", @@ -96,7 +100,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": 0 } ], "description": "Seconds to wait before generating another CSR in case CSMS does not return a signed certificate.", @@ -112,7 +117,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": "cp001" } ], "description": "The Charging Station identity.", @@ -143,7 +149,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": "Pionix" } ], "description": "The organization name of the CSO or an organization trusted by the CSO. This organization name is used to specify the subject field in the client certificate.", @@ -161,7 +168,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": 1 } ], "description": "The security profile used by the Charging Station.", diff --git a/config/v201/component_config/standardized/SmartChargingCtrlr.json b/config/v201/component_config/standardized/SmartChargingCtrlr.json index fb9db14de..a7689a24c 100644 --- a/config/v201/component_config/standardized/SmartChargingCtrlr.json +++ b/config/v201/component_config/standardized/SmartChargingCtrlr.json @@ -43,7 +43,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": false } ], "description": "Whether smart charging is enabled.", @@ -58,7 +59,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": 0 } ], "instance": "ChargingProfiles", @@ -90,7 +92,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": 42 } ], "description": "If at the Charging Station side a change in the limit in a ChargingProfile is lower than this percentage, the Charging Station MAY skip sending a NotifyChargingLimitRequest or a TransactionEventRequest message to the CSMS.", @@ -120,7 +123,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": 42 } ], "description": "Maximum number of periods that may be defined per ChargingSchedule.", @@ -150,7 +154,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": 42 } ], "description": "Maximum acceptable value for stackLevel in a ChargingProfile. Since the lowest stackLevel is 0, this means that if SmartChargingCtrlr.ProfileStackLevel = 1, there can be at most 2 valid charging profiles per Charging Profile Purpose per EVSE.", @@ -166,7 +171,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": "" } ], "description": "A list of supported quantities for use in a ChargingSchedule. Allowed values: 'A' and 'W\ufffd", diff --git a/config/v201/component_config/standardized/TariffCostCtrlr.json b/config/v201/component_config/standardized/TariffCostCtrlr.json index fc5e917f9..a3f1c3a8f 100644 --- a/config/v201/component_config/standardized/TariffCostCtrlr.json +++ b/config/v201/component_config/standardized/TariffCostCtrlr.json @@ -46,7 +46,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": "EUR" } ], "description": "Currency used by this Charging Station in a ISO 4217 [ISO4217] formatted currency code.", @@ -77,7 +78,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": false } ], "instance": "Cost", @@ -94,7 +96,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": "" } ], "description": "Message (and/or tariff information) to be shown to an EV Driver when there is no driver specific tariff information available.", @@ -110,7 +113,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": "" } ], "description": "Message to be shown to an EV Driver when the Charging Station cannot retrieve the cost for a transaction at the end of the transaction.", diff --git a/config/v201/component_config/standardized/TxCtrlr.json b/config/v201/component_config/standardized/TxCtrlr.json index ad8763cf7..0f6563636 100644 --- a/config/v201/component_config/standardized/TxCtrlr.json +++ b/config/v201/component_config/standardized/TxCtrlr.json @@ -13,7 +13,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": false } ], "default": true, @@ -44,7 +45,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": 120 } ], "description": "Interval from between \"starting\" of a transaction until incipient transaction is automatically canceled, due to failure of EV driver to (correctly) insert the charging cable connector(s) into the appropriate socket(s).", @@ -76,7 +78,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": true } ], "description": "When set to true, the Charging Station SHALL deauthorize the transaction when the cable is unplugged from the EV.", @@ -92,7 +95,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": true } ], "description": "Whether the Charging Station will deauthorize an ongoing transaction when it receives a non- Accepted authorization status in TransactionEventResponse for this transaction.", @@ -124,7 +128,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": "PowerPathClosed" } ], "description": "Defines when the Charging Station starts a new transaction", @@ -141,7 +146,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadWrite" + "mutability": "ReadWrite", + "value": "EVConnected,Authorized" } ], "description": "Defines when the Charging Station ends a transaction", diff --git a/config/v201/config.json b/config/v201/config.json deleted file mode 100644 index 6c5930a69..000000000 --- a/config/v201/config.json +++ /dev/null @@ -1,812 +0,0 @@ -[ - { - "name": "ChargingStatusIndicator", - "variables": { - "ChargingStatusIndicatorActive": { - "variable_name": "Active", - "attributes": { - "Actual": false - } - }, - "ChargingStatusIndicatorColor": { - "variable_name": "Color", - "attributes": { - "Actual": "FFFF00" - } - } - } - }, - - { - "name": "Connector", - "evse_id": 1, - "connector_id": 1, - "variables": { - "ConnectorAvailable": { - "variable_name": "Available", - "attributes": { - "Actual": true - } - }, - "ConnectorType": { - "variable_name": "ConnectorType", - "attributes": { - "Actual": "sType2" - } - }, - "ConnectorSupplyPhases": { - "variable_name": "SupplyPhases", - "attributes": { - "Actual": 3 - } - } - } - }, - { - "name": "EVSE", - "evse_id": 1, - "variables": { - "EVSEAvailable": { - "variable_name": "Available", - "attributes": { - "Actual": true - } - }, - "EVSESupplyPhases": { - "variable_name": "SupplyPhases", - "attributes": { - "Actual": 3 - } - } - } - }, - { - "name": "Connector", - "evse_id": 2, - "connector_id": 1, - "variables": { - "ConnectorAvailable": { - "variable_name": "Available", - "attributes": { - "Actual": true - } - }, - "ConnectorType": { - "variable_name": "ConnectorType", - "attributes": { - "Actual": "sType2" - } - }, - "ConnectorSupplyPhases": { - "variable_name": "SupplyPhases", - "attributes": { - "Actual": 3 - } - } - } - }, - { - "name": "EVSE", - "evse_id": 2, - "variables": { - "EVSEAvailable": { - "variable_name": "Available", - "attributes": { - "Actual": true - } - }, - "EVSESupplyPhases": { - "variable_name": "SupplyPhases", - "attributes": { - "Actual": 3 - } - } - } - }, - { - "name": "SampledDataCtrlr", - "variables": { - "SampledDataCtrlrEnabled": { - "variable_name": "Enabled", - "attributes": { - "Actual": true - } - }, - "SampledDataTxEndedInterval": { - "variable_name": "TxEndedInterval", - "attributes": { - "Actual": 60 - } - }, - "SampledDataTxEndedMeasurands": { - "variable_name": "TxEndedMeasurands", - "attributes": { - "Actual": "Energy.Active.Import.Register,Current.Import" - } - }, - "SampledDataTxStartedMeasurands": { - "variable_name": "TxStartedMeasurands", - "attributes": { - "Actual": "Energy.Active.Import.Register,Current.Import" - } - }, - "SampledDataTxUpdatedInterval": { - "variable_name": "TxUpdatedInterval", - "attributes": { - "Actual": 120 - } - }, - "SampledDataTxUpdatedMeasurands": { - "variable_name": "TxUpdatedMeasurands", - "attributes": { - "Actual": "Energy.Active.Import.Register,Current.Import,Voltage,Power.Active.Import,Power.Reactive.Import,Frequency,SoC" - } - } - } - }, - { - "name": "LocalAuthListCtrlr", - "variables": { - "BytesPerMessageSendLocalList": { - "variable_name": "BytesPerMessage", - "attributes": { - "Actual": 4096 - } - }, - "LocalAuthListCtrlrEntries": { - "variable_name": "Entries", - "attributes": { - "Actual": 0 - } - }, - "ItemsPerMessageSendLocalList": { - "variable_name": "ItemsPerMessage", - "attributes": { - "Actual": 250 - } - }, - "LocalAuthListCtrlrEnabled": { - "variable_name": "Enabled", - "attributes": { - "Actual": true - } - } - } - }, - { - "name": "InternalCtrlr", - "variables": { - "ChargePointId": { - "variable_name": "ChargePointId", - "attributes": { - "Actual": "cp001" - } - }, - "NetworkConnectionProfiles": { - "variable_name": "NetworkConnectionProfiles", - "attributes": { - "Actual": "[{\"configurationSlot\": 1, \"connectionData\": {\"messageTimeout\": 30, \"ocppCsmsUrl\": \"ws://localhost:9000\", \"ocppInterface\": \"Wired0\", \"ocppTransport\": \"JSON\", \"ocppVersion\": \"OCPP20\", \"securityProfile\": 1}}]" - } - }, - "ChargeBoxSerialNumber": { - "variable_name": "ChargeBoxSerialNumber", - "attributes": { - "Actual": "012345678" - } - }, - "ChargePointModel": { - "variable_name": "ChargePointModel", - "attributes": { - "Actual": "EVerestModel" - } - }, - "ChargePointVendor": { - "variable_name": "ChargePointVendor", - "attributes": { - "Actual": "EVerestVendor" - } - }, - "FirmwareVersion": { - "variable_name": "FirmwareVersion", - "attributes": { - "Actual": "1.0" - } - }, - "SupportedCiphers12": { - "variable_name": "SupportedCiphers12", - "attributes": { - "Actual": "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-GCM-SHA384" - } - }, - "SupportedCiphers13": { - "variable_name": "SupportedCiphers13", - "attributes": { - "Actual": "TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256" - } - }, - "NumberOfConnectors": { - "variable_name": "NumberOfConnectors", - "attributes": { - "Actual": 1 - } - }, - "LogMessagesFormat": { - "variable_name": "LogMessagesFormat", - "attributes": { - "Actual": "log,html,security" - } - }, - "SupportedCriteria": { - "variable_name": "SupportedCriteria", - "attributes": { - "Actual": "Enabled,Active,Available,Problem" - } - }, - "UpdateCertificateSymlinks": { - "variable_name": "UpdateCertificateSymlinks", - "attributes": { - "Actual": false - } - }, - "RoundClockAlignedTimestamps": { - "variable_name": "RoundClockAlignedTimestamps", - "attributes": { - "Actual": false - } - } - } - }, - { - "name": "OCPPCommCtrlr", - "variables": { - "FileTransferProtocols": { - "variable_name": "FileTransferProtocols", - "attributes": { - "Actual": "FTP" - } - }, - "MessageTimeout": { - "variable_name": "MessageTimeout", - "attributes": { - "Actual": 60 - }, - "instance": "Default" - }, - "MessageAttemptInterval": { - "variable_name": "MessageAttemptInterval", - "attributes": { - "Actual": 10 - }, - "instance": "TransactionEvent" - }, - "MessageAttempts": { - "variable_name": "MessageAttempts", - "attributes": { - "Actual": 5 - }, - "instance": "TransactionEvent" - }, - "NetworkConfigurationPriority": { - "variable_name": "NetworkConfigurationPriority", - "attributes": { - "Actual": "1" - } - }, - "NetworkProfileConnectionAttempts": { - "variable_name": "NetworkProfileConnectionAttempts", - "attributes": { - "Actual": 3 - } - }, - "OfflineThreshold": { - "variable_name": "OfflineThreshold", - "attributes": { - "Actual": 60 - } - }, - "ResetRetries": { - "variable_name": "ResetRetries", - "attributes": { - "Actual": 3 - } - }, - "RetryBackOffRandomRange": { - "variable_name": "RetryBackOffRandomRange", - "attributes": { - "Actual": 2 - } - }, - "RetryBackOffRepeatTimes": { - "variable_name": "RetryBackOffRepeatTimes", - "attributes": { - "Actual": 2 - } - }, - "RetryBackOffWaitMinimum": { - "variable_name": "RetryBackOffWaitMinimum", - "attributes": { - "Actual": 1 - } - }, - "UnlockOnEVSideDisconnect": { - "variable_name": "UnlockOnEVSideDisconnect", - "attributes": { - "Actual": true - } - }, - "WebSocketPingInterval": { - "variable_name": "WebSocketPingInterval", - "attributes": { - "Actual": 10 - } - }, - "OCPPCommCtrlrEnabled": { - "variable_name": "Enabled", - "attributes": { - "Actual": true - } - } - } - }, - { - "name": "DisplayMessageCtrlr", - "variables": { - "NumberOfDisplayMessages": { - "variable_name": "DisplayMessages", - "attributes": { - "Actual": 42 - } - }, - "DisplayMessageSupportedFormats": { - "variable_name": "SupportedFormats", - "attributes": { - "Actual": "" - } - }, - "DisplayMessageSupportedPriorities": { - "variable_name": "SupportedPriorities", - "attributes": { - "Actual": "" - } - }, - "DisplayMessageCtrlrEnabled": { - "variable_name": "Enabled", - "attributes": { - "Actual": true - } - } - } - }, - { - "name": "ClockCtrlr", - "variables": { - "DateTime": { - "variable_name": "DateTime", - "attributes": { - "Actual": "" - } - }, - "TimeSource": { - "variable_name": "TimeSource", - "attributes": { - "Actual": "Heartbeat" - } - }, - "ClockCtrlrEnabled": { - "variable_name": "Enabled", - "attributes": { - "Actual": true - } - } - } - }, - { - "name": "ReservationCtrlr", - "variables": {} - }, - { - "name": "ISO15118Ctrlr", - "variables": { - "ContractValidationOffline": { - "variable_name": "ContractValidationOffline", - "attributes": { - "Actual": true - } - }, - "ReservationCtrlrEnabled": { - "variable_name": "Enabled", - "attributes": { - "Actual": true - } - }, - "PnCEnabled": { - "variable_name": "PnCEnabled", - "attributes": { - "Actual": true - } - } - } - }, - { - "name": "TxCtrlr", - "variables": { - "EVConnectionTimeOut": { - "variable_name": "EVConnectionTimeOut", - "attributes": { - "Actual": 120 - } - }, - "StopTxOnEVSideDisconnect": { - "variable_name": "StopTxOnEVSideDisconnect", - "attributes": { - "Actual": true - } - }, - "StopTxOnInvalidId": { - "variable_name": "StopTxOnInvalidId", - "attributes": { - "Actual": true - } - }, - "TxStartPoint": { - "variable_name": "TxStartPoint", - "attributes": { - "Actual": "PowerPathClosed" - } - }, - "TxStopPoint": { - "variable_name": "TxStopPoint", - "attributes": { - "Actual": "EVConnected,Authorized" - } - }, - "TxCtrlrEnabled": { - "variable_name": "Enabled", - "attributes": { - "Actual": false - } - } - } - }, - { - "name": "AlignedDataCtrlr", - "variables": { - "AlignedDataInterval": { - "variable_name": "Interval", - "attributes": { - "Actual": 900 - } - }, - "AlignedDataMeasurands": { - "variable_name": "Measurands", - "attributes": { - "Actual": "Energy.Active.Import.Register,Voltage,Frequency" - } - }, - "AlignedDataTxEndedInterval": { - "variable_name": "TxEndedInterval", - "attributes": { - "Actual": 60 - } - }, - "AlignedDataTxEndedMeasurands": { - "variable_name": "TxEndedMeasurands", - "attributes": { - "Actual": "Energy.Active.Import.Register,Voltage" - } - }, - "AlignedDataSendDuringIdle": { - "variable_name": "SendDuringIdle", - "attributes": { - "Actual": false - } - }, - "AlignedDataCtrlrEnabled": { - "variable_name": "Enabled", - "attributes": { - "Actual": true - } - } - } - }, - { - "name": "AuthCtrlr", - "variables": { - "AuthorizeRemoteStart": { - "variable_name": "AuthorizeRemoteStart", - "attributes": { - "Actual": true - } - }, - "LocalAuthorizeOffline": { - "variable_name": "LocalAuthorizeOffline", - "attributes": { - "Actual": true - } - }, - "LocalPreAuthorize": { - "variable_name": "LocalPreAuthorize", - "attributes": { - "Actual": true - } - }, - "MasterPassGroupId": { - "variable_name": "MasterPassGroupId", - "attributes": { - "Actual": "123" - } - }, - "AuthCtrlrEnabled": { - "variable_name": "Enabled", - "attributes": { - "Actual": true - } - } - } - }, - { - "name": "AuthCacheCtrlr", - "variables": { - "AuthCacheCtrlrAvailable": { - "variable_name": "Available", - "attributes": { - "Actual": true - } - }, - "AuthCacheCtrlrEnabled": { - "variable_name": "Enabled", - "attributes": { - "Actual": true - } - } - } - }, - { - "name": "ChargingStation", - "variables": { - "ChargingStationAvailable": { - "variable_name": "Available", - "attributes": { - "Actual": true - } - }, - "ChargingStationSupplyPhases": { - "variable_name": "SupplyPhases", - "attributes": { - "Actual": 3 - } - }, - "ChargingStationPhaseRotation": { - "variable_name": "PhaseRotation", - "attributes": { - "Actual": "RST" - } - }, - "ChargingStationProblem": { - "variable_name": "Problem", - "attributes": { - "Actual": false - } - } - } - }, - { - "name": "CustomizationCtrlr", - "variables": {} - }, - { - "name": "DeviceDataCtrlr", - "variables": { - "BytesPerMessageGetReport": { - "variable_name": "BytesPerMessage", - "attributes": { - "Actual": 2048 - }, - "instance": "GetReport" - }, - "BytesPerMessageGetVariables": { - "variable_name": "BytesPerMessage", - "attributes": { - "Actual": 2048 - }, - "instance": "GetVariables" - }, - "BytesPerMessageSetVariables": { - "variable_name": "BytesPerMessage", - "attributes": { - "Actual": 2048 - }, - "instance": "SetVariables" - }, - "ItemsPerMessageGetReport": { - "variable_name": "ItemsPerMessage", - "attributes": { - "Actual": 100 - }, - "instance": "GetReport" - }, - "ItemsPerMessageGetVariables": { - "variable_name": "ItemsPerMessage", - "attributes": { - "Actual": 100 - }, - "instance": "GetVariables" - }, - "ItemsPerMessageSetVariables": { - "variable_name": "ItemsPerMessage", - "attributes": { - "Actual": 100 - }, - "instance": "SetVariables" - }, - "ReportingValueSize": { - "variable_name": "ReportingValueSize", - "attributes": { - "Actual": 2500 - } - }, - "ValueSize": { - "variable_name": "ValueSize", - "attributes": { - "Actual": 2500 - } - }, - "DeviceDataCtrlrEnabled": { - "variable_name": "Enabled", - "attributes": { - "Actual": true - } - } - } - }, - { - "name": "TariffCostCtrlr", - "variables": { - "TariffCostCtrlrCurrency": { - "variable_name": "Currency", - "attributes": { - "Actual": "" - } - }, - "TariffFallbackMessage": { - "variable_name": "TariffFallbackMessage", - "attributes": { - "Actual": "" - } - }, - "TotalCostFallbackMessage": { - "variable_name": "TotalCostFallbackMessage", - "attributes": { - "Actual": "" - } - }, - "TariffCostCtrlrEnabledCost": { - "variable_name": "Enabled", - "instance": "Cost", - "attributes": { - "Actual": false - } - } - } - }, - { - "name": "SecurityCtrlr", - "variables": { - "CertificateEntries": { - "variable_name": "CertificateEntries", - "attributes": { - "Actual": 100 - } - }, - "OrganizationName": { - "variable_name": "OrganizationName", - "attributes": { - "Actual": "Pionix" - } - }, - "SecurityProfile": { - "variable_name": "SecurityProfile", - "attributes": { - "Actual": "1" - } - }, - "Identity": { - "variable_name": "Identity", - "attributes": { - "Actual": "cp001" - } - }, - "BasicAuthPassword": { - "variable_name": "BasicAuthPassword", - "attributes": { - "Actual": "DEADBEEFDEADBEEF" - } - }, - "SecurityCtrlrEnabled": { - "variable_name": "Enabled", - "attributes": { - "Actual": false - } - }, - "CertSigningWaitMinimum": { - "variable_name": "CertSigningWaitMinimum", - "attributes": { - "Actual": 0 - } - }, - "CertSigningRepeatTimes": { - "variable_name": "CertSigningRepeatTimes", - "attributes": { - "Actual": 2 - } - } - } - }, - { - "name": "SmartChargingCtrlr", - "variables": { - "EntriesChargingProfiles": { - "variable_name": "Entries", - "attributes": { - "Actual": 0 - }, - "instance": "ChargingProfiles" - }, - "LimitChangeSignificance": { - "variable_name": "LimitChangeSignificance", - "attributes": { - "Actual": 42 - } - }, - "PeriodsPerSchedule": { - "variable_name": "PeriodsPerSchedule", - "attributes": { - "Actual": 42 - } - }, - "ChargingProfileMaxStackLevel": { - "variable_name": "ProfileStackLevel", - "attributes": { - "Actual": 42 - } - }, - "ChargingScheduleChargingRateUnit": { - "variable_name": "RateUnit", - "attributes": { - "Actual": "" - } - }, - "SmartChargingCtrlrAvailableEnabled": { - "variable_name": "Enabled", - "attributes": { - "Actual": false - } - } - } - }, - { - "name": "MonitoringCtrlr", - "variables": { - "BytesPerMessageSetVariableMonitoring": { - "variable_name": "BytesPerMessage", - "attributes": { - "Actual": 4096 - }, - "instance": "SetVariableMonitoring" - }, - "ItemsPerMessageSetVariableMonitoring": { - "variable_name": "ItemsPerMessage", - "attributes": { - "Actual": 250 - }, - "instance": "SetVariableMonitoring" - }, - "MonitoringCtrlrEnabled": { - "variable_name": "Enabled", - "attributes": { - "Actual": false - } - } - } - } -] diff --git a/include/ocpp/v201/device_model.hpp b/include/ocpp/v201/device_model.hpp index 8c8468956..4377b580d 100644 --- a/include/ocpp/v201/device_model.hpp +++ b/include/ocpp/v201/device_model.hpp @@ -256,7 +256,7 @@ class DeviceModel { /// \brief Sets the given monitor \p requests in the device model /// \param request /// \param type The type of the set monitors. HardWiredMonitor - used for OEM specific monitors, - /// PreconfiguredMonitor - monitors that were manually defined in the config.json, + /// PreconfiguredMonitor - monitors that were manually defined in the component config, /// CustomMonitor - used for monitors that are set by the CSMS, /// \return List of results of the requested operation std::vector set_monitors(const std::vector& requests, diff --git a/lib/ocpp/v201/init_device_model_db.cpp b/lib/ocpp/v201/init_device_model_db.cpp index 167003484..845f961cf 100644 --- a/lib/ocpp/v201/init_device_model_db.cpp +++ b/lib/ocpp/v201/init_device_model_db.cpp @@ -15,8 +15,6 @@ const static std::string CUSTOM_COMPONENT_CONFIG_DIR = "custom"; // TODO mz change EverestEnvironmentOCPPConfiguration in everest_environment_setup.py in everest-utils // TODO mz search for component_schemas and config_file etc to remove or change paths -// TODO mz should there be any changes in the types or interfaces? -// TODO mz copy config to schema's in default schema and remove config file namespace ocpp::v201 { diff --git a/tests/config/v201/resources/component_schemas/custom/Connector_1_1.json b/tests/config/v201/resources/component_schemas/custom/Connector_1_1.json deleted file mode 100644 index cfa28ebf6..000000000 --- a/tests/config/v201/resources/component_schemas/custom/Connector_1_1.json +++ /dev/null @@ -1,92 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "description": "Schema for Connector", - "type": "object", - "name": "Connector", - "evse_id": 1, - "connector_id": 1, - "properties": { - "ConnectorAvailabilityState": { - "variable_name": "AvailabilityState", - "characteristics": { - "supportsMonitoring": true, - "dataType": "OptionList", - "valuesList": "Available,Occupied,Reserved,Unavailable,Faulted" - }, - "attributes": [ - { - "type": "Actual" - } - ], - "description": "This variable reports current availability state for the Connector. Optional, because already reported in StatusNotification.", - "type": "string" - }, - "ConnectorAvailable": { - "variable_name": "Available", - "characteristics": { - "supportsMonitoring": true, - "dataType": "boolean" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "description": "Component exists", - "type": "boolean", - "default": false - }, - "ChargeProtocol": { - "variable_name": "ChargeProtocol", - "characteristics": { - "supportsMonitoring": true, - "dataType": "string" - }, - "attributes": [ - { - "type": "Actual" - } - ], - "description": "The Charging Control Protocol applicable to a Connector. CHAdeMO: CHAdeMO protocol, ISO15118: ISO15118 V2G protocol (wired or wireless) as used with CCS, CPPWM: IEC61851-1 / SAE J1772 protocol (ELV DC & PWM signalling via Control Pilot wire), Uncontrolled: No charging power management applies (e.g. Schuko socket), Undetermined: Yet to be determined (e.g. before plugged in), Unknown: Not determinable, NOTE: ChargeProtocol is distinct from and orthogonal to connectorType.", - "type": "string" - }, - "ConnectorType": { - "variable_name": "ConnectorType", - "characteristics": { - "supportsMonitoring": true, - "dataType": "string" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "description": "A value of ConnectorEnumType (See part 2) plus additionally: cGBT, cChaoJi, OppCharge. Specific type of connector, including sub-variant information. Note: Distinct and orthogonal to Charging Protocol, Power Type, Phases.", - "type": "string", - "default": "" - }, - "ConnectorSupplyPhases": { - "variable_name": "SupplyPhases", - "characteristics": { - "supportsMonitoring": true, - "dataType": "integer" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "description": "Number of alternating current phases connected/available.", - "type": "integer", - "default": "0" - } - }, - "required": [ - "ConnectorAvailable", - "ConnectorSupplyPhases", - "ConnectorType" - ] -} diff --git a/tests/config/v201/resources/component_schemas/custom/Connector_2_1.json b/tests/config/v201/resources/component_schemas/custom/Connector_2_1.json deleted file mode 100644 index 876238977..000000000 --- a/tests/config/v201/resources/component_schemas/custom/Connector_2_1.json +++ /dev/null @@ -1,92 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "description": "Schema for Connector", - "type": "object", - "name": "Connector", - "evse_id": 2, - "connector_id": 1, - "properties": { - "ConnectorAvailabilityState": { - "variable_name": "AvailabilityState", - "characteristics": { - "supportsMonitoring": true, - "dataType": "OptionList", - "valuesList": "Available,Occupied,Reserved,Unavailable,Faulted" - }, - "attributes": [ - { - "type": "Actual" - } - ], - "description": "This variable reports current availability state for the Connector. Optional, because already reported in StatusNotification.", - "type": "string" - }, - "ConnectorAvailable": { - "variable_name": "Available", - "characteristics": { - "supportsMonitoring": true, - "dataType": "boolean" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "description": "Component exists", - "type": "boolean", - "default": false - }, - "ChargeProtocol": { - "variable_name": "ChargeProtocol", - "characteristics": { - "supportsMonitoring": true, - "dataType": "string" - }, - "attributes": [ - { - "type": "Actual" - } - ], - "description": "The Charging Control Protocol applicable to a Connector. CHAdeMO: CHAdeMO protocol, ISO15118: ISO15118 V2G protocol (wired or wireless) as used with CCS, CPPWM: IEC61851-1 / SAE J1772 protocol (ELV DC & PWM signalling via Control Pilot wire), Uncontrolled: No charging power management applies (e.g. Schuko socket), Undetermined: Yet to be determined (e.g. before plugged in), Unknown: Not determinable, NOTE: ChargeProtocol is distinct from and orthogonal to connectorType.", - "type": "string" - }, - "ConnectorType": { - "variable_name": "ConnectorType", - "characteristics": { - "supportsMonitoring": true, - "dataType": "string" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "description": "A value of ConnectorEnumType (See part 2) plus additionally: cGBT, cChaoJi, OppCharge. Specific type of connector, including sub-variant information. Note: Distinct and orthogonal to Charging Protocol, Power Type, Phases.", - "type": "string", - "default": "" - }, - "ConnectorSupplyPhases": { - "variable_name": "SupplyPhases", - "characteristics": { - "supportsMonitoring": true, - "dataType": "integer" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "description": "Number of alternating current phases connected/available.", - "type": "integer", - "default": "0" - } - }, - "required": [ - "ConnectorAvailable", - "ConnectorSupplyPhases", - "ConnectorType" - ] -} diff --git a/tests/config/v201/resources/component_schemas/custom/EVSE_1.json b/tests/config/v201/resources/component_schemas/custom/EVSE_1.json deleted file mode 100644 index 2686ea3c9..000000000 --- a/tests/config/v201/resources/component_schemas/custom/EVSE_1.json +++ /dev/null @@ -1,130 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "description": "Schema for EVSE", - "type": "object", - "name": "EVSE", - "evse_id": 1, - "properties": { - "EVSEAllowReset": { - "variable_name": "AllowReset", - "characteristics": { - "supportsMonitoring": true, - "dataType": "boolean" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "description": "Can be used to announce that an EVSE can be reset individually", - "type": "boolean" - }, - "EVSEAvailabilityState": { - "variable_name": "AvailabilityState", - "characteristics": { - "supportsMonitoring": true, - "dataType": "OptionList", - "valuesList": "Available,Occupied,Reserved,Unavailable,Faulted" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "description": "This variable reports current availability state for the EVSE", - "type": "string", - "default": "Unavailable" - }, - "EVSEAvailable": { - "variable_name": "Available", - "characteristics": { - "supportsMonitoring": true, - "dataType": "boolean" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "description": "Component exists", - "type": "boolean", - "default": false - }, - "EvseId": { - "variable_name": "EvseId", - "characteristics": { - "supportsMonitoring": true, - "dataType": "string" - }, - "attributes": [ - { - "type": "Actual" - } - ], - "description": "The name of the EVSE in the string format as required by ISO 15118 and IEC 63119-2.", - "type": "string" - }, - "EVSEPower": { - "variable_name": "Power", - "characteristics": { - "unit": "W", - "maxLimit": 22000, - "supportsMonitoring": true, - "dataType": "decimal" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - }, - { - "type": "MaxSet", - "mutability": "ReadOnly" - } - ], - "description": " kW,The variableCharacteristic maxLimit, that holds the maximum power that this EVSE can provide, is required. The Actual value of the instantaneous (real) power is desired, but not required.", - "type": "number", - "default": "0" - }, - "EVSESupplyPhases": { - "variable_name": "SupplyPhases", - "characteristics": { - "supportsMonitoring": true, - "dataType": "integer" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "description": "Number of alternating current phases connected/available.", - "type": "integer", - "default": "0" - }, - "ISO15118EvseId": { - "variable_name": "ISO15118EvseId", - "characteristics": { - "supportsMonitoring": true, - "dataType": "string" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadWrite" - } - ], - "description": "The name of the EVSE in the string format as required by ISO 15118 and IEC 63119-2. Example: \"DE*ICE*E*1234567890*1\"", - "type": "string" - } - }, - "required": [ - "EVSEAvailabilityState", - "EVSEAvailable", - "EVSEPower", - "EVSESupplyPhases" - ] -} diff --git a/tests/config/v201/resources/component_schemas/custom/EVSE_2.json b/tests/config/v201/resources/component_schemas/custom/EVSE_2.json deleted file mode 100644 index 58ba4a477..000000000 --- a/tests/config/v201/resources/component_schemas/custom/EVSE_2.json +++ /dev/null @@ -1,130 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "description": "Schema for EVSE", - "type": "object", - "name": "EVSE", - "evse_id": 2, - "properties": { - "EVSEAllowReset": { - "variable_name": "AllowReset", - "characteristics": { - "supportsMonitoring": true, - "dataType": "boolean" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "description": "Can be used to announce that an EVSE can be reset individually", - "type": "boolean" - }, - "EVSEAvailabilityState": { - "variable_name": "AvailabilityState", - "characteristics": { - "supportsMonitoring": true, - "dataType": "OptionList", - "valuesList": "Available,Occupied,Reserved,Unavailable,Faulted" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "description": "This variable reports current availability state for the EVSE", - "type": "string", - "default": "Unavailable" - }, - "EVSEAvailable": { - "variable_name": "Available", - "characteristics": { - "supportsMonitoring": true, - "dataType": "boolean" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "description": "Component exists", - "type": "boolean", - "default": false - }, - "EvseId": { - "variable_name": "EvseId", - "characteristics": { - "supportsMonitoring": true, - "dataType": "string" - }, - "attributes": [ - { - "type": "Actual" - } - ], - "description": "The name of the EVSE in the string format as required by ISO 15118 and IEC 63119-2.", - "type": "string" - }, - "EVSEPower": { - "variable_name": "Power", - "characteristics": { - "unit": "W", - "maxLimit": 22000, - "supportsMonitoring": true, - "dataType": "decimal" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - }, - { - "type": "MaxSet", - "mutability": "ReadOnly" - } - ], - "description": " kW,The variableCharacteristic maxLimit, that holds the maximum power that this EVSE can provide, is required. The Actual value of the instantaneous (real) power is desired, but not required.", - "type": "number", - "default": "0" - }, - "EVSESupplyPhases": { - "variable_name": "SupplyPhases", - "characteristics": { - "supportsMonitoring": true, - "dataType": "integer" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "description": "Number of alternating current phases connected/available.", - "type": "integer", - "default": "0" - }, - "ISO15118EvseId": { - "variable_name": "ISO15118EvseId", - "characteristics": { - "supportsMonitoring": true, - "dataType": "string" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadWrite" - } - ], - "description": "The name of the EVSE in the string format as required by ISO 15118 and IEC 63119-2. Example: \"DE*ICE*E*1234567890*1\"", - "type": "string" - } - }, - "required": [ - "EVSEAvailabilityState", - "EVSEAvailable", - "EVSEPower", - "EVSESupplyPhases" - ] -} diff --git a/tests/config/v201/resources/component_schemas/standardized/UnitTestCtrlr.json b/tests/config/v201/resources/component_schemas/standardized/UnitTestCtrlr.json deleted file mode 100644 index 22a164329..000000000 --- a/tests/config/v201/resources/component_schemas/standardized/UnitTestCtrlr.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "description": "Schema for UnitTestCtrlr", - "name": "UnitTestCtrlr", - "type": "object", - "evse_id": 2, - "connector_id": 3, - "properties": { - "UnitTestPropertyA": { - "variable_name": "UnitTestPropertyAName", - "characteristics": { - "supportsMonitoring": true, - "dataType": "boolean" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadWrite" - } - ], - "default": "1", - "type": "boolean" - }, - "UnitTestPropertyB": { - "variable_name": "UnitTestPropertyBName", - "characteristics": { - "supportsMonitoring": false, - "dataType": "string" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "type": "string" - }, - "UnitTestPropertyC": { - "variable_name": "UnitTestPropertyCName", - "characteristics": { - "supportsMonitoring": false, - "dataType": "integer" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "type": "integer" - } - }, - "required": [ - "UnitTestPropertyA" - ] -} diff --git a/tests/config/v201/resources/config.json b/tests/config/v201/resources/config.json deleted file mode 100644 index 68ceeeb30..000000000 --- a/tests/config/v201/resources/config.json +++ /dev/null @@ -1,83 +0,0 @@ -[ - { - "name": "UnitTestCtrlr", - "evse_id": 2, - "connector_id": 3, - "variables": { - "UnitTestPropertyB": { - "variable_name": "UnitTestPropertyBName", - "attributes": { - "Actual": "test_value" - } - } - } - }, - { - "name": "EVSE", - "evse_id": 1, - "variables": { - "EVSEAvailable": { - "variable_name": "Available", - "attributes": { - "Actual": false - } - }, - "EVSEPower": { - "variable_name": "Power", - "attributes": { - "MaxSet": 44000, - "Actual": 2000 - } - }, - "EVSESupplyPhases": { - "variable_name": "SupplyPhases", - "attributes": { - "Actual": 6 - } - } - } - }, - { - "name": "Connector", - "evse_id": 2, - "connector_id": 1, - "variables": { - "ConnectorAvailable": { - "variable_name": "Available", - "attributes": { - "Actual": true - } - }, - "ConnectorType": { - "variable_name": "ConnectorType", - "attributes": { - "Actual": "cChaoJi" - } - } - } - }, - { - "name": "EVSE", - "evse_id": 2, - "variables": { - "EVSEAvailable": { - "variable_name": "Available", - "attributes": { - "Actual": true - } - }, - "EVSEPower": { - "variable_name": "Power", - "attributes": { - "MaxSet": 22000 - } - }, - "EVSEAvailabilityState": { - "variable_name": "AvailabilityState", - "attributes": { - "Actual": "Faulted" - } - } - } - } -] diff --git a/tests/config/v201/resources/config_not_existing_attribute.json b/tests/config/v201/resources/config_not_existing_attribute.json deleted file mode 100644 index 0647f93de..000000000 --- a/tests/config/v201/resources/config_not_existing_attribute.json +++ /dev/null @@ -1,15 +0,0 @@ -[ - { - "name": "UnitTestCtrlr", - "evse_id": 2, - "connector_id": 3, - "variables": { - "UnitTestPropertyB": { - "variable_name": "UnitTestPropertyBName", - "attributes": { - "MaxSet": "test_value" - } - } - } - } -] diff --git a/tests/config/v201/resources/config_wrong_attribute.json b/tests/config/v201/resources/config_wrong_attribute.json deleted file mode 100644 index cad579e42..000000000 --- a/tests/config/v201/resources/config_wrong_attribute.json +++ /dev/null @@ -1,14 +0,0 @@ -[ - { - "name": "EVSE", - "evse_id": 1, - "variables": { - "EVSEAvailable": { - "variable_name": "Available", - "attributes": { - "NotExisting": false - } - } - } - } -] diff --git a/tests/config/v201/resources/config_wrong_component.json b/tests/config/v201/resources/config_wrong_component.json deleted file mode 100644 index 185d0f7b8..000000000 --- a/tests/config/v201/resources/config_wrong_component.json +++ /dev/null @@ -1,14 +0,0 @@ -[ - { - "name": "NotExistingComponent", - "evse_id": 1, - "variables": { - "EVSEAvailable": { - "variable_name": "Available", - "attributes": { - "Actual": false - } - } - } - } -] diff --git a/tests/config/v201/resources/config_wrong_component_connectorid.json b/tests/config/v201/resources/config_wrong_component_connectorid.json deleted file mode 100644 index 0fe88648b..000000000 --- a/tests/config/v201/resources/config_wrong_component_connectorid.json +++ /dev/null @@ -1,15 +0,0 @@ -[ - { - "name": "UnitTestCtrlr", - "evse_id": 1, - "connector_id": 5, - "variables": { - "UnitTestPropertyB": { - "variable_name": "UnitTestPropertyBName", - "attributes": { - "Actual": "test_value" - } - } - } - } -] diff --git a/tests/config/v201/resources/config_wrong_variable.json b/tests/config/v201/resources/config_wrong_variable.json deleted file mode 100644 index 8927d12dc..000000000 --- a/tests/config/v201/resources/config_wrong_variable.json +++ /dev/null @@ -1,14 +0,0 @@ -[ - { - "name": "EVSE", - "evse_id": 1, - "variables": { - "EVSEAvailable": { - "variable_name": "Avail", - "attributes": { - "Actual": false - } - } - } - } -] diff --git a/tests/config/v201/resources_changed/component_schemas/custom/Connector_1_1.json b/tests/config/v201/resources_changed/component_schemas/custom/Connector_1_1.json deleted file mode 100644 index bc142c4fb..000000000 --- a/tests/config/v201/resources_changed/component_schemas/custom/Connector_1_1.json +++ /dev/null @@ -1,110 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "description": "Schema for Connector", - "type": "object", - "name": "Connector", - "evse_id": 1, - "connector_id": 1, - "properties": { - "ConnectorAvailabilityState": { - "variable_name": "AvailabilityState", - "characteristics": { - "supportsMonitoring": true, - "dataType": "OptionList", - "valuesList": "Available,Occupied,Reserved,Unavailable,Faulted" - }, - "attributes": [ - { - "type": "Actual" - } - ], - "description": "This variable reports current availability state for the Connector. Optional, because already reported in StatusNotification.", - "type": "string" - }, - "ConnectorAvailable": { - "variable_name": "Available", - "characteristics": { - "supportsMonitoring": true, - "dataType": "boolean" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "description": "Component exists", - "type": "boolean", - "default": false - }, - "ConnectorEnabled": { - "variable_name": "Enabled", - "characteristics": { - "supportsMonitoring": false, - "dataType": "boolean" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadWrite" - } - ] - }, - "ChargeProtocol": { - "variable_name": "ChargeProtocol", - "characteristics": { - "supportsMonitoring": true, - "dataType": "string" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "WriteOnly" - } - ], - "description": "The Charging Control Protocol applicable to a Connector. CHAdeMO: CHAdeMO protocol, ISO15118: ISO15118 V2G protocol (wired or wireless) as used with CCS, CPPWM: IEC61851-1 / SAE J1772 protocol (ELV DC & PWM signalling via Control Pilot wire), Uncontrolled: No charging power management applies (e.g. Schuko socket), Undetermined: Yet to be determined (e.g. before plugged in), Unknown: Not determinable, NOTE: ChargeProtocol is distinct from and orthogonal to connectorType.", - "type": "string" - }, - "ConnectorType": { - "variable_name": "ConnectorType", - "characteristics": { - "supportsMonitoring": true, - "dataType": "integer" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - }, - { - "type": "Target", - "mutability": "ReadWrite" - } - ], - "description": "A value of ConnectorEnumType (See part 2) plus additionally: cGBT, cChaoJi, OppCharge. Specific type of connector, including sub-variant information. Note: Distinct and orthogonal to Charging Protocol, Power Type, Phases.", - "type": "integer", - "default": "0" - }, - "ConnectorSupplyPhases": { - "variable_name": "SupplyPhases", - "characteristics": { - "supportsMonitoring": true, - "dataType": "integer" - }, - "attributes": [ - { - "type": "Target", - "mutability": "ReadOnly" - } - ], - "description": "Number of alternating current phases connected/available.", - "type": "integer", - "default": "0" - } - }, - "required": [ - "ConnectorAvailable", - "ConnectorSupplyPhases", - "ConnectorType" - ] -} diff --git a/tests/config/v201/resources_changed/component_schemas/custom/Connector_2_2.json b/tests/config/v201/resources_changed/component_schemas/custom/Connector_2_2.json deleted file mode 100644 index ff90fec7e..000000000 --- a/tests/config/v201/resources_changed/component_schemas/custom/Connector_2_2.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "description": "Schema for Connector", - "type": "object", - "name": "Connector", - "evse_id": 2, - "connector_id": 2, - "properties": { - "ConnectorAvailabilityState": { - "variable_name": "AvailabilityState", - "characteristics": { - "supportsMonitoring": true, - "dataType": "OptionList", - "valuesList": "Available,Unavailable" - }, - "attributes": [ - { - "type": "Actual" - } - ], - "description": "This variable reports current availability state for the Connector. Optional, because already reported in StatusNotification.", - "type": "string" - }, - "ConnectorAvailable": { - "variable_name": "Available", - "characteristics": { - "supportsMonitoring": true, - "dataType": "boolean" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "description": "Component exists", - "type": "boolean", - "default": false - } - }, - "required": [ - "ConnectorAvailable", - "ConnectorSupplyPhases", - "ConnectorType" - ] -} diff --git a/tests/config/v201/resources_changed/component_schemas/custom/EVSE_1.json b/tests/config/v201/resources_changed/component_schemas/custom/EVSE_1.json deleted file mode 100644 index ab3e74070..000000000 --- a/tests/config/v201/resources_changed/component_schemas/custom/EVSE_1.json +++ /dev/null @@ -1,119 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "description": "Schema for EVSE", - "type": "object", - "name": "EVSE", - "evse_id": 1, - "properties": { - "EVSEAllowReset": { - "variable_name": "AllowReset", - "characteristics": { - "supportsMonitoring": true, - "dataType": "boolean" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "description": "Can be used to announce that an EVSE can be reset individually", - "type": "boolean" - }, - "EVSEAvailabilityState": { - "variable_name": "AvailabilityState", - "characteristics": { - "supportsMonitoring": true, - "dataType": "OptionList", - "valuesList": "Available,Occupied,Reserved,Unavailable,Faulted" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "description": "This variable reports current availability state for the EVSE", - "type": "string", - "default": "Unavailable" - }, - "EVSEAvailable": { - "variable_name": "Available", - "characteristics": { - "supportsMonitoring": true, - "dataType": "boolean" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "description": "Component exists", - "type": "boolean", - "default": false - }, - "EvseId": { - "variable_name": "EvseId", - "characteristics": { - "supportsMonitoring": true, - "dataType": "string" - }, - "attributes": [ - { - "type": "Actual" - } - ], - "description": "The name of the EVSE in the string format as required by ISO 15118 and IEC 63119-2.", - "type": "string" - }, - "EVSEPower": { - "variable_name": "Power", - "characteristics": { - "unit": "kW", - "maxLimit": 22000, - "supportsMonitoring": true, - "dataType": "decimal" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - }, - { - "type": "MaxSet", - "mutability": "ReadOnly" - }, - { - "type": "Target", - "mutability": "ReadWrite" - } - ], - "description": " kW,The variableCharacteristic maxLimit, that holds the maximum power that this EVSE can provide, is required. The Actual value of the instantaneous (real) power is desired, but not required.", - "type": "number", - "default": "0" - }, - "EVSESupplyPhases": { - "variable_name": "SupplyPhases", - "characteristics": { - "supportsMonitoring": true, - "dataType": "integer" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "description": "Number of alternating current phases connected/available.", - "type": "integer", - "default": "0" - } - }, - "required": [ - "EVSEAvailabilityState", - "EVSEAvailable", - "EVSEPower", - "EVSESupplyPhases" - ] -} diff --git a/tests/config/v201/resources_changed/component_schemas/custom/EVSE_2.json b/tests/config/v201/resources_changed/component_schemas/custom/EVSE_2.json deleted file mode 100644 index 28a9184d8..000000000 --- a/tests/config/v201/resources_changed/component_schemas/custom/EVSE_2.json +++ /dev/null @@ -1,126 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "description": "Schema for EVSE", - "type": "object", - "name": "EVSE", - "evse_id": 2, - "properties": { - "EVSEAllowReset": { - "variable_name": "AllowReset", - "characteristics": { - "supportsMonitoring": true, - "dataType": "boolean" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "description": "Can be used to announce that an EVSE can be reset individually", - "type": "boolean" - }, - "EVSEAvailabilityState": { - "variable_name": "AvailabilityState", - "characteristics": { - "supportsMonitoring": false, - "dataType": "string", - "valuesList": "Available,Occupied,Reserved,Unavailable,Faulted" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "description": "This variable reports current availability state for the EVSE", - "type": "string", - "default": "Unavailable" - }, - "EVSEAvailable": { - "variable_name": "Available", - "characteristics": { - "supportsMonitoring": true, - "dataType": "boolean" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "description": "Component exists", - "type": "boolean", - "default": false - }, - "EvseId": { - "variable_name": "EvseId", - "characteristics": { - "supportsMonitoring": true, - "dataType": "string" - }, - "attributes": [ - { - "type": "Actual" - } - ], - "description": "The name of the EVSE in the string format as required by ISO 15118 and IEC 63119-2.", - "type": "string" - }, - "EVSEPower": { - "variable_name": "Power", - "characteristics": { - "unit": "W", - "maxLimit": 22000, - "supportsMonitoring": true, - "dataType": "decimal" - }, - "attributes": [ - { - "type": "MaxSet", - "mutability": "ReadOnly" - } - ], - "description": " kW,The variableCharacteristic maxLimit, that holds the maximum power that this EVSE can provide, is required. The Actual value of the instantaneous (real) power is desired, but not required.", - "type": "number", - "default": "0" - }, - "EVSESupplyPhases": { - "variable_name": "SupplyPhases", - "characteristics": { - "supportsMonitoring": true, - "dataType": "integer" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "description": "Number of alternating current phases connected/available.", - "type": "integer", - "default": "0" - }, - "ISO15118EvseId": { - "variable_name": "ISO15118EvseId", - "characteristics": { - "supportsMonitoring": true, - "dataType": "string" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadWrite" - } - ], - "description": "The name of the EVSE in the string format as required by ISO 15118 and IEC 63119-2. Example: \"DE*ICE*E*1234567890*1\"", - "type": "string" - } - }, - "required": [ - "EVSEAvailabilityState", - "EVSEAvailable", - "EVSEPower", - "EVSESupplyPhases" - ] -} diff --git a/tests/config/v201/resources_changed/component_schemas/custom/EVSE_3.json b/tests/config/v201/resources_changed/component_schemas/custom/EVSE_3.json deleted file mode 100644 index d241fb7e2..000000000 --- a/tests/config/v201/resources_changed/component_schemas/custom/EVSE_3.json +++ /dev/null @@ -1,130 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "description": "Schema for EVSE", - "type": "object", - "name": "EVSE", - "evse_id": 3, - "properties": { - "EVSEAllowReset": { - "variable_name": "AllowReset", - "characteristics": { - "supportsMonitoring": true, - "dataType": "boolean" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "description": "Can be used to announce that an EVSE can be reset individually", - "type": "boolean" - }, - "EVSEAvailabilityState": { - "variable_name": "AvailabilityState", - "characteristics": { - "supportsMonitoring": true, - "dataType": "OptionList", - "valuesList": "Available,Occupied,Reserved,Unavailable,Faulted" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "description": "This variable reports current availability state for the EVSE", - "type": "string", - "default": "Unavailable" - }, - "EVSEAvailable": { - "variable_name": "Available", - "characteristics": { - "supportsMonitoring": true, - "dataType": "boolean" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "description": "Component exists", - "type": "boolean", - "default": false - }, - "EvseId": { - "variable_name": "EvseId", - "characteristics": { - "supportsMonitoring": true, - "dataType": "string" - }, - "attributes": [ - { - "type": "Actual" - } - ], - "description": "The name of the EVSE in the string format as required by ISO 15118 and IEC 63119-2.", - "type": "string" - }, - "EVSEPower": { - "variable_name": "Power", - "characteristics": { - "unit": "W", - "maxLimit": 22000, - "supportsMonitoring": true, - "dataType": "decimal" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - }, - { - "type": "MaxSet", - "mutability": "ReadOnly" - } - ], - "description": " kW,The variableCharacteristic maxLimit, that holds the maximum power that this EVSE can provide, is required. The Actual value of the instantaneous (real) power is desired, but not required.", - "type": "number", - "default": "0" - }, - "EVSESupplyPhases": { - "variable_name": "SupplyPhases", - "characteristics": { - "supportsMonitoring": true, - "dataType": "integer" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "description": "Number of alternating current phases connected/available.", - "type": "integer", - "default": "0" - }, - "ISO15118EvseId": { - "variable_name": "ISO15118EvseId", - "characteristics": { - "supportsMonitoring": true, - "dataType": "string" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadWrite" - } - ], - "description": "The name of the EVSE in the string format as required by ISO 15118 and IEC 63119-2. Example: \"DE*ICE*E*1234567890*1\"", - "type": "string" - } - }, - "required": [ - "EVSEAvailabilityState", - "EVSEAvailable", - "EVSEPower", - "EVSESupplyPhases" - ] -} diff --git a/tests/config/v201/resources_changed/component_schemas/standardized/UnitTestCtrlr.json b/tests/config/v201/resources_changed/component_schemas/standardized/UnitTestCtrlr.json deleted file mode 100644 index 8627dae06..000000000 --- a/tests/config/v201/resources_changed/component_schemas/standardized/UnitTestCtrlr.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "description": "Schema for UnitTestCtrlr", - "name": "UnitTestCtrlr", - "type": "object", - "evse_id": 2, - "connector_id": 3, - "properties": { - "UnitTestPropertyA": { - "variable_name": "UnitTestPropertyAName", - "characteristics": { - "supportsMonitoring": true, - "dataType": "string" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadWrite" - } - ], - "default": "1", - "type": "string" - }, - "UnitTestPropertyB": { - "variable_name": "UnitTestPropertyBName", - "characteristics": { - "supportsMonitoring": false, - "dataType": "string" - }, - "attributes": [ - { - "type": "Actual", - "mutability": "ReadOnly" - } - ], - "type": "string" - } - }, - "required": [ - "UnitTestPropertyA" - ] -} diff --git a/tests/config/v201/resources_changed/config.json b/tests/config/v201/resources_changed/config.json deleted file mode 100644 index 2b49aab23..000000000 --- a/tests/config/v201/resources_changed/config.json +++ /dev/null @@ -1,57 +0,0 @@ -[ - { - "name": "EVSE", - "evse_id": 1, - "variables": { - "EVSESupplyPhases": { - "variable_name": "SupplyPhases", - "attributes": { - "Actual": 2 - } - } - } - }, - { - "name": "Connector", - "evse_id": 2, - "connector_id": 1, - "variables": { - "ConnectorAvailable": { - "variable_name": "Available", - "attributes": { - "Actual": true - } - }, - "ConnectorType": { - "variable_name": "ConnectorType", - "attributes": { - "Actual": "OppCharge" - } - } - } - }, - { - "name": "EVSE", - "evse_id": 2, - "variables": { - "EVSEAvailable": { - "variable_name": "Available", - "attributes": { - "Actual": false - } - }, - "EVSEPower": { - "variable_name": "Power", - "attributes": { - "MaxSet": 22000 - } - }, - "EVSEAvailabilityState": { - "variable_name": "AvailabilityState", - "attributes": { - "Actual": "Faulted" - } - } - } - } -] diff --git a/tests/lib/ocpp/v201/test_init_device_model_db.cpp b/tests/lib/ocpp/v201/test_init_device_model_db.cpp index e424458ac..89a868966 100644 --- a/tests/lib/ocpp/v201/test_init_device_model_db.cpp +++ b/tests/lib/ocpp/v201/test_init_device_model_db.cpp @@ -13,9 +13,6 @@ #include -// TODO mz add removed tests with config: add component config for this and check if they also fail -// TODO mz remove config.json for tests: not needed anymore - namespace ocpp::v201 { class InitDeviceModelDbTest : public DatabaseTestingUtils { @@ -395,8 +392,7 @@ TEST_F(InitDeviceModelDbTest, init_db) { AttributeEnum::Actual, "false")); EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "SupplyPhases", std::nullopt, AttributeEnum::Actual, "2")); - // // Variable does not exist so it could not set the value. - // EXPECT_FALSE(variable_exists("EVSE", std::nullopt, 1, std::nullopt, "AvalableEVSEThingie", std::nullopt)); + // Variable was removed, so it will be set to the default value again. EXPECT_TRUE( attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "Power", std::nullopt, AttributeEnum::Actual, "0")); @@ -404,7 +400,7 @@ TEST_F(InitDeviceModelDbTest, init_db) { EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "Power", std::nullopt, AttributeEnum::MaxSet, "44000")); // // Component does not exist so it could not set anything. - // EXPECT_FALSE(component_exists("UnitTestCtrlr", std::nullopt, 1, 5)); + EXPECT_FALSE(component_exists("UnitTestCtrlr", std::nullopt, 1, 5)); } // TEST_F(InitDeviceModelDbTest, insert_values) { From 8a2ac179f8ef46559b201397c93aa0a161dfcb49 Mon Sep 17 00:00:00 2001 From: "Maaike Zijderveld, iolar" Date: Wed, 7 Aug 2024 12:12:03 +0200 Subject: [PATCH 05/12] Remove unused test. Add check integrity function to see if variables that are required have a (default) value set. Signed-off-by: Maaike Zijderveld, iolar --- lib/ocpp/v201/init_device_model_db.cpp | 64 ++++++++++++++ .../ocpp/v201/test_init_device_model_db.cpp | 86 ------------------- 2 files changed, 64 insertions(+), 86 deletions(-) diff --git a/lib/ocpp/v201/init_device_model_db.cpp b/lib/ocpp/v201/init_device_model_db.cpp index 845f961cf..06fbe1adb 100644 --- a/lib/ocpp/v201/init_device_model_db.cpp +++ b/lib/ocpp/v201/init_device_model_db.cpp @@ -19,6 +19,7 @@ const static std::string CUSTOM_COMPONENT_CONFIG_DIR = "custom"; namespace ocpp::v201 { // Forward declarations. +static void check_integrity(const std::map>& component_configs); static bool is_same_component_key(const ComponentKey& component_key1, const ComponentKey& component_key2); static bool is_same_attribute_type(const VariableAttribute attribute1, const VariableAttribute& attribute2); static bool is_attribute_different(const VariableAttribute& attribute1, const VariableAttribute& attribute2); @@ -29,6 +30,7 @@ static bool is_same_variable(const DeviceModelVariable& v1, const DeviceModelVar static bool is_variable_different(const DeviceModelVariable& v1, const DeviceModelVariable& v2); static std::string get_string_value_from_json(const json& value); static std::string get_component_name_for_logging(const ComponentKey& component); +static std::string get_variable_name_for_logging(const DeviceModelVariable& variable); InitDeviceModelDb::InitDeviceModelDb(const std::filesystem::path& database_path, const std::filesystem::path& migration_files_path) : @@ -55,6 +57,9 @@ void InitDeviceModelDb::initialize_database(const std::filesystem::path& config_ // Get component schemas from the filesystem. std::map> component_configs = get_all_component_configs(config_path); + // Check if the config is consistent (fe has a value when required). + check_integrity(component_configs); + // Remove components from db if they do not exist in the component schemas if (this->database_exists) { remove_not_existing_components_from_db(component_configs, existing_components); @@ -996,6 +1001,51 @@ void from_json(const json& j, DeviceModelVariable& c) { } } +/// +/// \brief Check integrity of config. +/// +/// This will do some checks if the config is correct, for example if all required attributes have a value. +/// +/// \param component_configs Read config from the file system. +/// +static void check_integrity(const std::map>& component_configs) { + for (const auto& [component_key, variables] : component_configs) { + for (const DeviceModelVariable& variable : variables) { + if (!variable.required) { + // Variable is not required, move to next variable. + continue; + } + + if (variable.default_actual_value.has_value()) { + // There is a default value set, so for this required variable, we have a value (maybe there is a + // value set as well but since we also have a default value, we don't have to check that) + continue; + } + + const auto& actual_attribute = std::find_if( + variable.attributes.begin(), variable.attributes.end(), [](const DbVariableAttribute& attribute) { + if (attribute.variable_attribute.type.has_value() && + attribute.variable_attribute.type.value() == AttributeEnum::Actual) { + return true; + } + return false; + }); + + if (actual_attribute == variable.attributes.end()) { + EVLOG_AND_THROW(InitDeviceModelDbError("Could not find required Actual attribute for variable " + + get_variable_name_for_logging(variable) + " of component " + + get_component_name_for_logging(component_key))); + } + + if (!actual_attribute->variable_attribute.value.has_value()) { + EVLOG_AND_THROW(InitDeviceModelDbError("No value set for Actual attribute for required variable " + + get_variable_name_for_logging(variable) + " of component " + + get_component_name_for_logging(component_key))); + } + } + } +} + /* Below functions check if components, attributes, variables, characteristics are the same / equal in the schema * and database. The 'is_same' functions check if two objects are the same, comparing their unique properties. The * is_..._different functions check if the objects properties are different (and as a result should be changed in @@ -1166,4 +1216,18 @@ static std::string get_component_name_for_logging(const ComponentKey& component) return component_name; } +/// +/// \brief Get a string that describes the variable, used for logging. +/// +/// This includes the name and the instance of the variable +/// +/// \param variable The variable to get the string from. +/// \return The logging string. +/// +static std::string get_variable_name_for_logging(const DeviceModelVariable& variable) { + const std::string variable_name = + variable.name + (variable.instance.has_value() ? ", instance" + variable.instance.value() : ""); + return variable_name; +} + } // namespace ocpp::v201 diff --git a/tests/lib/ocpp/v201/test_init_device_model_db.cpp b/tests/lib/ocpp/v201/test_init_device_model_db.cpp index 89a868966..790ff9555 100644 --- a/tests/lib/ocpp/v201/test_init_device_model_db.cpp +++ b/tests/lib/ocpp/v201/test_init_device_model_db.cpp @@ -403,92 +403,6 @@ TEST_F(InitDeviceModelDbTest, init_db) { EXPECT_FALSE(component_exists("UnitTestCtrlr", std::nullopt, 1, 5)); } -// TEST_F(InitDeviceModelDbTest, insert_values) { -// /* This test will test if the config and default values are correctly set. We test this twice: first an initial -// * config, then a changed configuration. -// */ - -// InitDeviceModelDb db(DATABASE_PATH, MIGRATION_FILES_PATH); - -// // Database should not exist yet. But since it does a filesystem check and we have an in memory database, we -// // explicitly set the variable here. -// db.database_exists = false; -// // First create the database. -// EXPECT_NO_THROW(db.initialize_database(SCHEMAS_PATH, true)); -// // Then insert the config and default values. -// EXPECT_TRUE(db.insert_config_and_default_values(SCHEMAS_PATH, CONFIG_PATH)); - -// // Test some values. -// EXPECT_TRUE(attribute_has_value("UnitTestCtrlr", std::nullopt, 2, 3, "UnitTestPropertyBName", std::nullopt, -// AttributeEnum::Actual, "test_value")); -// // Test some not default values. -// EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "Available", std::nullopt, -// AttributeEnum::Actual, "false")); -// EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "Power", std::nullopt, -// AttributeEnum::MaxSet, -// "44000")); -// EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "Power", std::nullopt, -// AttributeEnum::Actual, -// "2000")); -// EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "SupplyPhases", std::nullopt, -// AttributeEnum::Actual, "6")); -// EXPECT_TRUE( -// attribute_has_value("Connector", std::nullopt, 2, 1, "Available", std::nullopt, AttributeEnum::Actual, -// "true")); -// EXPECT_TRUE(attribute_has_value("Connector", std::nullopt, 2, 1, "ConnectorType", std::nullopt, -// AttributeEnum::Actual, "cChaoJi")); -// EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "Available", std::nullopt, -// AttributeEnum::Actual, "false")); -// EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 2, std::nullopt, "Available", std::nullopt, -// AttributeEnum::Actual, "true")); -// EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 2, std::nullopt, "Power", std::nullopt, -// AttributeEnum::MaxSet, -// "22000")); -// EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 2, std::nullopt, "AvailabilityState", std::nullopt, -// AttributeEnum::Actual, "Faulted")); - -// // Default value -// EXPECT_TRUE(attribute_has_value("Connector", std::nullopt, 1, 1, "Available", std::nullopt, -// AttributeEnum::Actual, -// "false")); -// EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "AvailabilityState", std::nullopt, -// AttributeEnum::Actual, "Unavailable")); -// EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 2, std::nullopt, "SupplyPhases", std::nullopt, -// AttributeEnum::Actual, "0")); -// EXPECT_TRUE( -// attribute_has_value("Connector", std::nullopt, 1, 1, "ConnectorType", std::nullopt, AttributeEnum::Actual, -// "")); - -// // Insert new config. -// // First set the source of an attribute to something else than 'default' -// set_attribute_source("Connector", std::nullopt, 2, 1, "ConnectorType", std::nullopt, AttributeEnum::Actual, -// "test"); - -// EXPECT_TRUE(db.insert_config_and_default_values(SCHEMAS_PATH, CONFIG_PATH_CHANGED)); - -// // Source was not 'default', connector type not changed. -// EXPECT_TRUE(attribute_has_value("Connector", std::nullopt, 2, 1, "ConnectorType", std::nullopt, -// AttributeEnum::Actual, "cChaoJi")); - -// // Check changed values. -// EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 2, std::nullopt, "Available", std::nullopt, -// AttributeEnum::Actual, "false")); -// EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "SupplyPhases", std::nullopt, -// AttributeEnum::Actual, "2")); -// // // Variable does not exist so it could not set the value. -// // EXPECT_FALSE(variable_exists("EVSE", std::nullopt, 1, std::nullopt, "AvalableEVSEThingie", std::nullopt)); -// // Variable was removed, so it will be set to the default value again. -// EXPECT_TRUE( -// attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "Power", std::nullopt, AttributeEnum::Actual, -// "0")); -// // Default value only applies to 'Actual', not 'MaxSet' -// EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 1, std::nullopt, "Power", std::nullopt, -// AttributeEnum::MaxSet, -// "44000")); -// // // Component does not exist so it could not set anything. -// // EXPECT_FALSE(component_exists("UnitTestCtrlr", std::nullopt, 1, 5)); -// } - TEST_F(InitDeviceModelDbTest, wrong_migration_file_path) { InitDeviceModelDb db(DATABASE_PATH, "/tmp/thisdoesnotexisthopefully"); // The migration script is not correct (there is none in the given folder), this should throw an exception. From ef3ff781db6d7d2c2a21c87cfeb9961b32d8518c Mon Sep 17 00:00:00 2001 From: "Maaike Zijderveld, iolar" Date: Wed, 7 Aug 2024 18:27:38 +0200 Subject: [PATCH 06/12] Add integrity check if type is correct. Add extra tests for the integrity checks. Signed-off-by: Maaike Zijderveld, iolar --- include/ocpp/common/utils.hpp | 1 + lib/ocpp/common/utils.cpp | 4 + lib/ocpp/v201/init_device_model_db.cpp | 155 +++++++++++++++--- tests/CMakeLists.txt | 7 +- .../standardized/UnitTestCtrlr.json | 2 +- .../custom/Connector_1_1.json | 10 +- .../custom/Connector_2_2.json | 4 +- .../custom/Connector_1_1.json | 115 +++++++++++++ .../custom/EVSE_1.json | 120 ++++++++++++++ .../standardized/UnitTestCtrlr.json | 75 +++++++++ .../custom/Connector_1_1.json | 115 +++++++++++++ .../custom/EVSE_1.json | 120 ++++++++++++++ .../standardized/UnitTestCtrlr.json | 59 +++++++ .../ocpp/v201/test_init_device_model_db.cpp | 45 +++++ 14 files changed, 800 insertions(+), 32 deletions(-) create mode 100644 tests/config/v201/resources_wrong/component_config_required_no_value/custom/Connector_1_1.json create mode 100644 tests/config/v201/resources_wrong/component_config_required_no_value/custom/EVSE_1.json create mode 100644 tests/config/v201/resources_wrong/component_config_required_no_value/standardized/UnitTestCtrlr.json create mode 100644 tests/config/v201/resources_wrong/component_config_wrong_value_type/custom/Connector_1_1.json create mode 100644 tests/config/v201/resources_wrong/component_config_wrong_value_type/custom/EVSE_1.json create mode 100644 tests/config/v201/resources_wrong/component_config_wrong_value_type/standardized/UnitTestCtrlr.json diff --git a/include/ocpp/common/utils.hpp b/include/ocpp/common/utils.hpp index e3698a110..2df209118 100644 --- a/include/ocpp/common/utils.hpp +++ b/include/ocpp/common/utils.hpp @@ -19,6 +19,7 @@ std::tuple is_positive_integer(const std::string& value); bool is_decimal_number(const std::string& value); bool is_rfc3339_datetime(const std::string& value); +bool is_boolean(const std::string& value); } // namespace ocpp diff --git a/lib/ocpp/common/utils.cpp b/lib/ocpp/common/utils.cpp index 1054cb202..a0823312b 100644 --- a/lib/ocpp/common/utils.cpp +++ b/lib/ocpp/common/utils.cpp @@ -86,4 +86,8 @@ bool is_rfc3339_datetime(const std::string& value) { return std::regex_match(value, datetime_pattern); } +bool is_boolean(const std::string& value) { + return iequals(value, "true") || iequals(value, "false"); +} + } // namespace ocpp diff --git a/lib/ocpp/v201/init_device_model_db.cpp b/lib/ocpp/v201/init_device_model_db.cpp index 06fbe1adb..ab45d375b 100644 --- a/lib/ocpp/v201/init_device_model_db.cpp +++ b/lib/ocpp/v201/init_device_model_db.cpp @@ -20,6 +20,9 @@ namespace ocpp::v201 { // Forward declarations. static void check_integrity(const std::map>& component_configs); +static std::optional check_integrity_required_value(const DeviceModelVariable& variable); +static std::vector check_integrity_value_type(const DeviceModelVariable& variable); +static bool value_is_of_type(const std::string& value, const DataEnum& type); static bool is_same_component_key(const ComponentKey& component_key1, const ComponentKey& component_key2); static bool is_same_attribute_type(const VariableAttribute attribute1, const VariableAttribute& attribute2); static bool is_attribute_different(const VariableAttribute& attribute1, const VariableAttribute& attribute2); @@ -1001,49 +1004,153 @@ void from_json(const json& j, DeviceModelVariable& c) { } } +/* Below functions check the integrity of the component config, for example if the type is correct or if a value is set + * when a variable is required. + */ + /// /// \brief Check integrity of config. /// /// This will do some checks if the config is correct, for example if all required attributes have a value. +/// It will print all found integrity errors in the logging. /// /// \param component_configs Read config from the file system. +/// \throws InitDeviceModelDbError when at least one of the components / variables / attributes has an error. /// static void check_integrity(const std::map>& component_configs) { + std::string final_error_message = "Check integrity failed:\n"; + bool has_error = false; for (const auto& [component_key, variables] : component_configs) { + bool has_component_error = false; + std::string component_errors = "- Component " + get_component_name_for_logging(component_key) + '\n'; for (const DeviceModelVariable& variable : variables) { - if (!variable.required) { - // Variable is not required, move to next variable. - continue; + std::vector error_messages; + if (variable.required) { + std::optional error_message = check_integrity_required_value(variable); + if (error_message.has_value()) { + error_messages.push_back(error_message.value()); + } } - if (variable.default_actual_value.has_value()) { - // There is a default value set, so for this required variable, we have a value (maybe there is a - // value set as well but since we also have a default value, we don't have to check that) - continue; + std::vector value_type_errors = check_integrity_value_type(variable); + for (const std::string& error : value_type_errors) { + error_messages.push_back(error); } - const auto& actual_attribute = std::find_if( - variable.attributes.begin(), variable.attributes.end(), [](const DbVariableAttribute& attribute) { - if (attribute.variable_attribute.type.has_value() && - attribute.variable_attribute.type.value() == AttributeEnum::Actual) { - return true; - } - return false; - }); - - if (actual_attribute == variable.attributes.end()) { - EVLOG_AND_THROW(InitDeviceModelDbError("Could not find required Actual attribute for variable " + - get_variable_name_for_logging(variable) + " of component " + - get_component_name_for_logging(component_key))); + if (!error_messages.empty()) { + has_error = true; + has_component_error = true; + std::string error = " - Variable " + get_variable_name_for_logging(variable) + ", errors:\n"; + for (const std::string& error_message : error_messages) { + error += " - " + error_message + '\n'; + } + component_errors.append(error); } + } + + if (has_component_error) { + final_error_message.append(component_errors); + } + } - if (!actual_attribute->variable_attribute.value.has_value()) { - EVLOG_AND_THROW(InitDeviceModelDbError("No value set for Actual attribute for required variable " + - get_variable_name_for_logging(variable) + " of component " + - get_component_name_for_logging(component_key))); + if (has_error) { + EVLOG_AND_THROW(InitDeviceModelDbError(final_error_message)); + } +} + +/// +/// \brief Check if a required device model variable has a value set or a default value. +/// \param variable The variable to check. +/// \return std::nullopt if the required variable has a value or default value. Error message if it is not. +/// +static std::optional check_integrity_required_value(const DeviceModelVariable& variable) { + const auto& actual_attribute = + std::find_if(variable.attributes.begin(), variable.attributes.end(), [](const DbVariableAttribute& attribute) { + if (attribute.variable_attribute.type.has_value() && + attribute.variable_attribute.type.value() == AttributeEnum::Actual) { + return true; } + return false; + }); + + if (actual_attribute == variable.attributes.end()) { + return "Could not find required Actual attribute."; + } + + if (variable.default_actual_value.has_value()) { + // There is a default value set, so for this required variable, we have a value (maybe there is a + // value set as well but since we also have a default value, we don't have to check that) + return std::nullopt; + } + + if (!actual_attribute->variable_attribute.value.has_value()) { + return "No value set for Actual attribute for required variable."; + } + + return std::nullopt; +} + +/// +/// \brief Check if the variable attributes have the given type. +/// \param variable Variable to check the attributes from. +/// \return The errors if there are any, otherwise an empty vector. +/// +static std::vector check_integrity_value_type(const DeviceModelVariable& variable) { + const DataEnum& type = variable.characteristics.dataType; + std::vector errors; + if (variable.default_actual_value.has_value()) { + if (!value_is_of_type(variable.default_actual_value.value(), type)) { + errors.push_back("Default value (" + variable.default_actual_value.value() + + ") has wrong type, type should have been " + conversions::data_enum_to_string(type) + "."); } } + + for (const DbVariableAttribute& attribute : variable.attributes) { + if (attribute.variable_attribute.value.has_value()) { + if (!value_is_of_type(attribute.variable_attribute.value.value(), type)) { + errors.push_back( + "Attribute " + + (attribute.variable_attribute.type.has_value() + ? "'" + conversions::attribute_enum_to_string(attribute.variable_attribute.type.value()) + "'" + : "") + + " value (" + attribute.variable_attribute.value.value().get() + + ") has wrong type, type should have been: " + conversions::data_enum_to_string(type) + "."); + } + } + } + + return errors; +} + +/// +/// \brief Check if a value string is of the given enum type. +/// \param value The value to check. +/// \param type The type. +/// \return True if value is of the given type. +/// +static bool value_is_of_type(const std::string& value, const DataEnum& type) { + if (value.empty()) { + // We can not check if the type of the values that are empty are valid. + return true; + } + + switch (type) { + case DataEnum::string: + return true; + case DataEnum::decimal: + return is_integer(value) || is_decimal_number(value); + case DataEnum::integer: + return is_integer(value); + case DataEnum::dateTime: + return is_rfc3339_datetime(value); + case DataEnum::boolean: + return is_boolean(value); + case DataEnum::OptionList: + case DataEnum::SequenceList: + case DataEnum::MemberList: + return true; + } + return false; } /* Below functions check if components, attributes, variables, characteristics are the same / equal in the schema diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index e49be7987..fbd59ad9c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -4,12 +4,15 @@ set(MIGRATION_FILES_DEVICE_MODEL_LOCATION_V201 "${CMAKE_CURRENT_BINARY_DIR}/reso set(DEVICE_MODEL_DB_LOCATION_V201 "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/everest/modules/OCPP201/device_model_storage.db") set(DEVICE_MODEL_RESOURCES_LOCATION_V201 "${CMAKE_CURRENT_BINARY_DIR}/resources/config/v201") set(DEVICE_MODEL_RESOURCES_CHANGED_LOCATION_V201 "${CMAKE_CURRENT_BINARY_DIR}/resources/config/v201/changed") +set(DEVICE_MODEL_RESOURCES_WRONG_LOCATION_V201 "${CMAKE_CURRENT_BINARY_DIR}/resources/config/v201/wrong") set(DEVICE_MODEL_CURRENT_RESOURCES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/config/v201/resources) set(DEVICE_MODEL_CURRENT_CHANGED_RESOURCES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/config/v201/resources_changed) +set(DEVICE_MODEL_CURRENT_WRONG_RESOURCES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/config/v201/resources_wrong) set(DEVICE_MODEL_EXAMPLE_SCHEMAS_LOCATION_V201 "${CMAKE_CURRENT_BINARY_DIR}/resources/example_config/v201/component_config") set(DEVICE_MODEL_CURRENT_EXAMPLE_SCHEMAS_LOCATION_V201 "${PROJECT_SOURCE_DIR}/config/v201/component_config") -add_executable(libocpp_unit_tests) +add_executable(libocpp_unit_tests + config/v201/resources_wrong/component_config_required_no_value/standardized/UnitTestCtrlr.json) target_compile_definitions(libocpp_unit_tests PRIVATE @@ -33,6 +36,8 @@ add_custom_command(TARGET libocpp_unit_tests POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${DEVICE_MODEL_CURRENT_RESOURCES_DIR} ${DEVICE_MODEL_RESOURCES_LOCATION_V201} COMMAND ${CMAKE_COMMAND} -E remove_directory ${DEVICE_MODEL_RESOURCES_CHANGED_LOCATION_V201} COMMAND ${CMAKE_COMMAND} -E copy_directory ${DEVICE_MODEL_CURRENT_CHANGED_RESOURCES_DIR} ${DEVICE_MODEL_RESOURCES_CHANGED_LOCATION_V201} + COMMAND ${CMAKE_COMMAND} -E remove_directory ${DEVICE_MODEL_RESOURCES_WRONG_LOCATION_V201} + COMMAND ${CMAKE_COMMAND} -E copy_directory ${DEVICE_MODEL_CURRENT_WRONG_RESOURCES_DIR} ${DEVICE_MODEL_RESOURCES_WRONG_LOCATION_V201} COMMAND ${CMAKE_COMMAND} -E remove_directory ${DEVICE_MODEL_EXAMPLE_SCHEMAS_LOCATION_V201} COMMAND ${CMAKE_COMMAND} -E copy_directory ${DEVICE_MODEL_CURRENT_EXAMPLE_SCHEMAS_LOCATION_V201} ${DEVICE_MODEL_EXAMPLE_SCHEMAS_LOCATION_V201} ) diff --git a/tests/config/v201/resources/component_config/standardized/UnitTestCtrlr.json b/tests/config/v201/resources/component_config/standardized/UnitTestCtrlr.json index 896c1bb9c..e282268b6 100644 --- a/tests/config/v201/resources/component_config/standardized/UnitTestCtrlr.json +++ b/tests/config/v201/resources/component_config/standardized/UnitTestCtrlr.json @@ -18,7 +18,7 @@ "mutability": "ReadWrite" } ], - "default": "1", + "default": true, "type": "boolean" }, "UnitTestPropertyB": { diff --git a/tests/config/v201/resources_changed/component_config/custom/Connector_1_1.json b/tests/config/v201/resources_changed/component_config/custom/Connector_1_1.json index 642e8109c..611661207 100644 --- a/tests/config/v201/resources_changed/component_config/custom/Connector_1_1.json +++ b/tests/config/v201/resources_changed/component_config/custom/Connector_1_1.json @@ -69,7 +69,7 @@ "variable_name": "ConnectorType", "characteristics": { "supportsMonitoring": true, - "dataType": "integer" + "dataType": "string" }, "attributes": [ { @@ -83,8 +83,8 @@ } ], "description": "A value of ConnectorEnumType (See part 2) plus additionally: cGBT, cChaoJi, OppCharge. Specific type of connector, including sub-variant information. Note: Distinct and orthogonal to Charging Protocol, Power Type, Phases.", - "type": "integer", - "default": "0" + "type": "string", + "default": "cCCS2" }, "ConnectorSupplyPhases": { "variable_name": "SupplyPhases", @@ -96,6 +96,10 @@ { "type": "Target", "mutability": "ReadOnly" + }, + { + "type": "Actual", + "mutability": "ReadOnly" } ], "description": "Number of alternating current phases connected/available.", diff --git a/tests/config/v201/resources_changed/component_config/custom/Connector_2_2.json b/tests/config/v201/resources_changed/component_config/custom/Connector_2_2.json index ff90fec7e..e15e8c7a5 100644 --- a/tests/config/v201/resources_changed/component_config/custom/Connector_2_2.json +++ b/tests/config/v201/resources_changed/component_config/custom/Connector_2_2.json @@ -39,8 +39,6 @@ } }, "required": [ - "ConnectorAvailable", - "ConnectorSupplyPhases", - "ConnectorType" + "ConnectorAvailable" ] } diff --git a/tests/config/v201/resources_wrong/component_config_required_no_value/custom/Connector_1_1.json b/tests/config/v201/resources_wrong/component_config_required_no_value/custom/Connector_1_1.json new file mode 100644 index 000000000..4e00c9bc1 --- /dev/null +++ b/tests/config/v201/resources_wrong/component_config_required_no_value/custom/Connector_1_1.json @@ -0,0 +1,115 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Schema for Connector", + "type": "object", + "name": "Connector", + "evse_id": 1, + "connector_id": 1, + "properties": { + "ConnectorAvailabilityState": { + "variable_name": "AvailabilityState", + "characteristics": { + "supportsMonitoring": true, + "dataType": "OptionList", + "valuesList": "Available,Occupied,Reserved,Unavailable,Faulted" + }, + "attributes": [ + { + "type": "Actual" + } + ], + "description": "This variable reports current availability state for the Connector. Optional, because already reported in StatusNotification.", + "type": "string" + }, + "ConnectorAvailable": { + "variable_name": "Available", + "characteristics": { + "supportsMonitoring": true, + "dataType": "boolean" + }, + "attributes": [ + { + "type": "Actual", + "mutability": "ReadOnly" + } + ], + "description": "Component exists", + "type": "boolean", + "default": false + }, + "ConnectorEnabled": { + "variable_name": "Enabled", + "characteristics": { + "supportsMonitoring": false, + "dataType": "boolean" + }, + "attributes": [ + { + "type": "Actual", + "mutability": "ReadWrite" + } + ] + }, + "ChargeProtocol": { + "variable_name": "ChargeProtocol", + "characteristics": { + "supportsMonitoring": true, + "dataType": "string" + }, + "attributes": [ + { + "type": "Actual", + "mutability": "WriteOnly" + } + ], + "description": "The Charging Control Protocol applicable to a Connector. CHAdeMO: CHAdeMO protocol, ISO15118: ISO15118 V2G protocol (wired or wireless) as used with CCS, CPPWM: IEC61851-1 / SAE J1772 protocol (ELV DC & PWM signalling via Control Pilot wire), Uncontrolled: No charging power management applies (e.g. Schuko socket), Undetermined: Yet to be determined (e.g. before plugged in), Unknown: Not determinable, NOTE: ChargeProtocol is distinct from and orthogonal to connectorType.", + "type": "string" + }, + "ConnectorType": { + "variable_name": "ConnectorType", + "characteristics": { + "supportsMonitoring": true, + "dataType": "string" + }, + "attributes": [ + { + "type": "Actual", + "mutability": "ReadOnly", + "value": "cCCS2" + }, + { + "type": "Target", + "mutability": "ReadWrite" + } + ], + "description": "A value of ConnectorEnumType (See part 2) plus additionally: cGBT, cChaoJi, OppCharge. Specific type of connector, including sub-variant information. Note: Distinct and orthogonal to Charging Protocol, Power Type, Phases.", + "type": "string", + "default": "0" + }, + "ConnectorSupplyPhases": { + "variable_name": "SupplyPhases", + "characteristics": { + "supportsMonitoring": true, + "dataType": "integer" + }, + "attributes": [ + { + "type": "Target", + "mutability": "ReadOnly" + }, + { + "type": "Actual", + "mutability": "ReadOnly" + } + ], + "description": "Number of alternating current phases connected/available.", + "type": "integer", + "default": "0" + } + }, + "required": [ + "ConnectorAvailable", + "ConnectorSupplyPhases", + "ConnectorType" + ] +} diff --git a/tests/config/v201/resources_wrong/component_config_required_no_value/custom/EVSE_1.json b/tests/config/v201/resources_wrong/component_config_required_no_value/custom/EVSE_1.json new file mode 100644 index 000000000..7ec4f62e0 --- /dev/null +++ b/tests/config/v201/resources_wrong/component_config_required_no_value/custom/EVSE_1.json @@ -0,0 +1,120 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Schema for EVSE", + "type": "object", + "name": "EVSE", + "evse_id": 1, + "properties": { + "EVSEAllowReset": { + "variable_name": "AllowReset", + "characteristics": { + "supportsMonitoring": true, + "dataType": "boolean" + }, + "attributes": [ + { + "type": "Actual", + "mutability": "ReadOnly" + } + ], + "description": "Can be used to announce that an EVSE can be reset individually", + "type": "boolean" + }, + "EVSEAvailabilityState": { + "variable_name": "AvailabilityState", + "characteristics": { + "supportsMonitoring": true, + "dataType": "OptionList", + "valuesList": "Available,Occupied,Reserved,Unavailable,Faulted" + }, + "attributes": [ + { + "type": "Actual", + "mutability": "ReadOnly" + } + ], + "description": "This variable reports current availability state for the EVSE", + "type": "string", + "default": "Unavailable" + }, + "EVSEAvailable": { + "variable_name": "Available", + "characteristics": { + "supportsMonitoring": true, + "dataType": "boolean" + }, + "attributes": [ + { + "type": "Actual", + "mutability": "ReadOnly" + } + ], + "description": "Component exists", + "type": "boolean", + "default": false + }, + "EvseId": { + "variable_name": "EvseId", + "characteristics": { + "supportsMonitoring": true, + "dataType": "string" + }, + "attributes": [ + { + "type": "Actual" + } + ], + "description": "The name of the EVSE in the string format as required by ISO 15118 and IEC 63119-2.", + "type": "string" + }, + "EVSEPower": { + "variable_name": "Power", + "characteristics": { + "unit": "kW", + "maxLimit": 22000, + "supportsMonitoring": true, + "dataType": "decimal" + }, + "attributes": [ + { + "type": "Actual", + "mutability": "ReadOnly" + }, + { + "type": "MaxSet", + "mutability": "ReadOnly" + }, + { + "type": "Target", + "mutability": "ReadWrite" + } + ], + "description": " kW,The variableCharacteristic maxLimit, that holds the maximum power that this EVSE can provide, is required. The Actual value of the instantaneous (real) power is desired, but not required.", + "type": "number", + "default": "0" + }, + "EVSESupplyPhases": { + "variable_name": "SupplyPhases", + "characteristics": { + "supportsMonitoring": true, + "dataType": "integer" + }, + "attributes": [ + { + "type": "Actual", + "mutability": "ReadOnly", + "value": 2 + } + ], + "description": "Number of alternating current phases connected/available.", + "type": "integer", + "default": "0" + } + }, + "required": [ + "EVSEAvailabilityState", + "EVSEAvailable", + "EVSEPower", + "EVSESupplyPhases" + ] +} diff --git a/tests/config/v201/resources_wrong/component_config_required_no_value/standardized/UnitTestCtrlr.json b/tests/config/v201/resources_wrong/component_config_required_no_value/standardized/UnitTestCtrlr.json new file mode 100644 index 000000000..e965e49e5 --- /dev/null +++ b/tests/config/v201/resources_wrong/component_config_required_no_value/standardized/UnitTestCtrlr.json @@ -0,0 +1,75 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Schema for UnitTestCtrlr", + "name": "UnitTestCtrlr", + "type": "object", + "evse_id": 2, + "connector_id": 3, + "properties": { + "UnitTestPropertyA": { + "variable_name": "UnitTestPropertyAName", + "characteristics": { + "supportsMonitoring": true, + "dataType": "boolean" + }, + "attributes": [ + { + "type": "Actual", + "mutability": "ReadWrite" + } + ], + "type": "boolean" + }, + "UnitTestPropertyB": { + "variable_name": "UnitTestPropertyBName", + "characteristics": { + "supportsMonitoring": false, + "dataType": "string" + }, + "attributes": [ + { + "type": "Actual", + "mutability": "ReadOnly", + "value": "test_value" + } + ], + "type": "string" + }, + "UnitTestPropertyC": { + "variable_name": "UnitTestPropertyCName", + "characteristics": { + "supportsMonitoring": false, + "dataType": "integer" + }, + "attributes": [ + { + "type": "Target", + "mutability": "ReadOnly" + } + ], + "type": "integer", + "default": 42 + }, + "UnitTestPropertyD": { + "variable_name": "UnitTestPropertyDName", + "characteristics": { + "supportsMonitoring": false, + "dataType": "integer" + }, + "attributes": [ + { + "type": "Actual", + "mutability": "ReadOnly" + } + ], + "type": "integer", + "default": 42 + } + }, + "required": [ + "UnitTestPropertyA", + "UnitTestPropertyB", + "UnitTestPropertyC", + "UnitTestPropertyD" + ] +} diff --git a/tests/config/v201/resources_wrong/component_config_wrong_value_type/custom/Connector_1_1.json b/tests/config/v201/resources_wrong/component_config_wrong_value_type/custom/Connector_1_1.json new file mode 100644 index 000000000..42f212ce7 --- /dev/null +++ b/tests/config/v201/resources_wrong/component_config_wrong_value_type/custom/Connector_1_1.json @@ -0,0 +1,115 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Schema for Connector", + "type": "object", + "name": "Connector", + "evse_id": 1, + "connector_id": 1, + "properties": { + "ConnectorAvailabilityState": { + "variable_name": "AvailabilityState", + "characteristics": { + "supportsMonitoring": true, + "dataType": "OptionList", + "valuesList": "Available,Occupied,Reserved,Unavailable,Faulted" + }, + "attributes": [ + { + "type": "Actual" + } + ], + "description": "This variable reports current availability state for the Connector. Optional, because already reported in StatusNotification.", + "type": "string" + }, + "ConnectorAvailable": { + "variable_name": "Available", + "characteristics": { + "supportsMonitoring": true, + "dataType": "boolean" + }, + "attributes": [ + { + "type": "Actual", + "mutability": "ReadOnly" + } + ], + "description": "Component exists", + "type": "boolean", + "default": false + }, + "ConnectorEnabled": { + "variable_name": "Enabled", + "characteristics": { + "supportsMonitoring": false, + "dataType": "boolean" + }, + "attributes": [ + { + "type": "Actual", + "mutability": "ReadWrite" + } + ] + }, + "ChargeProtocol": { + "variable_name": "ChargeProtocol", + "characteristics": { + "supportsMonitoring": true, + "dataType": "string" + }, + "attributes": [ + { + "type": "Actual", + "mutability": "WriteOnly" + } + ], + "description": "The Charging Control Protocol applicable to a Connector. CHAdeMO: CHAdeMO protocol, ISO15118: ISO15118 V2G protocol (wired or wireless) as used with CCS, CPPWM: IEC61851-1 / SAE J1772 protocol (ELV DC & PWM signalling via Control Pilot wire), Uncontrolled: No charging power management applies (e.g. Schuko socket), Undetermined: Yet to be determined (e.g. before plugged in), Unknown: Not determinable, NOTE: ChargeProtocol is distinct from and orthogonal to connectorType.", + "type": "string" + }, + "ConnectorType": { + "variable_name": "ConnectorType", + "characteristics": { + "supportsMonitoring": true, + "dataType": "string" + }, + "attributes": [ + { + "type": "Actual", + "mutability": "ReadOnly", + "value": "OppCharge" + }, + { + "type": "Target", + "mutability": "ReadWrite" + } + ], + "description": "A value of ConnectorEnumType (See part 2) plus additionally: cGBT, cChaoJi, OppCharge. Specific type of connector, including sub-variant information. Note: Distinct and orthogonal to Charging Protocol, Power Type, Phases.", + "type": "string", + "default": "sType2" + }, + "ConnectorSupplyPhases": { + "variable_name": "SupplyPhases", + "characteristics": { + "supportsMonitoring": true, + "dataType": "integer" + }, + "attributes": [ + { + "type": "Target", + "mutability": "ReadOnly" + }, + { + "type": "Actual", + "mutability": "ReadOnly" + } + ], + "description": "Number of alternating current phases connected/available.", + "type": "integer", + "default": "0" + } + }, + "required": [ + "ConnectorAvailable", + "ConnectorSupplyPhases", + "ConnectorType" + ] +} diff --git a/tests/config/v201/resources_wrong/component_config_wrong_value_type/custom/EVSE_1.json b/tests/config/v201/resources_wrong/component_config_wrong_value_type/custom/EVSE_1.json new file mode 100644 index 000000000..7ec4f62e0 --- /dev/null +++ b/tests/config/v201/resources_wrong/component_config_wrong_value_type/custom/EVSE_1.json @@ -0,0 +1,120 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Schema for EVSE", + "type": "object", + "name": "EVSE", + "evse_id": 1, + "properties": { + "EVSEAllowReset": { + "variable_name": "AllowReset", + "characteristics": { + "supportsMonitoring": true, + "dataType": "boolean" + }, + "attributes": [ + { + "type": "Actual", + "mutability": "ReadOnly" + } + ], + "description": "Can be used to announce that an EVSE can be reset individually", + "type": "boolean" + }, + "EVSEAvailabilityState": { + "variable_name": "AvailabilityState", + "characteristics": { + "supportsMonitoring": true, + "dataType": "OptionList", + "valuesList": "Available,Occupied,Reserved,Unavailable,Faulted" + }, + "attributes": [ + { + "type": "Actual", + "mutability": "ReadOnly" + } + ], + "description": "This variable reports current availability state for the EVSE", + "type": "string", + "default": "Unavailable" + }, + "EVSEAvailable": { + "variable_name": "Available", + "characteristics": { + "supportsMonitoring": true, + "dataType": "boolean" + }, + "attributes": [ + { + "type": "Actual", + "mutability": "ReadOnly" + } + ], + "description": "Component exists", + "type": "boolean", + "default": false + }, + "EvseId": { + "variable_name": "EvseId", + "characteristics": { + "supportsMonitoring": true, + "dataType": "string" + }, + "attributes": [ + { + "type": "Actual" + } + ], + "description": "The name of the EVSE in the string format as required by ISO 15118 and IEC 63119-2.", + "type": "string" + }, + "EVSEPower": { + "variable_name": "Power", + "characteristics": { + "unit": "kW", + "maxLimit": 22000, + "supportsMonitoring": true, + "dataType": "decimal" + }, + "attributes": [ + { + "type": "Actual", + "mutability": "ReadOnly" + }, + { + "type": "MaxSet", + "mutability": "ReadOnly" + }, + { + "type": "Target", + "mutability": "ReadWrite" + } + ], + "description": " kW,The variableCharacteristic maxLimit, that holds the maximum power that this EVSE can provide, is required. The Actual value of the instantaneous (real) power is desired, but not required.", + "type": "number", + "default": "0" + }, + "EVSESupplyPhases": { + "variable_name": "SupplyPhases", + "characteristics": { + "supportsMonitoring": true, + "dataType": "integer" + }, + "attributes": [ + { + "type": "Actual", + "mutability": "ReadOnly", + "value": 2 + } + ], + "description": "Number of alternating current phases connected/available.", + "type": "integer", + "default": "0" + } + }, + "required": [ + "EVSEAvailabilityState", + "EVSEAvailable", + "EVSEPower", + "EVSESupplyPhases" + ] +} diff --git a/tests/config/v201/resources_wrong/component_config_wrong_value_type/standardized/UnitTestCtrlr.json b/tests/config/v201/resources_wrong/component_config_wrong_value_type/standardized/UnitTestCtrlr.json new file mode 100644 index 000000000..c51f5df2e --- /dev/null +++ b/tests/config/v201/resources_wrong/component_config_wrong_value_type/standardized/UnitTestCtrlr.json @@ -0,0 +1,59 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Schema for UnitTestCtrlr", + "name": "UnitTestCtrlr", + "type": "object", + "evse_id": 2, + "connector_id": 3, + "properties": { + "UnitTestPropertyA": { + "variable_name": "UnitTestPropertyAName", + "characteristics": { + "supportsMonitoring": true, + "dataType": "boolean" + }, + "attributes": [ + { + "type": "Actual", + "mutability": "ReadWrite", + "value": 42 + } + ], + "type": "boolean" + }, + "UnitTestPropertyB": { + "variable_name": "UnitTestPropertyBName", + "characteristics": { + "supportsMonitoring": false, + "dataType": "decimal" + }, + "attributes": [ + { + "type": "Actual", + "mutability": "ReadOnly", + "value": "test_value" + } + ], + "type": "number", + "default": "test" + }, + "UnitTestPropertyC": { + "variable_name": "UnitTestPropertyCName", + "characteristics": { + "supportsMonitoring": false, + "dataType": "integer" + }, + "attributes": [ + { + "type": "Actual", + "mutability": "ReadOnly" + } + ], + "type": "integer", + "default": "true" + } + }, + "required": [ + "UnitTestPropertyA" + ] +} diff --git a/tests/lib/ocpp/v201/test_init_device_model_db.cpp b/tests/lib/ocpp/v201/test_init_device_model_db.cpp index 790ff9555..010c9923d 100644 --- a/tests/lib/ocpp/v201/test_init_device_model_db.cpp +++ b/tests/lib/ocpp/v201/test_init_device_model_db.cpp @@ -21,6 +21,9 @@ class InitDeviceModelDbTest : public DatabaseTestingUtils { const std::string MIGRATION_FILES_PATH = "./resources/v201/device_model_migration_files"; const std::string SCHEMAS_PATH = "./resources/config/v201/component_config"; const std::string SCHEMAS_PATH_CHANGED = "./resources/config/v201/changed/component_config"; + const std::string SCHEMAS_PATH_REQUIRED_NO_VALUE = + "./resources/config/v201/wrong/component_config_required_no_value"; + const std::string SCHEMAS_PATH_WRONG_VALUE_TYPE = "./resources/config/v201/wrong/component_config_wrong_value_type"; public: InitDeviceModelDbTest() { @@ -423,6 +426,48 @@ TEST_F(InitDeviceModelDbTest, default_device_model_config) { EXPECT_NO_THROW(db.initialize_database(SCHEMAS_PATH_DEFAULT, true)); } +TEST_F(InitDeviceModelDbTest, missing_required_values) { + // Test if initializing fails when there is a missing required value. + InitDeviceModelDb db(DATABASE_PATH, MIGRATION_FILES_PATH); + try { + db.initialize_database(SCHEMAS_PATH_REQUIRED_NO_VALUE, true); + FAIL() << "Expected InitDeviceModelDbError, but no exception was thrown"; + } catch (const InitDeviceModelDbError& exception) { + EXPECT_EQ(std::string(exception.what()), "Check integrity failed:\n" + "- Component UnitTestCtrlr, evse 2, connector 3\n" + " - Variable UnitTestPropertyAName, errors:\n" + " - No value set for Actual attribute for required variable.\n" + " - Variable UnitTestPropertyCName, errors:\n" + " - Could not find required Actual attribute.\n"); + } catch (const std::exception& exception) { + FAIL() << "Expected InitDeviceModelDbError, but exception of type " << typeid(exception).name() + << " was thrown"; + } +} + +TEST_F(InitDeviceModelDbTest, wrong_type) { + // Test if initializing fails when there is a missing required value. + InitDeviceModelDb db(DATABASE_PATH, MIGRATION_FILES_PATH); + try { + db.initialize_database(SCHEMAS_PATH_WRONG_VALUE_TYPE, true); + FAIL() << "Expected InitDeviceModelDbError, but no exception was thrown"; + } catch (const InitDeviceModelDbError& exception) { + EXPECT_EQ(std::string(exception.what()), + "Check integrity failed:\n" + "- Component UnitTestCtrlr, evse 2, connector 3\n" + " - Variable UnitTestPropertyAName, errors:\n" + " - Attribute 'Actual' value (42) has wrong type, type should have been: boolean.\n" + " - Variable UnitTestPropertyBName, errors:\n" + " - Default value (test) has wrong type, type should have been decimal.\n" + " - Attribute 'Actual' value (test_value) has wrong type, type should have been: decimal.\n" + " - Variable UnitTestPropertyCName, errors:\n" + " - Default value (true) has wrong type, type should have been integer.\n"); + } catch (const std::exception& exception) { + FAIL() << "Expected InitDeviceModelDbError, but exception of type " << typeid(exception).name() + << " was thrown"; + } +} + // Helper functions bool InitDeviceModelDbTest::check_all_tables_exist(const std::vector& tables, const bool exist) { From 06d9c8092b3627c90c00a35a5c265d4fab8e66e4 Mon Sep 17 00:00:00 2001 From: "Maaike Zijderveld, iolar" Date: Thu, 8 Aug 2024 12:46:51 +0200 Subject: [PATCH 07/12] Remove TODO's that taken care of. Add more 'auto' instead of specific type in for loops. Fix schema's for unit tests. Signed-off-by: Maaike Zijderveld, iolar --- lib/ocpp/v201/init_device_model_db.cpp | 23 +++++++++---------- lib/ocpp/v201/ocpp_types.cpp | 1 - .../custom/Connector_1_1.json | 15 ++++-------- .../component_config/custom/EVSE_2.json | 1 - .../ocpp/v201/test_init_device_model_db.cpp | 8 +++---- 5 files changed, 20 insertions(+), 28 deletions(-) diff --git a/lib/ocpp/v201/init_device_model_db.cpp b/lib/ocpp/v201/init_device_model_db.cpp index ab45d375b..721ab7e21 100644 --- a/lib/ocpp/v201/init_device_model_db.cpp +++ b/lib/ocpp/v201/init_device_model_db.cpp @@ -13,9 +13,6 @@ const static std::string STANDARDIZED_COMPONENT_CONFIG_DIR = "standardized"; const static std::string CUSTOM_COMPONENT_CONFIG_DIR = "custom"; -// TODO mz change EverestEnvironmentOCPPConfiguration in everest_environment_setup.py in everest-utils -// TODO mz search for component_schemas and config_file etc to remove or change paths - namespace ocpp::v201 { // Forward declarations. @@ -195,7 +192,7 @@ void InitDeviceModelDb::insert_component(const ComponentKey& component_key, const int64_t component_id = this->database->get_last_inserted_rowid(); // Loop over the properties of this component. - for (const DeviceModelVariable& variable : component_variables) { + for (const auto& variable : component_variables) { EVLOG_debug << "-- Inserting variable " << variable.name; // Add variable @@ -206,7 +203,7 @@ void InitDeviceModelDb::insert_component(const ComponentKey& component_key, std::map> InitDeviceModelDb::read_component_config(const std::vector& components_schema_path) { std::map> components; - for (const std::filesystem::path& path : components_schema_path) { + for (const auto& path : components_schema_path) { std::ifstream schema_file(path); try { json data = json::parse(schema_file); @@ -510,7 +507,7 @@ void InitDeviceModelDb::insert_attribute(const VariableAttribute& attribute, con void InitDeviceModelDb::insert_attributes(const std::vector& attributes, const uint64_t& variable_id, const std::optional& default_actual_value) { - for (const DbVariableAttribute& attribute : attributes) { + for (const auto& attribute : attributes) { insert_attribute(attribute.variable_attribute, variable_id, default_actual_value); } } @@ -520,7 +517,7 @@ void InitDeviceModelDb::update_attributes(const std::vector const uint64_t& variable_id, const std::optional& default_actual_value) { // First check if there are attributes in the database that are not in the config. They should be removed. - for (const DbVariableAttribute& db_attribute : db_attributes) { + for (const auto& db_attribute : db_attributes) { const auto& it = std::find_if( new_attributes.begin(), new_attributes.end(), [&db_attribute](const DbVariableAttribute& new_attribute) { return is_same_attribute_type(db_attribute.variable_attribute, new_attribute.variable_attribute); @@ -532,7 +529,7 @@ void InitDeviceModelDb::update_attributes(const std::vector } // Check if the variable attributes in the config match the ones from the database. If not, add or update. - for (const DbVariableAttribute& new_attribute : new_attributes) { + for (const auto& new_attribute : new_attributes) { const auto& it = std::find_if( db_attributes.begin(), db_attributes.end(), [&new_attribute](const DbVariableAttribute& db_attribute) { return is_same_attribute_type(new_attribute.variable_attribute, db_attribute.variable_attribute); @@ -856,7 +853,7 @@ void InitDeviceModelDb::update_component_variables( } // Check for variables that do exist in the database but do not exist in the config. They should be removed. - for (const DeviceModelVariable& db_variable : db_variables) { + for (const auto& db_variable : db_variables) { auto it = std::find_if(variables.begin(), variables.end(), [&db_variable](const DeviceModelVariable& variable) { return is_same_variable(variable, db_variable); }); @@ -869,7 +866,7 @@ void InitDeviceModelDb::update_component_variables( // Check for variables that do exist in the config. If they are not in the database, they should be added. // Otherwise, they should be updated. - for (const DeviceModelVariable& variable : variables) { + for (const auto& variable : variables) { auto it = std::find_if(db_variables.begin(), db_variables.end(), [&variable](const DeviceModelVariable& db_variable) { return is_same_variable(db_variable, variable); @@ -1064,6 +1061,9 @@ static void check_integrity(const std::map check_integrity_required_value(const DeviceModelVariable& variable) { + // For now, we assume that if a variable is required, it should have an 'Actual' value. But the spec is not clear + // about this. There are some implicit signs in favor of having always at least an 'Actual' value, but it is not + // explicitly stated. Robert asked OCA about this. const auto& actual_attribute = std::find_if(variable.attributes.begin(), variable.attributes.end(), [](const DbVariableAttribute& attribute) { if (attribute.variable_attribute.type.has_value() && @@ -1220,7 +1220,7 @@ static bool variable_has_same_attributes(const std::vector& return false; } - for (const DbVariableAttribute& attribute : attributes1) { + for (const auto& attribute : attributes1) { const auto& it = std::find_if(attributes2.begin(), attributes2.end(), [&attribute](const DbVariableAttribute& a) { if (!is_attribute_different(a.variable_attribute, attribute.variable_attribute)) { @@ -1299,7 +1299,6 @@ static std::string get_string_value_from_json(const json& value) { } else if (value.is_array() || value.is_object()) { EVLOG_warning << "String value " << value.dump() << " from config is an object or array, but config values should be from a primitive type."; - // TODO mz throw here or is this ok? return value.dump(); } else { return value.dump(); diff --git a/lib/ocpp/v201/ocpp_types.cpp b/lib/ocpp/v201/ocpp_types.cpp index 534bfe05f..d59331cf6 100644 --- a/lib/ocpp/v201/ocpp_types.cpp +++ b/lib/ocpp/v201/ocpp_types.cpp @@ -1879,7 +1879,6 @@ void from_json(const json& j, VariableAttribute& k) { k.value = "false"; } } else if (value.is_array() || value.is_object()) { - // TODO mz throw here or is this ok? // Maybe this is correct and is just a string (json value string), so just return the string. k.value = value.dump(); } else { diff --git a/tests/config/v201/resources_changed/component_config/custom/Connector_1_1.json b/tests/config/v201/resources_changed/component_config/custom/Connector_1_1.json index 611661207..faf606d26 100644 --- a/tests/config/v201/resources_changed/component_config/custom/Connector_1_1.json +++ b/tests/config/v201/resources_changed/component_config/custom/Connector_1_1.json @@ -30,7 +30,8 @@ "attributes": [ { "type": "Actual", - "mutability": "ReadOnly" + "mutability": "ReadOnly", + "value": true } ], "description": "Component exists", @@ -69,13 +70,13 @@ "variable_name": "ConnectorType", "characteristics": { "supportsMonitoring": true, - "dataType": "string" + "dataType": "integer" }, "attributes": [ { "type": "Actual", "mutability": "ReadOnly", - "value": "OppCharge" + "value": "2" }, { "type": "Target", @@ -83,8 +84,7 @@ } ], "description": "A value of ConnectorEnumType (See part 2) plus additionally: cGBT, cChaoJi, OppCharge. Specific type of connector, including sub-variant information. Note: Distinct and orthogonal to Charging Protocol, Power Type, Phases.", - "type": "string", - "default": "cCCS2" + "type": "string" }, "ConnectorSupplyPhases": { "variable_name": "SupplyPhases", @@ -96,10 +96,6 @@ { "type": "Target", "mutability": "ReadOnly" - }, - { - "type": "Actual", - "mutability": "ReadOnly" } ], "description": "Number of alternating current phases connected/available.", @@ -109,7 +105,6 @@ }, "required": [ "ConnectorAvailable", - "ConnectorSupplyPhases", "ConnectorType" ] } diff --git a/tests/config/v201/resources_changed/component_config/custom/EVSE_2.json b/tests/config/v201/resources_changed/component_config/custom/EVSE_2.json index 07c380afa..a4cb69e0e 100644 --- a/tests/config/v201/resources_changed/component_config/custom/EVSE_2.json +++ b/tests/config/v201/resources_changed/component_config/custom/EVSE_2.json @@ -123,7 +123,6 @@ "required": [ "EVSEAvailabilityState", "EVSEAvailable", - "EVSEPower", "EVSESupplyPhases" ] } diff --git a/tests/lib/ocpp/v201/test_init_device_model_db.cpp b/tests/lib/ocpp/v201/test_init_device_model_db.cpp index 010c9923d..110fca4bd 100644 --- a/tests/lib/ocpp/v201/test_init_device_model_db.cpp +++ b/tests/lib/ocpp/v201/test_init_device_model_db.cpp @@ -286,7 +286,7 @@ TEST_F(InitDeviceModelDbTest, init_db) { // accordingly. // First set the source of an attribute to something else than 'default' - set_attribute_source("Connector", std::nullopt, 1, 1, "ConnectorType", std::nullopt, AttributeEnum::Actual, "test"); + set_attribute_source("Connector", std::nullopt, 1, 1, "Available", std::nullopt, AttributeEnum::Actual, "test"); InitDeviceModelDb db2 = InitDeviceModelDb(DATABASE_PATH, MIGRATION_FILES_PATH); // This time, the database does exist (again: std::filesystem::exists, which is automatically used, will not work @@ -386,9 +386,9 @@ TEST_F(InitDeviceModelDbTest, init_db) { EXPECT_TRUE(variable_exists("UnitTestCtrlr", std::nullopt, 2, 3, "UnitTestPropertyBName", std::nullopt)); EXPECT_FALSE(variable_exists("UnitTestCtrlr", std::nullopt, 2, 3, "UnitTestPropertyCName", std::nullopt)); - // Source was not 'default', connector type not changed. - EXPECT_TRUE(attribute_has_value("Connector", std::nullopt, 1, 1, "ConnectorType", std::nullopt, - AttributeEnum::Actual, "cGBT")); + // Source was not 'default', available not changed. + EXPECT_TRUE(attribute_has_value("Connector", std::nullopt, 1, 1, "Available", std::nullopt, AttributeEnum::Actual, + "false")); // Check changed values. EXPECT_TRUE(attribute_has_value("EVSE", std::nullopt, 2, std::nullopt, "Available", std::nullopt, From 58a6f168db7659669e347491c98a9403d9313a85 Mon Sep 17 00:00:00 2001 From: "Maaike Zijderveld, iolar" Date: Fri, 9 Aug 2024 11:49:33 +0200 Subject: [PATCH 08/12] Formatting... Signed-off-by: Maaike Zijderveld, iolar --- include/ocpp/v201/charge_point.hpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/include/ocpp/v201/charge_point.hpp b/include/ocpp/v201/charge_point.hpp index a77f01d72..d2750d3c2 100644 --- a/include/ocpp/v201/charge_point.hpp +++ b/include/ocpp/v201/charge_point.hpp @@ -799,10 +799,9 @@ class ChargePoint : public ChargePointInterface, private ocpp::ChargingStationBa ChargePoint(const std::map& evse_connector_structure, const std::string& device_model_storage_address, const bool initialize_device_model, const std::string& device_model_migration_path, const std::string& device_model_config_path, - const std::string& ocpp_main_path, - const std::string& core_database_path, const std::string& sql_init_path, - const std::string& message_log_path, const std::shared_ptr evse_security, - const Callbacks& callbacks); + const std::string& ocpp_main_path, const std::string& core_database_path, + const std::string& sql_init_path, const std::string& message_log_path, + const std::shared_ptr evse_security, const Callbacks& callbacks); /// \brief Construct a new ChargePoint object /// \param evse_connector_structure Map that defines the structure of EVSE and connectors of the chargepoint. The From 85cbc971f80ac9249ed5768274d0d8deb2452241 Mon Sep 17 00:00:00 2001 From: "Maaike Zijderveld, iolar" Date: Wed, 14 Aug 2024 12:11:12 +0200 Subject: [PATCH 09/12] Fix build after merge Signed-off-by: Maaike Zijderveld, iolar --- tests/lib/ocpp/v201/test_charge_point.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/lib/ocpp/v201/test_charge_point.cpp b/tests/lib/ocpp/v201/test_charge_point.cpp index 1ae57a57d..b198f3030 100644 --- a/tests/lib/ocpp/v201/test_charge_point.cpp +++ b/tests/lib/ocpp/v201/test_charge_point.cpp @@ -64,7 +64,6 @@ class ChargePointFixture : public DatabaseTestingUtils { void create_device_model_db(const std::string& path) { InitDeviceModelDb db(path, MIGRATION_FILES_PATH); db.initialize_database(SCHEMAS_PATH, true); - db.insert_config_and_default_values(SCHEMAS_PATH, CONFIG_PATH); } std::shared_ptr From 0513a4ac90ccdbd9e3e9d7d76f23cd0c40527184 Mon Sep 17 00:00:00 2001 From: "Maaike Zijderveld, iolar" Date: Thu, 15 Aug 2024 11:59:25 +0200 Subject: [PATCH 10/12] Fix failing tests Signed-off-by: Maaike Zijderveld, iolar --- tests/lib/ocpp/v201/test_charge_point.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/lib/ocpp/v201/test_charge_point.cpp b/tests/lib/ocpp/v201/test_charge_point.cpp index b198f3030..5c82b6d5c 100644 --- a/tests/lib/ocpp/v201/test_charge_point.cpp +++ b/tests/lib/ocpp/v201/test_charge_point.cpp @@ -23,8 +23,7 @@ static const int DEFAULT_PROFILE_ID = 1; static const int DEFAULT_STACK_LEVEL = 1; static const std::string TEMP_OUTPUT_PATH = "/tmp/ocpp201"; const static std::string MIGRATION_FILES_PATH = "./resources/v201/device_model_migration_files"; -const static std::string SCHEMAS_PATH = "./resources/example_config/v201/component_schemas"; -const static std::string CONFIG_PATH = "./resources/example_config/v201/config.json"; +const static std::string SCHEMAS_PATH = "./resources/example_config/v201/component_config"; const static std::string DEVICE_MODEL_DB_IN_MEMORY_PATH = "file::memory:?cache=shared"; static const std::string DEFAULT_TX_ID = "10c75ff7-74f5-44f5-9d01-f649f3ac7b78"; From e4707855a5ca57edf8e8d9fb623ec2678764bbc0 Mon Sep 17 00:00:00 2001 From: "Maaike Zijderveld, iolar" Date: Mon, 19 Aug 2024 10:34:23 +0200 Subject: [PATCH 11/12] Review comments Signed-off-by: Maaike Zijderveld, iolar --- doc/ocpp_201_device_model_initialization.md | 2 +- lib/ocpp/v201/init_device_model_db.cpp | 26 ++++++++++++++------- lib/ocpp/v201/ocpp_types.cpp | 1 - 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/doc/ocpp_201_device_model_initialization.md b/doc/ocpp_201_device_model_initialization.md index b7edcdd11..61a52a1f4 100644 --- a/doc/ocpp_201_device_model_initialization.md +++ b/doc/ocpp_201_device_model_initialization.md @@ -42,7 +42,7 @@ software, it will: - Check if there are Components in the database that are not in the component config's. Those will be removed. - Check if there are Components in the component config's that are not in the database. Those will be added. - Check if anything has changed inside the Component (`Variable`, `Characteristics` or `Attributes`). - Those will be removed, changed or added. Those will be removed, changed or added to the database as well. + Those will be removed, changed or added to the database as well. Note: When the `evse_id` or `connector_id` of a component is changed, this is seen as the removal of a Component and addition of a new one. diff --git a/lib/ocpp/v201/init_device_model_db.cpp b/lib/ocpp/v201/init_device_model_db.cpp index 721ab7e21..a5c68e22b 100644 --- a/lib/ocpp/v201/init_device_model_db.cpp +++ b/lib/ocpp/v201/init_device_model_db.cpp @@ -28,6 +28,8 @@ static bool variable_has_same_attributes(const std::vector& static bool is_characteristics_different(const VariableCharacteristics& c1, const VariableCharacteristics& c2); static bool is_same_variable(const DeviceModelVariable& v1, const DeviceModelVariable& v2); static bool is_variable_different(const DeviceModelVariable& v1, const DeviceModelVariable& v2); +static bool has_attribute_actual_value(const VariableAttribute& attribute, + const std::optional& default_actual_value); static std::string get_string_value_from_json(const json& value); static std::string get_component_name_for_logging(const ComponentKey& component); static std::string get_variable_name_for_logging(const DeviceModelVariable& variable); @@ -495,9 +497,7 @@ void InitDeviceModelDb::insert_attribute(const VariableAttribute& attribute, con const int64_t attribute_id = this->database->get_last_inserted_rowid(); - if (attribute.value.has_value() || - (attribute.type.has_value() && (attribute.type.value() == AttributeEnum::Actual) && - default_actual_value.has_value())) { + if (has_attribute_actual_value(attribute, default_actual_value)) { insert_variable_attribute_value( attribute_id, (attribute.value.has_value() ? attribute.value.value().get() : default_actual_value.value()), true); @@ -601,9 +601,7 @@ void InitDeviceModelDb::update_attribute(const VariableAttribute& attribute, con throw InitDeviceModelDbError("Could not update attribute: " + std::string(this->database->get_error_message())); } - if (attribute.value.has_value() || - (attribute.type.has_value() && (attribute.type.value() == AttributeEnum::Actual) && - default_actual_value.has_value())) { + if (has_attribute_actual_value(attribute, default_actual_value)) { if (!insert_variable_attribute_value( static_cast(db_attribute.db_id.value()), (attribute.value.has_value() ? attribute.value.value().get() : default_actual_value.value()), false)) { @@ -1208,8 +1206,7 @@ static bool is_attribute_different(const VariableAttribute& attribute1, const Va /// /// \brief Check if a variable has the same attributes, or if there is for example an extra attribute added, removed -/// or -/// changed. +/// or changed. /// \param attributes1 Attributes 1 /// \param attributes2 Attributes 2 /// \return True if they are the same. @@ -1279,6 +1276,19 @@ static bool is_variable_different(const DeviceModelVariable& v1, const DeviceMod return true; } +/// +/// \brief Check if the attribute has an actual value or a default value. +/// \param attribute The attribute to check. +/// \param default_actual_value The default value. +/// \return True when the attribute has an actual or default value. +/// +static bool has_attribute_actual_value(const VariableAttribute& attribute, + const std::optional& default_actual_value) { + return (attribute.value.has_value() || + (attribute.type.has_value() && (attribute.type.value() == AttributeEnum::Actual) && + default_actual_value.has_value())); +} + /// /// \brief Get string value from json. /// diff --git a/lib/ocpp/v201/ocpp_types.cpp b/lib/ocpp/v201/ocpp_types.cpp index b114cd17b..b38f3b8d8 100644 --- a/lib/ocpp/v201/ocpp_types.cpp +++ b/lib/ocpp/v201/ocpp_types.cpp @@ -1867,7 +1867,6 @@ void from_json(const json& j, VariableAttribute& k) { k.type.emplace(conversions::string_to_attribute_enum(j.at("type"))); } - // TODO mz change this in the generator (if everyone agrees)!! if (j.contains("value")) { const json& value = j.at("value"); if (value.is_string()) { From fa1116857889db4ca3af10632f0c401ba8a14162 Mon Sep 17 00:00:00 2001 From: "Maaike Zijderveld, iolar" Date: Mon, 19 Aug 2024 11:44:13 +0200 Subject: [PATCH 12/12] Bump version to 0.16.0 Signed-off-by: Maaike Zijderveld, iolar --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ec41a85d..3803bf07e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.14) project(ocpp - VERSION 0.15.1 + VERSION 0.16.0 DESCRIPTION "A C++ implementation of the Open Charge Point Protocol" LANGUAGES CXX )