diff --git a/include/ocpp/v201/smart_charging.hpp b/include/ocpp/v201/smart_charging.hpp index 7c5fe815dc..59b370213a 100644 --- a/include/ocpp/v201/smart_charging.hpp +++ b/include/ocpp/v201/smart_charging.hpp @@ -62,7 +62,9 @@ class SmartChargingHandler { explicit SmartChargingHandler(std::map>& evses); /// - /// \brief validates the given \p profile according to the specification + /// \brief validates the given \p profile according to the specification. + /// If a profile does not have validFrom or validTo set, we conform the values + /// to a representation that fits the spec. /// ProfileValidationResultEnum validate_profile(ChargingProfile& profile, int32_t evse_id); @@ -103,7 +105,7 @@ class SmartChargingHandler { /// \brief Checks a given \p profile and associated \p evse_id validFrom and validTo range /// This method assumes that the existing profile will have dates set for validFrom and validTo /// - bool is_overlapping_validity_period(int evse_id, ChargingProfile& profile) const; + bool is_overlapping_validity_period(int evse_id, const ChargingProfile& profile) const; private: std::vector get_evse_specific_tx_default_profiles() const; diff --git a/lib/ocpp/v201/smart_charging.cpp b/lib/ocpp/v201/smart_charging.cpp index 3b4ae58f4a..b18d9a043c 100644 --- a/lib/ocpp/v201/smart_charging.cpp +++ b/lib/ocpp/v201/smart_charging.cpp @@ -78,6 +78,8 @@ SmartChargingHandler::SmartChargingHandler(std::mapvalidate_evse_exists(evse_id); @@ -128,6 +130,10 @@ ProfileValidationResultEnum SmartChargingHandler::validate_charging_station_max_ return ProfileValidationResultEnum::InvalidProfileType; } + if (is_overlapping_validity_period(evse_id, profile)) { + return ProfileValidationResultEnum::DuplicateProfileValidityPeriod; + } + if (evse_id > 0) { return ProfileValidationResultEnum::ChargingStationMaxProfileEvseIdGreaterThanZero; } @@ -307,9 +313,7 @@ std::vector SmartChargingHandler::get_station_wide_tx_default_p } bool SmartChargingHandler::is_overlapping_validity_period(int candidate_evse_id, - ChargingProfile& candidate_profile) const { - - conform_validity_periods(candidate_profile); + const ChargingProfile& candidate_profile) const { if (candidate_profile.chargingProfilePurpose == ChargingProfilePurposeEnum::TxProfile) { // This only applies to non TxProfile types. diff --git a/tests/lib/ocpp/v201/test_smart_charging_handler.cpp b/tests/lib/ocpp/v201/test_smart_charging_handler.cpp index 0d1cca7ae7..19d5bc5701 100644 --- a/tests/lib/ocpp/v201/test_smart_charging_handler.cpp +++ b/tests/lib/ocpp/v201/test_smart_charging_handler.cpp @@ -621,12 +621,14 @@ TEST_F(ChargepointTestFixtureV201, K01FR06_ExisitingProfileLastForever_RejectInc install_profile_on_evse(DEFAULT_EVSE_ID, DEFAULT_PROFILE_ID, ocpp::DateTime(date::utc_clock::time_point::min()), ocpp::DateTime(date::utc_clock::time_point::max())); + auto periods = create_charging_schedule_periods(0); auto profile = create_charging_profile( DEFAULT_PROFILE_ID + 1, ChargingProfilePurposeEnum::TxDefaultProfile, - create_charge_schedule(ChargingRateUnitEnum::A), uuid(), ChargingProfileKindEnum::Absolute, DEFAULT_STACK_LEVEL, - ocpp::DateTime("2024-01-02T13:00:00"), ocpp::DateTime("2024-03-01T13:00:00")); + create_charge_schedule(ChargingRateUnitEnum::A, periods, ocpp::DateTime("2024-01-17T17:00:00")), uuid(), + ChargingProfileKindEnum::Absolute, DEFAULT_STACK_LEVEL, ocpp::DateTime("2024-01-02T13:00:00"), + ocpp::DateTime("2024-03-01T13:00:00")); - auto sut = handler.validate_tx_default_profile(profile, DEFAULT_EVSE_ID); + auto sut = handler.validate_profile(profile, DEFAULT_EVSE_ID); EXPECT_THAT(sut, testing::Eq(ProfileValidationResultEnum::DuplicateProfileValidityPeriod)); } @@ -635,12 +637,13 @@ TEST_F(ChargepointTestFixtureV201, K01FR06_ExisitingProfileHasValidFromIncomingV install_profile_on_evse(DEFAULT_EVSE_ID, DEFAULT_PROFILE_ID, ocpp::DateTime("2024-01-01T13:00:00"), ocpp::DateTime(date::utc_clock::time_point::max())); - auto profile = create_charging_profile(DEFAULT_PROFILE_ID + 1, ChargingProfilePurposeEnum::TxDefaultProfile, - create_charge_schedule(ChargingRateUnitEnum::A), uuid(), - ChargingProfileKindEnum::Absolute, DEFAULT_STACK_LEVEL, {}, - ocpp::DateTime("2024-01-01T13:00:00")); + auto periods = create_charging_schedule_periods(0); + auto profile = create_charging_profile( + DEFAULT_PROFILE_ID + 1, ChargingProfilePurposeEnum::TxDefaultProfile, + create_charge_schedule(ChargingRateUnitEnum::A, periods, ocpp::DateTime("2024-01-17T17:00:00")), uuid(), + ChargingProfileKindEnum::Absolute, DEFAULT_STACK_LEVEL, {}, ocpp::DateTime("2024-01-01T13:00:00")); - auto sut = handler.validate_tx_default_profile(profile, DEFAULT_EVSE_ID); + auto sut = handler.validate_profile(profile, DEFAULT_EVSE_ID); EXPECT_THAT(sut, testing::Eq(ProfileValidationResultEnum::DuplicateProfileValidityPeriod)); } @@ -649,12 +652,13 @@ TEST_F(ChargepointTestFixtureV201, K01FR06_ExisitingProfileHasValidToIncomingVal install_profile_on_evse(DEFAULT_EVSE_ID, DEFAULT_PROFILE_ID, ocpp::DateTime("2024-02-01T13:00:00"), ocpp::DateTime(date::utc_clock::time_point::max())); - auto profile = create_charging_profile(DEFAULT_PROFILE_ID + 1, ChargingProfilePurposeEnum::TxDefaultProfile, - create_charge_schedule(ChargingRateUnitEnum::A), uuid(), - ChargingProfileKindEnum::Absolute, DEFAULT_STACK_LEVEL, - ocpp::DateTime("2024-01-31T13:00:00"), {}); + auto periods = create_charging_schedule_periods(0); + auto profile = create_charging_profile( + DEFAULT_PROFILE_ID + 1, ChargingProfilePurposeEnum::TxDefaultProfile, + create_charge_schedule(ChargingRateUnitEnum::A, periods, ocpp::DateTime("2024-01-17T17:00:00")), uuid(), + ChargingProfileKindEnum::Absolute, DEFAULT_STACK_LEVEL, ocpp::DateTime("2024-01-31T13:00:00"), {}); - auto sut = handler.validate_tx_default_profile(profile, DEFAULT_EVSE_ID); + auto sut = handler.validate_profile(profile, DEFAULT_EVSE_ID); EXPECT_THAT(sut, testing::Eq(ProfileValidationResultEnum::DuplicateProfileValidityPeriod)); } @@ -664,11 +668,13 @@ TEST_F(ChargepointTestFixtureV201, K01FR06_ExisitingProfileHasValidPeriodIncomin ocpp::DateTime(date::utc_clock::now() - std::chrono::hours(5 * 24)), ocpp::DateTime(date::utc_clock::now() + std::chrono::hours(5 * 24))); - auto profile = create_charging_profile(DEFAULT_PROFILE_ID + 1, ChargingProfilePurposeEnum::TxDefaultProfile, - create_charge_schedule(ChargingRateUnitEnum::A), uuid(), - ChargingProfileKindEnum::Absolute, DEFAULT_STACK_LEVEL, {}, {}); + auto periods = create_charging_schedule_periods(0); + auto profile = create_charging_profile( + DEFAULT_PROFILE_ID + 1, ChargingProfilePurposeEnum::TxDefaultProfile, + create_charge_schedule(ChargingRateUnitEnum::A, periods, ocpp::DateTime("2024-01-17T17:00:00")), uuid(), + ChargingProfileKindEnum::Absolute, DEFAULT_STACK_LEVEL, {}, {}); - auto sut = handler.validate_tx_default_profile(profile, DEFAULT_EVSE_ID); + auto sut = handler.validate_profile(profile, DEFAULT_EVSE_ID); EXPECT_THAT(sut, testing::Eq(ProfileValidationResultEnum::DuplicateProfileValidityPeriod)); } @@ -677,12 +683,14 @@ TEST_F(ChargepointTestFixtureV201, K01FR06_ExisitingProfileHasValidPeriodIncomin install_profile_on_evse(DEFAULT_EVSE_ID, DEFAULT_PROFILE_ID, ocpp::DateTime("2024-01-01T13:00:00"), ocpp::DateTime("2024-02-01T13:00:00")); + auto periods = create_charging_schedule_periods(0); auto profile = create_charging_profile( DEFAULT_PROFILE_ID + 1, ChargingProfilePurposeEnum::TxDefaultProfile, - create_charge_schedule(ChargingRateUnitEnum::A, {}, {}), uuid(), ChargingProfileKindEnum::Absolute, - DEFAULT_STACK_LEVEL, ocpp::DateTime("2024-01-15T13:00:00"), ocpp::DateTime("2024-02-01T13:00:00")); + create_charge_schedule(ChargingRateUnitEnum::A, periods, ocpp::DateTime("2024-01-17T17:00:00")), uuid(), + ChargingProfileKindEnum::Absolute, DEFAULT_STACK_LEVEL, ocpp::DateTime("2024-01-15T13:00:00"), + ocpp::DateTime("2024-02-01T13:00:00")); - auto sut = handler.validate_tx_default_profile(profile, DEFAULT_EVSE_ID); + auto sut = handler.validate_profile(profile, DEFAULT_EVSE_ID); EXPECT_THAT(sut, testing::Eq(ProfileValidationResultEnum::DuplicateProfileValidityPeriod)); }