Skip to content

Commit

Permalink
smart charging: updated validation to be explicit when conforming pro…
Browse files Browse the repository at this point in the history
…file (#838)

OCPP2.0.1 SmartCharging: updated validation to be explictit when conforming profile
---------

Signed-off-by: Coury Richards <146002925+couryrr-afs@users.noreply.github.com>
Signed-off-by: Piet Gömpel <pietgoempel@gmail.com>
Co-authored-by: Coury Richards <146002925+couryrr-afs@users.noreply.github.com>
  • Loading branch information
Pietfried and couryrr-afs authored Oct 25, 2024
1 parent 8d74ff5 commit f480fc0
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 80 deletions.
15 changes: 8 additions & 7 deletions include/ocpp/v201/smart_charging.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,16 +72,16 @@ class SmartChargingHandlerInterface {
public:
virtual ~SmartChargingHandlerInterface() = default;

virtual SetChargingProfileResponse validate_and_add_profile(
virtual SetChargingProfileResponse conform_validate_and_add_profile(
ChargingProfile& profile, int32_t evse_id,
ChargingLimitSourceEnum charging_limit_source = ChargingLimitSourceEnum::CSO,
AddChargingProfileSource source_of_request = AddChargingProfileSource::SetChargingProfile) = 0;

virtual void delete_transaction_tx_profiles(const std::string& transaction_id) = 0;

virtual ProfileValidationResultEnum
validate_profile(ChargingProfile& profile, int32_t evse_id,
AddChargingProfileSource source_of_request = AddChargingProfileSource::SetChargingProfile) = 0;
virtual ProfileValidationResultEnum conform_and_validate_profile(
ChargingProfile& profile, int32_t evse_id,
AddChargingProfileSource source_of_request = AddChargingProfileSource::SetChargingProfile) = 0;

virtual SetChargingProfileResponse
add_profile(ChargingProfile& profile, int32_t evse_id,
Expand Down Expand Up @@ -121,7 +121,7 @@ class SmartChargingHandler : public SmartChargingHandlerInterface {
/// \brief validates the given \p profile according to the specification,
/// adding it to our stored list of profiles if valid.
///
SetChargingProfileResponse validate_and_add_profile(
SetChargingProfileResponse conform_validate_and_add_profile(
ChargingProfile& profile, int32_t evse_id,
ChargingLimitSourceEnum charging_limit_source = ChargingLimitSourceEnum::CSO,
AddChargingProfileSource source_of_request = AddChargingProfileSource::SetChargingProfile) override;
Expand All @@ -131,7 +131,7 @@ class SmartChargingHandler : public SmartChargingHandlerInterface {
/// If a profile does not have validFrom or validTo set, we conform the values
/// to a representation that fits the spec.
///
ProfileValidationResultEnum validate_profile(
ProfileValidationResultEnum conform_and_validate_profile(
ChargingProfile& profile, int32_t evse_id,
AddChargingProfileSource source_of_request = AddChargingProfileSource::SetChargingProfile) override;

Expand Down Expand Up @@ -181,7 +181,7 @@ class SmartChargingHandler : public SmartChargingHandlerInterface {
///
/// \brief validates the given \p profile and associated \p evse_id according to the specification
///
ProfileValidationResultEnum validate_tx_default_profile(ChargingProfile& profile, int32_t evse_id) const;
ProfileValidationResultEnum validate_tx_default_profile(const ChargingProfile& profile, int32_t evse_id) const;

///
/// \brief validates the given \p profile according to the specification
Expand Down Expand Up @@ -216,6 +216,7 @@ class SmartChargingHandler : public SmartChargingHandlerInterface {
std::vector<ChargingProfile> get_evse_specific_tx_default_profiles() const;
std::vector<ChargingProfile> get_station_wide_tx_default_profiles() const;
std::vector<ChargingProfile> get_valid_profiles_for_evse(int32_t evse_id);
void conform_schedule_number_phases(int32_t profile_id, ChargingSchedulePeriod& charging_schedule_period) const;
void conform_validity_periods(ChargingProfile& profile) const;
CurrentPhaseType get_current_phase_type(const std::optional<EvseInterface*> evse_opt) const;
};
Expand Down
6 changes: 3 additions & 3 deletions lib/ocpp/v201/charge_point.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3146,7 +3146,7 @@ void ChargePoint::handle_remote_start_transaction_request(Call<RequestStartTrans

if (charging_profile.chargingProfilePurpose == ChargingProfilePurposeEnum::TxProfile) {

const auto add_profile_response = this->smart_charging_handler->validate_and_add_profile(
const auto add_profile_response = this->smart_charging_handler->conform_validate_and_add_profile(
msg.chargingProfile.value(), evse_id, ChargingLimitSourceEnum::CSO,
AddChargingProfileSource::RequestStartTransactionRequest);
if (add_profile_response.status == ChargingProfileStatusEnum::Accepted) {
Expand Down Expand Up @@ -3392,7 +3392,7 @@ void ChargePoint::handle_set_charging_profile_req(Call<SetChargingProfileRequest
return;
}

response = this->smart_charging_handler->validate_and_add_profile(msg.chargingProfile, msg.evseId);
response = this->smart_charging_handler->conform_validate_and_add_profile(msg.chargingProfile, msg.evseId);
if (response.status == ChargingProfileStatusEnum::Accepted) {
EVLOG_debug << "Accepting SetChargingProfileRequest";
this->callbacks.set_charging_profiles_callback();
Expand Down Expand Up @@ -4461,7 +4461,7 @@ void ChargePoint::clear_invalid_charging_profiles() {
for (const auto& [evse_id, profiles] : evses) {
for (auto profile : profiles) {
try {
if (this->smart_charging_handler->validate_profile(profile, evse_id) !=
if (this->smart_charging_handler->conform_and_validate_profile(profile, evse_id) !=
ProfileValidationResultEnum::Valid) {
this->database_handler->delete_charging_profile(profile.id);
}
Expand Down
53 changes: 39 additions & 14 deletions lib/ocpp/v201/smart_charging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,13 +155,14 @@ void SmartChargingHandler::delete_transaction_tx_profiles(const std::string& tra
this->database_handler->delete_charging_profile_by_transaction_id(transaction_id);
}

SetChargingProfileResponse SmartChargingHandler::validate_and_add_profile(ChargingProfile& profile, int32_t evse_id,
ChargingLimitSourceEnum charging_limit_source,
AddChargingProfileSource source_of_request) {
SetChargingProfileResponse
SmartChargingHandler::conform_validate_and_add_profile(ChargingProfile& profile, int32_t evse_id,
ChargingLimitSourceEnum charging_limit_source,
AddChargingProfileSource source_of_request) {
SetChargingProfileResponse response;
response.status = ChargingProfileStatusEnum::Rejected;

auto result = this->validate_profile(profile, evse_id, source_of_request);
auto result = this->conform_and_validate_profile(profile, evse_id, source_of_request);
if (result == ProfileValidationResultEnum::Valid) {
response = this->add_profile(profile, evse_id, charging_limit_source);
} else {
Expand All @@ -173,8 +174,9 @@ SetChargingProfileResponse SmartChargingHandler::validate_and_add_profile(Chargi
return response;
}

ProfileValidationResultEnum SmartChargingHandler::validate_profile(ChargingProfile& profile, int32_t evse_id,
AddChargingProfileSource source_of_request) {
ProfileValidationResultEnum
SmartChargingHandler::conform_and_validate_profile(ChargingProfile& profile, int32_t evse_id,
AddChargingProfileSource source_of_request) {

auto result = ProfileValidationResultEnum::Valid;

Expand Down Expand Up @@ -256,7 +258,7 @@ ProfileValidationResultEnum SmartChargingHandler::validate_charging_station_max_
return ProfileValidationResultEnum::Valid;
}

ProfileValidationResultEnum SmartChargingHandler::validate_tx_default_profile(ChargingProfile& profile,
ProfileValidationResultEnum SmartChargingHandler::validate_tx_default_profile(const ChargingProfile& profile,
int32_t evse_id) const {
auto profiles = evse_id == 0 ? get_evse_specific_tx_default_profiles() : get_station_wide_tx_default_profiles();

Expand Down Expand Up @@ -396,10 +398,7 @@ SmartChargingHandler::validate_profile_schedules(ChargingProfile& profile,
return ProfileValidationResultEnum::ChargingSchedulePeriodUnsupportedNumberPhases;
}

// K01.FR.49
if (!charging_schedule_period.numberPhases.has_value()) {
charging_schedule_period.numberPhases.emplace(DEFAULT_AND_MAX_NUMBER_PHASES);
}
conform_schedule_number_phases(profile.id, charging_schedule_period);
}
}

Expand Down Expand Up @@ -465,7 +464,7 @@ std::vector<ChargingProfile> SmartChargingHandler::get_valid_profiles_for_evse(i

auto evse_profiles = this->database_handler->get_charging_profiles_for_evse(evse_id);
for (auto profile : evse_profiles) {
if (this->validate_profile(profile, evse_id) == ProfileValidationResultEnum::Valid) {
if (this->conform_and_validate_profile(profile, evse_id) == ProfileValidationResultEnum::Valid) {
valid_profiles.push_back(profile);
}
}
Expand Down Expand Up @@ -538,9 +537,35 @@ bool SmartChargingHandler::is_overlapping_validity_period(const ChargingProfile&
return false;
}

/// \brief sets attributes of the given \p charging_schedule_period according to the specification.
/// 2.11. ChargingSchedulePeriodType if absent numberPhases set to 3
void SmartChargingHandler::conform_schedule_number_phases(int32_t profileId,
ChargingSchedulePeriod& charging_schedule_period) const {
// K01.FR.49
if (!charging_schedule_period.numberPhases.has_value()) {
EVLOG_debug << "Conforming profile: " << profileId << " added number phase as "
<< DEFAULT_AND_MAX_NUMBER_PHASES;
charging_schedule_period.numberPhases.emplace(DEFAULT_AND_MAX_NUMBER_PHASES);
}
}

///
/// \brief sets attributes of the given \p profile according to the specification.
/// 2.10. ChargingProfileType validFrom if absent set to current date
/// 2.10. ChargingProfileType validTo if absent set to max date
///
void SmartChargingHandler::conform_validity_periods(ChargingProfile& profile) const {
profile.validFrom = profile.validFrom.value_or(ocpp::DateTime());
profile.validTo = profile.validTo.value_or(ocpp::DateTime(date::utc_clock::time_point::max()));
if (!profile.validFrom.has_value()) {
auto validFrom = ocpp::DateTime();
EVLOG_debug << "Conforming profile: " << profile.id << " added validFrom as " << validFrom;
profile.validFrom = validFrom;
}

if (!profile.validTo.has_value()) {
auto validTo = ocpp::DateTime(date::utc_clock::time_point::max());
EVLOG_debug << "Conforming profile: " << profile.id << " added validTo as " << validTo;
profile.validTo = validTo;
}
}

ProfileValidationResultEnum
Expand Down
4 changes: 2 additions & 2 deletions tests/lib/ocpp/v201/mocks/smart_charging_handler_mock.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
namespace ocpp::v201 {
class SmartChargingHandlerMock : public SmartChargingHandlerInterface {
public:
MOCK_METHOD(SetChargingProfileResponse, validate_and_add_profile,
MOCK_METHOD(SetChargingProfileResponse, conform_validate_and_add_profile,
(ChargingProfile & profile, int32_t evse_id, ChargingLimitSourceEnum charging_limit_source,
AddChargingProfileSource source_of_request));
MOCK_METHOD(ProfileValidationResultEnum, validate_profile,
MOCK_METHOD(ProfileValidationResultEnum, conform_and_validate_profile,
(ChargingProfile & profile, int32_t evse_id, AddChargingProfileSource source_of_request));
MOCK_METHOD(void, delete_transaction_tx_profiles, (const std::string& transaction_id));
MOCK_METHOD(SetChargingProfileResponse, add_profile,
Expand Down
18 changes: 9 additions & 9 deletions tests/lib/ocpp/v201/test_charge_point.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -666,8 +666,8 @@ TEST_F(ChargePointFunctionalityTestFixtureV201, K01_SetChargingProfileRequest_Va
request_to_enhanced_message<SetChargingProfileRequest, MessageType::SetChargingProfile>(req);

EXPECT_CALL(*smart_charging_handler,
validate_and_add_profile(profile, DEFAULT_EVSE_ID, ChargingLimitSourceEnum::CSO,
DEFAULT_REQUEST_TO_ADD_PROFILE_SOURCE));
conform_validate_and_add_profile(profile, DEFAULT_EVSE_ID, ChargingLimitSourceEnum::CSO,
DEFAULT_REQUEST_TO_ADD_PROFILE_SOURCE));

charge_point->handle_message(set_charging_profile_req);
}
Expand All @@ -689,7 +689,7 @@ TEST_F(ChargePointFunctionalityTestFixtureV201, K01FR07_SetChargingProfileReques
SetChargingProfileResponse accept_response;
accept_response.status = ChargingProfileStatusEnum::Accepted;

ON_CALL(*smart_charging_handler, validate_and_add_profile).WillByDefault(testing::Return(accept_response));
ON_CALL(*smart_charging_handler, conform_validate_and_add_profile).WillByDefault(testing::Return(accept_response));
EXPECT_CALL(set_charging_profiles_callback_mock, Call);

charge_point->handle_message(set_charging_profile_req);
Expand Down Expand Up @@ -717,7 +717,7 @@ TEST_F(ChargePointFunctionalityTestFixtureV201, K01FR07_SetChargingProfileReques
reject_response.statusInfo->additionalInfo = conversions::profile_validation_result_to_string(
ProfileValidationResultEnum::TxProfileEvseHasNoActiveTransaction);

ON_CALL(*smart_charging_handler, validate_and_add_profile).WillByDefault(testing::Return(reject_response));
ON_CALL(*smart_charging_handler, conform_validate_and_add_profile).WillByDefault(testing::Return(reject_response));
EXPECT_CALL(set_charging_profiles_callback_mock, Call).Times(0);

charge_point->handle_message(set_charging_profile_req);
Expand All @@ -738,7 +738,7 @@ TEST_F(ChargePointFunctionalityTestFixtureV201,
auto set_charging_profile_req =
request_to_enhanced_message<SetChargingProfileRequest, MessageType::SetChargingProfile>(req);

EXPECT_CALL(*smart_charging_handler, validate_and_add_profile).Times(0);
EXPECT_CALL(*smart_charging_handler, conform_validate_and_add_profile).Times(0);
EXPECT_CALL(set_charging_profiles_callback_mock, Call).Times(0);

charge_point->handle_message(set_charging_profile_req);
Expand All @@ -765,7 +765,7 @@ TEST_F(ChargePointFunctionalityTestFixtureV201, K01FR29_SmartChargingCtrlrAvaila
auto set_charging_profile_req =
request_to_enhanced_message<SetChargingProfileRequest, MessageType::SetChargingProfile>(req);

EXPECT_CALL(*smart_charging_handler, validate_and_add_profile).Times(0);
EXPECT_CALL(*smart_charging_handler, conform_validate_and_add_profile).Times(0);

charge_point->handle_message(set_charging_profile_req);
}
Expand All @@ -789,7 +789,7 @@ TEST_F(ChargePointFunctionalityTestFixtureV201,
auto start_transaction_req =
request_to_enhanced_message<RequestStartTransactionRequest, MessageType::RequestStartTransaction>(req);

EXPECT_CALL(*smart_charging_handler, validate_and_add_profile).Times(1);
EXPECT_CALL(*smart_charging_handler, conform_validate_and_add_profile).Times(1);

charge_point->handle_message(start_transaction_req);
}
Expand All @@ -815,7 +815,7 @@ TEST_F(ChargePointFunctionalityTestFixtureV201, K01FR29_SmartChargingCtrlrAvaila
auto set_charging_profile_req =
request_to_enhanced_message<SetChargingProfileRequest, MessageType::SetChargingProfile>(req);

EXPECT_CALL(*smart_charging_handler, validate_and_add_profile).Times(1);
EXPECT_CALL(*smart_charging_handler, conform_validate_and_add_profile).Times(1);

charge_point->handle_message(set_charging_profile_req);
}
Expand Down Expand Up @@ -915,7 +915,7 @@ TEST_F(ChargePointFunctionalityTestFixtureV201,
auto start_transaction_req =
request_to_enhanced_message<RequestStartTransactionRequest, MessageType::RequestStartTransaction>(req);

EXPECT_CALL(*smart_charging_handler, validate_and_add_profile).Times(0);
EXPECT_CALL(*smart_charging_handler, conform_validate_and_add_profile).Times(0);

charge_point->handle_message(start_transaction_req);
}
Expand Down
6 changes: 4 additions & 2 deletions tests/lib/ocpp/v201/test_composite_schedule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -690,8 +690,10 @@ TEST_F(CompositeScheduleTestFixtureV201, K08_CalculateCompositeSchedule_DemoCase
CompositeSchedule actual =
handler.calculate_composite_schedule(profiles, start_time, end_time, DEFAULT_EVSE_ID, ChargingRateUnitEnum::W);

ASSERT_EQ(ProfileValidationResultEnum::Valid, handler.validate_profile(profiles.at(0), DEFAULT_EVSE_ID));
ASSERT_EQ(ProfileValidationResultEnum::Valid, handler.validate_profile(profiles.at(1), DEFAULT_EVSE_ID));
ASSERT_EQ(ProfileValidationResultEnum::Valid,
handler.conform_and_validate_profile(profiles.at(0), DEFAULT_EVSE_ID));
ASSERT_EQ(ProfileValidationResultEnum::Valid,
handler.conform_and_validate_profile(profiles.at(1), DEFAULT_EVSE_ID));
ASSERT_EQ(actual, expected);
}

Expand Down
Loading

0 comments on commit f480fc0

Please sign in to comment.