Skip to content

Commit 2b4c1a3

Browse files
committed
fix: rebase with main
fix: setting JSON configuration to include schema validation (#1782) Moved validation function to base class and added checks to V2 device model storage (OCPP 1.6) Additional tests to ensure that schema validation on set works for both JSON and database implemantations. Signed-off-by: James Chapman <james.chapman@pionix.de>
1 parent bd298e9 commit 2b4c1a3

14 files changed

+200
-37
lines changed

lib/everest/ocpp/include/ocpp/v16/charge_point_configuration.hpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ class ChargePointConfiguration : private ChargePointConfigurationBase, public Ch
2424
json custom_schema;
2525
json internal_schema;
2626
bool core_schema_unlock_connector_on_ev_side_disconnect_ro_value;
27-
fs::path ocpp_main_path;
2827
fs::path user_config_path;
2928

3029
std::recursive_mutex configuration_mutex;
@@ -36,11 +35,10 @@ class ChargePointConfiguration : private ChargePointConfigurationBase, public Ch
3635
void setChargepointInformationProperty(json& user_config, const std::string& key,
3736
const std::optional<std::string>& value);
3837

39-
bool validate(const std::string_view& schema_file, const json& object);
40-
4138
public:
4239
ChargePointConfiguration(const std::string& config, const fs::path& ocpp_main_path,
4340
const fs::path& user_config_path);
41+
virtual ~ChargePointConfiguration() = default;
4442
void setChargepointInformation(const std::string& chargePointVendor, const std::string& chargePointModel,
4543
const std::optional<std::string>& chargePointSerialNumber,
4644
const std::optional<std::string>& chargeBoxSerialNumber,

lib/everest/ocpp/include/ocpp/v16/charge_point_configuration_base.hpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77
#include <ocpp/v16/types.hpp>
88

99
#include <cstddef>
10+
#include <filesystem>
1011
#include <map>
1112
#include <optional>
1213
#include <set>
14+
#include <string_view>
1315

1416
namespace ocpp::v16 {
1517

@@ -39,11 +41,20 @@ class ChargePointConfigurationBase {
3941
MessagesSet supported_message_types_sending;
4042
ProfilesSet supported_feature_profiles;
4143
MeasurandsMap supported_measurands;
44+
std::filesystem::path ocpp_main_path;
4245

4346
void initialise(const ProfilesSet& initial_set, const std::optional<std::string>& supported_profiles_csl,
4447
const std::optional<std::string>& supported_measurands_csl);
4548

4649
public:
50+
ChargePointConfigurationBase(const std::string_view& ocpp_main_path) : ocpp_main_path(ocpp_main_path) {
51+
}
52+
ChargePointConfigurationBase(const std::filesystem::path& ocpp_main_path) : ocpp_main_path(ocpp_main_path) {
53+
}
54+
virtual ~ChargePointConfigurationBase() = default;
55+
56+
bool validate(const std::string_view& schema_file, const json& object) const;
57+
4758
bool isValidSupportedMeasurands(const std::string& csl) const;
4859
std::optional<MeasurandWithPhaseList> csvToMeasurandWithPhaseVector(const std::string& csl) const;
4960

lib/everest/ocpp/include/ocpp/v16/charge_point_configuration_devicemodel.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ class ChargePointConfigurationDeviceModel : private ChargePointConfigurationBase
9595
SetResult setInternalWaitForSetUserPriceTimeout(const std::string& value);
9696

9797
public:
98-
explicit ChargePointConfigurationDeviceModel(std::unique_ptr<v2::DeviceModelInterface> device_model_interface);
98+
explicit ChargePointConfigurationDeviceModel(const std::string_view& ocpp_main_path,
99+
std::unique_ptr<v2::DeviceModelInterface> device_model_interface);
99100
virtual ~ChargePointConfigurationDeviceModel() = default;
100101

101102
// UserConfig and Internal

lib/everest/ocpp/include/ocpp/v16/charge_point_configuration_interface.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ struct KeyValue;
2020
/// \brief contains the configuration of the charge point
2121
class ChargePointConfigurationInterface {
2222
public:
23+
virtual ~ChargePointConfigurationInterface() = default;
2324
// UserConfig and Internal
2425
virtual std::string getChargeBoxSerialNumber() = 0;
2526
virtual std::optional<CiString<25>> getChargePointSerialNumber() = 0;

lib/everest/ocpp/lib/ocpp/v16/charge_point_configuration.cpp

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ namespace ocpp::v16 {
1919

2020
ChargePointConfiguration::ChargePointConfiguration(const std::string& config, const fs::path& ocpp_main_path,
2121
const fs::path& user_config_path) :
22-
ocpp_main_path(ocpp_main_path), user_config_path(user_config_path) {
22+
ChargePointConfigurationBase(ocpp_main_path), user_config_path(user_config_path) {
2323

2424
if (!fs::exists(this->user_config_path)) {
2525
EVLOG_critical << "User config file does not exist";
@@ -160,24 +160,6 @@ void ChargePointConfiguration::setChargepointInformationProperty(json& user_conf
160160
}
161161
}
162162

163-
bool ChargePointConfiguration::validate(const std::string_view& schema_file, const json& object) {
164-
bool result{false};
165-
try {
166-
fs::path schema_path = ocpp_main_path / "profile_schemas" / schema_file;
167-
std::ifstream ifs(schema_path);
168-
auto schema_json = json::parse(ifs);
169-
ocpp::Schemas schema(std::move(schema_json));
170-
auto validator = schema.get_validator();
171-
if (validator) {
172-
validator->validate(object);
173-
result = true;
174-
}
175-
} catch (const std::exception& e) {
176-
EVLOG_error << "Error validating against schema " << schema_file << ": " << e.what();
177-
}
178-
return result;
179-
}
180-
181163
void ChargePointConfiguration::setChargepointInformation(const std::string& chargePointVendor,
182164
const std::string& chargePointModel,
183165
const std::optional<std::string>& chargePointSerialNumber,

lib/everest/ocpp/lib/ocpp/v16/charge_point_configuration_base.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22
// Copyright 2020 - 2026 Pionix GmbH and Contributors to EVerest
33

44
#include <cstddef>
5+
#include <ocpp/common/schemas.hpp>
56
#include <ocpp/v16/charge_point_configuration_base.hpp>
67
#include <ocpp/v16/utils.hpp>
78

89
#include <exception>
10+
#include <fstream>
911
#include <regex>
1012
#include <string>
1113

@@ -157,6 +159,24 @@ void ChargePointConfigurationBase::initialise(const ProfilesSet& initial_set,
157159
}
158160
}
159161

162+
bool ChargePointConfigurationBase::validate(const std::string_view& schema_file, const json& object) const {
163+
bool result{false};
164+
try {
165+
fs::path schema_path = ocpp_main_path / "profile_schemas" / schema_file;
166+
std::ifstream ifs(schema_path);
167+
auto schema_json = json::parse(ifs);
168+
ocpp::Schemas schema(std::move(schema_json));
169+
auto validator = schema.get_validator();
170+
if (validator) {
171+
validator->validate(object);
172+
result = true;
173+
}
174+
} catch (const std::exception& e) {
175+
EVLOG_error << "Error validating against schema " << schema_file << ": " << e.what();
176+
}
177+
return result;
178+
}
179+
160180
bool ChargePointConfigurationBase::isValidSupportedMeasurands(const std::string& csl) const {
161181
const auto elements = utils::from_csl(csl);
162182
bool result{true};

lib/everest/ocpp/lib/ocpp/v16/charge_point_configuration_devicemodel.cpp

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -758,7 +758,17 @@ ChargePointConfigurationDeviceModel::setInternalDefaultPrice(const std::string&
758758
try {
759759
json default_price = json::object();
760760
default_price = json::parse(value);
761-
result = set_value(*storage, keys::valid_keys::DefaultPrice, value);
761+
762+
// perform schema validation on value
763+
json test_value;
764+
test_value["CustomDisplayCostAndPrice"] = true;
765+
test_value["DefaultPrice"] = default_price;
766+
767+
if (validate("CostAndPrice.json", test_value)) {
768+
result = set_value(*storage, keys::valid_keys::DefaultPrice, value);
769+
} else {
770+
EVLOG_error << "DefaultPrice is invalid: " << value;
771+
}
762772
} catch (const std::exception& e) {
763773
EVLOG_error << "Default price json not correct, can not store default price : " << e.what();
764774
}
@@ -844,7 +854,17 @@ ChargePointConfigurationDeviceModel::setInternalDefaultPriceText(const std::stri
844854
// add new info
845855
default_price_json["priceTexts"].push_back(value_json);
846856
}
847-
result = set_value(*storage, keys::valid_keys::DefaultPriceText, default_price_json.dump(2));
857+
858+
// perform schema validation on default_price
859+
json test_value;
860+
test_value["CustomDisplayCostAndPrice"] = true;
861+
test_value["DefaultPriceText"] = default_price_json;
862+
863+
if (validate("CostAndPrice.json", test_value)) {
864+
result = set_value(*storage, keys::valid_keys::DefaultPriceText, default_price_json.dump(2));
865+
} else {
866+
EVLOG_error << "DefaultPriceText value is invalid: " << value;
867+
}
848868
} else {
849869
EVLOG_error << "Error while setting default price: 'priceTexts' is not an array";
850870
}
@@ -907,8 +927,8 @@ ChargePointConfigurationDeviceModel::setInternalWaitForSetUserPriceTimeout(const
907927
// Public methods
908928

909929
ChargePointConfigurationDeviceModel::ChargePointConfigurationDeviceModel(
910-
std::unique_ptr<v2::DeviceModelInterface> device_model_interface) :
911-
ChargePointConfigurationBase(), storage(std::move(device_model_interface)) {
930+
const std::string_view& ocpp_main_path, std::unique_ptr<v2::DeviceModelInterface> device_model_interface) :
931+
ChargePointConfigurationBase(ocpp_main_path), storage(std::move(device_model_interface)) {
912932
const auto profiles = get_optional<std::string>(*storage, keys::valid_keys::SupportedFeatureProfiles);
913933
const auto measurands = get_optional<std::string>(*storage, keys::valid_keys::SupportedMeasurands);
914934
ProfilesSet initial;

lib/everest/ocpp/tests/lib/ocpp/v16/v2config/configuration_stub.hpp

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,42 @@
55

66
#include <gtest/gtest.h>
77

8+
#include <filesystem>
89
#include <fstream>
910
#include <memory>
1011

1112
#include <ocpp/v16/charge_point_configuration.hpp>
1213
#include <ocpp/v16/charge_point_configuration_devicemodel.hpp>
1314
#include <ocpp/v16/utils.hpp>
15+
#include <string_view>
1416

1517
#include "memory_storage.hpp"
1618

1719
namespace ocpp::v16::stubs {
1820

21+
namespace fs = std::filesystem;
22+
1923
// create instances for v16 and v2 configuration
2024
class ConfigurationBase : public testing::Test {
2125
protected:
2226
std::unique_ptr<ocpp::v16::ChargePointConfigurationInterface> v16_config;
2327
std::unique_ptr<ocpp::v16::ChargePointConfigurationInterface> v2_config;
2428
std::unique_ptr<MemoryStorage> device_model;
2529

26-
void SetUp() override {
27-
std::ifstream ifs(CONFIG_FILE_LOCATION_V16);
30+
void loadConfig(const std::string_view& file) {
31+
fs::path cfg{CONFIG_DIR_V16};
32+
cfg /= file;
33+
std::ifstream ifs(cfg);
2834
const std::string config_file((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
2935
v16_config = std::make_unique<ocpp::v16::ChargePointConfiguration>(config_file, CONFIG_DIR_V16,
3036
USER_CONFIG_FILE_LOCATION_V16);
3137
device_model = std::make_unique<MemoryStorage>();
3238
std::unique_ptr<ocpp::v2::DeviceModelInterface> proxy = std::make_unique<MemoryStorageProxy>(*device_model);
33-
v2_config = std::make_unique<ocpp::v16::ChargePointConfigurationDeviceModel>(std::move(proxy));
39+
v2_config = std::make_unique<ocpp::v16::ChargePointConfigurationDeviceModel>(CONFIG_DIR_V16, std::move(proxy));
40+
}
41+
42+
void SetUp() override {
43+
loadConfig("config.json");
3444
}
3545

3646
// void TearDown() override {
@@ -53,4 +63,13 @@ class Configuration : public ConfigurationBase, public testing::WithParamInterfa
5363
}
5464
};
5565

66+
// create instances for v16 and v2 configuration
67+
class ConfigurationFull : public Configuration {
68+
protected:
69+
void SetUp() override {
70+
loadConfig("config-full.json");
71+
device_model->apply_full_config();
72+
}
73+
};
74+
5675
} // namespace ocpp::v16::stubs

lib/everest/ocpp/tests/lib/ocpp/v16/v2config/memory_storage.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include "memory_storage.hpp"
55

6+
#include <iterator>
67
#include <ocpp/v16/known_keys.hpp>
78
#include <ocpp/v2/ocpp_enums.hpp>
89
#include <ocpp/v2/ocpp_types.hpp>
@@ -52,7 +53,6 @@ const std::map<std::string, std::string> required_vars_internal = {
5253
{"LogRotationMaximumFileSize", "0"},
5354
{"SupportedChargingProfilePurposeTypes", "ChargePointMaxProfile,TxDefaultProfile,TxProfile"},
5455
{"LogMessagesFormat", ""},
55-
{"AllowChargingProfileWithoutStartSchedule", "true"},
5656
{"CompositeScheduleDefaultLimitAmps", "48"},
5757
{"CompositeScheduleDefaultLimitWatts", "33120"},
5858
{"CompositeScheduleDefaultNumberPhases", "3"},
@@ -134,6 +134,13 @@ const std::map<std::string, std::string> required_vars_california_pricing = {
134134
// Do not add additional values
135135
const std::map<std::string, std::string> required_vars_custom = {};
136136

137+
// additional values for full config
138+
const std::map<std::string, std::string> full_vars_california_pricing = {
139+
{"SupportedLanguages", "en, nl, de, nb_NO"},
140+
{"CustomMultiLanguageMessages", "true"},
141+
{"Language", "en"},
142+
};
143+
137144
std::map<std::string, std::string> vars_internal;
138145
std::map<std::string, std::string> vars_core;
139146
std::map<std::string, std::string> vars_firmware_management;
@@ -191,6 +198,10 @@ MemoryStorage::MemoryStorage() {
191198
read_only.clear();
192199
}
193200

201+
void MemoryStorage::apply_full_config() {
202+
vars_california_pricing.insert(full_vars_california_pricing.begin(), full_vars_california_pricing.end());
203+
}
204+
194205
void MemoryStorage::set_readonly(const std::string& key) {
195206
read_only.insert(key);
196207
}

lib/everest/ocpp/tests/lib/ocpp/v16/v2config/memory_storage.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ class MemoryStorage : public ocpp::v2::DeviceModelInterface {
4545

4646
MemoryStorage();
4747

48+
void apply_full_config();
49+
4850
void set_readonly(const std::string& key);
4951
void set(const std::string_view& component, const std::string_view& variable, const std::string_view& value);
5052
std::string get(const std::string_view& component, const std::string_view& variable);

0 commit comments

Comments
 (0)