From d5f1bc4aeb67fcdb69fa76220ad0d0f14834d57e Mon Sep 17 00:00:00 2001 From: Ivan Rogach Date: Wed, 18 Dec 2024 10:19:18 +0100 Subject: [PATCH] Raise error if charging schedules are empty Signed-off-by: Ivan Rogach --- include/ocpp/v201/smart_charging.hpp | 3 ++- lib/ocpp/v201/smart_charging.cpp | 8 +++++++ .../ocpp/v201/test_smart_charging_handler.cpp | 22 +++++++++++++++++-- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/include/ocpp/v201/smart_charging.hpp b/include/ocpp/v201/smart_charging.hpp index d37eb0b2a..c573dfa3e 100644 --- a/include/ocpp/v201/smart_charging.hpp +++ b/include/ocpp/v201/smart_charging.hpp @@ -46,7 +46,8 @@ enum class ProfileValidationResultEnum { ChargingStationMaxProfileEvseIdGreaterThanZero, DuplicateTxDefaultProfileFound, DuplicateProfileValidityPeriod, - RequestStartTransactionNonTxProfile + RequestStartTransactionNonTxProfile, + ChargingProfileEmptyChargingSchedules }; /// \brief This is used to associate charging profiles with a source. diff --git a/lib/ocpp/v201/smart_charging.cpp b/lib/ocpp/v201/smart_charging.cpp index 29201b71f..2148ca73a 100644 --- a/lib/ocpp/v201/smart_charging.cpp +++ b/lib/ocpp/v201/smart_charging.cpp @@ -76,6 +76,8 @@ std::string profile_validation_result_to_string(ProfileValidationResultEnum e) { return "DuplicateProfileValidityPeriod"; case ProfileValidationResultEnum::RequestStartTransactionNonTxProfile: return "RequestStartTransactionNonTxProfile"; + case ProfileValidationResultEnum::ChargingProfileEmptyChargingSchedules: + return "ChargingProfileEmptyChargingSchedules"; } throw EnumToStringException{e, "ProfileValidationResultEnum"}; @@ -105,6 +107,7 @@ std::string profile_validation_result_to_reason_code(ProfileValidationResultEnum case ProfileValidationResultEnum::ChargingSchedulePeriodUnsupportedNumberPhases: case ProfileValidationResultEnum::ChargingSchedulePeriodExtraneousPhaseValues: case ProfileValidationResultEnum::ChargingSchedulePeriodPhaseToUseACPhaseSwitchingUnsupported: + case ProfileValidationResultEnum::ChargingProfileEmptyChargingSchedules: return "InvalidSchedule"; case ProfileValidationResultEnum::TxProfileMissingTransactionId: return "MissingParam"; @@ -338,6 +341,11 @@ SmartChargingHandler::validate_tx_profile(const ChargingProfile& profile, int32_ ProfileValidationResultEnum SmartChargingHandler::validate_profile_schedules(ChargingProfile& profile, std::optional evse_opt) const { + + if (profile.chargingSchedule.empty()) { + return ProfileValidationResultEnum::ChargingProfileEmptyChargingSchedules; + } + auto charging_station_supply_phases = this->device_model->get_value(ControllerComponentVariables::ChargingStationSupplyPhases); diff --git a/tests/lib/ocpp/v201/test_smart_charging_handler.cpp b/tests/lib/ocpp/v201/test_smart_charging_handler.cpp index 065eb8761..8a82372c9 100644 --- a/tests/lib/ocpp/v201/test_smart_charging_handler.cpp +++ b/tests/lib/ocpp/v201/test_smart_charging_handler.cpp @@ -146,12 +146,12 @@ class SmartChargingHandlerTestFixtureV201 : public DatabaseTestingUtils { ChargingProfile create_charging_profile(int32_t charging_profile_id, ChargingProfilePurposeEnum charging_profile_purpose, - ChargingSchedule charging_schedule, std::optional transaction_id = {}, + std::vector charging_schedules, + std::optional transaction_id = {}, ChargingProfileKindEnum charging_profile_kind = ChargingProfileKindEnum::Absolute, int stack_level = DEFAULT_STACK_LEVEL, std::optional validFrom = {}, std::optional validTo = {}) { auto recurrency_kind = RecurrencyKindEnum::Daily; - std::vector charging_schedules = {charging_schedule}; ChargingProfile charging_profile; charging_profile.id = charging_profile_id; charging_profile.stackLevel = stack_level; @@ -166,6 +166,16 @@ class SmartChargingHandlerTestFixtureV201 : public DatabaseTestingUtils { return charging_profile; } + ChargingProfile + create_charging_profile(int32_t charging_profile_id, ChargingProfilePurposeEnum charging_profile_purpose, + ChargingSchedule charging_schedule, std::optional transaction_id = {}, + ChargingProfileKindEnum charging_profile_kind = ChargingProfileKindEnum::Absolute, + int stack_level = DEFAULT_STACK_LEVEL, std::optional validFrom = {}, + std::optional validTo = {}) { + return create_charging_profile(charging_profile_id, charging_profile_purpose, {charging_schedule}, + transaction_id, charging_profile_kind, stack_level, validFrom, validTo); + } + ChargingProfileCriterion create_charging_profile_criteria( std::optional> sources = std::nullopt, std::optional> ids = std::nullopt, @@ -1747,4 +1757,12 @@ TEST_F(SmartChargingHandlerTestFixtureV201, K01_ValidateTxProfile_AllowsExisting EXPECT_THAT(sut, testing::Eq(ProfileValidationResultEnum::Valid)); } +TEST_F(SmartChargingHandlerTestFixtureV201, K01_ValidateTxProfile_EmptyChargingSchedule) { + auto profile = create_charging_profile(DEFAULT_PROFILE_ID, ChargingProfilePurposeEnum::ChargingStationMaxProfile, + std::vector{}, ocpp::DateTime("2024-01-17T17:00:00")); + + auto sut = handler.conform_and_validate_profile(profile, DEFAULT_EVSE_ID); + ASSERT_THAT(sut, testing::Eq(ProfileValidationResultEnum::ChargingProfileEmptyChargingSchedules)); +} + } // namespace ocpp::v201