-
Notifications
You must be signed in to change notification settings - Fork 56
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
SmartChargingHandler: Add validation for TxProfiles
Creates a skeleton for SmartChargingHandler and adds a method to validate TxProfiles and TxProfiles only. This method ensures that a given profile (assumed to be TxProfile) fits all of the functional requirements specific to TxProfiles per K01. The function, `validate_tx_profile ()`, takes a profile and an EVSE, and returns a variant of `ProfileValidationResultEnum`. This enum allows us to have detailed responses for the different types of invalid profiles, and eventually will let us log *why* a profile is invalid if the general validation fails. Part of the prerequisites for #361 Co-authored-by: Gianfranco Berardi <[email protected]> Signed-off-by: Christopher Davis <[email protected]>
- Loading branch information
1 parent
d9536ad
commit ce6b167
Showing
7 changed files
with
399 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// Copyright 2020 - 2023 Pionix GmbH and Contributors to EVerest | ||
|
||
#ifndef OCPP_V201_SMART_CHARGING_HPP | ||
#define OCPP_V201_SMART_CHARGING_HPP | ||
|
||
#include "ocpp/v201/enums.hpp" | ||
#include <limits> | ||
|
||
#include <ocpp/v201/database_handler.hpp> | ||
#include <ocpp/v201/evse.hpp> | ||
#include <ocpp/v201/ocpp_types.hpp> | ||
#include <ocpp/v201/transaction.hpp> | ||
|
||
namespace ocpp::v201 { | ||
|
||
enum class ProfileValidationResultEnum { | ||
Valid, | ||
TxProfileMissingTransactionId, | ||
TxProfileEvseIdNotGreaterThanZero, | ||
TxProfileTransactionNotOnEvse, | ||
TxProfileEvseHasNoActiveTransaction, | ||
TxProfileConflictingStackLevel | ||
}; | ||
|
||
/// \brief This class handles and maintains incoming ChargingProfiles and contains the logic | ||
/// to calculate the composite schedules | ||
class SmartChargingHandler { | ||
private: | ||
std::shared_ptr<ocpp::v201::DatabaseHandler> database_handler; | ||
// cppcheck-suppress unusedStructMember | ||
std::vector<ChargingProfile> charging_profiles; | ||
|
||
public: | ||
explicit SmartChargingHandler(std::shared_ptr<DatabaseHandler> database_handler); | ||
|
||
/// | ||
/// \brief validates the given \p profile according to the specification | ||
/// | ||
ProfileValidationResultEnum validate_tx_profile(const ChargingProfile& profile, Evse& evse) const; | ||
|
||
/// \brief Adds a given \p profile to our stored list of profiles | ||
void add_profile(ChargingProfile& profile); | ||
}; | ||
|
||
} // namespace ocpp::v201 | ||
|
||
#endif // OCPP_V201_SMART_CHARGING_HPP |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// Copyright 2020 - 2023 Pionix GmbH and Contributors to EVerest | ||
|
||
#include "ocpp/common/types.hpp" | ||
#include "ocpp/v201/enums.hpp" | ||
#include "ocpp/v201/ocpp_types.hpp" | ||
#include "ocpp/v201/transaction.hpp" | ||
#include <memory> | ||
#include <ocpp/v201/smart_charging.hpp> | ||
|
||
using namespace std::chrono; | ||
|
||
namespace ocpp::v201 { | ||
|
||
SmartChargingHandler::SmartChargingHandler(std::shared_ptr<DatabaseHandler> database_handler) : | ||
database_handler(database_handler) { | ||
} | ||
|
||
ProfileValidationResultEnum SmartChargingHandler::validate_tx_profile(const ChargingProfile& profile, | ||
Evse& evse) const { | ||
if (!profile.transactionId.has_value()) { | ||
return ProfileValidationResultEnum::TxProfileMissingTransactionId; | ||
} | ||
|
||
int32_t evseId = evse.get_evse_info().id; | ||
if (evseId <= 0) { | ||
return ProfileValidationResultEnum::TxProfileEvseIdNotGreaterThanZero; | ||
} | ||
|
||
if (!evse.has_active_transaction()) { | ||
return ProfileValidationResultEnum::TxProfileEvseHasNoActiveTransaction; | ||
} | ||
|
||
auto& transaction = evse.get_transaction(); | ||
if (transaction->transactionId != profile.transactionId.value()) { | ||
return ProfileValidationResultEnum::TxProfileTransactionNotOnEvse; | ||
} | ||
|
||
auto conflicts_with = [&profile](const ChargingProfile& candidate) { | ||
return candidate.transactionId == profile.transactionId && candidate.stackLevel == profile.stackLevel; | ||
}; | ||
if (std::any_of(charging_profiles.begin(), charging_profiles.end(), conflicts_with)) { | ||
return ProfileValidationResultEnum::TxProfileConflictingStackLevel; | ||
} | ||
|
||
return ProfileValidationResultEnum::Valid; | ||
} | ||
|
||
void SmartChargingHandler::add_profile(ChargingProfile& profile) { | ||
charging_profiles.push_back(profile); | ||
} | ||
|
||
} // namespace ocpp::v201 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,9 @@ | ||
target_include_directories(libocpp_unit_tests PUBLIC mocks) | ||
|
||
target_sources(libocpp_unit_tests PRIVATE | ||
test_device_model_storage_sqlite.cpp | ||
test_notify_report_requests_splitter.cpp | ||
test_ocsp_updater.cpp | ||
test_component_state_manager.cpp | ||
test_device_model.cpp) | ||
test_device_model.cpp | ||
test_smart_charging_handler.cpp) |
44 changes: 44 additions & 0 deletions
44
tests/lib/ocpp/v201/mocks/component_state_manager_mock.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
#include <gmock/gmock.h> | ||
|
||
#include "ocpp/v201/component_state_manager.hpp" | ||
|
||
namespace ocpp::v201 { | ||
class ComponentStateManagerMock : public ComponentStateManagerInterface { | ||
MOCK_METHOD(void, set_cs_effective_availability_changed_callback, | ||
(const std::function<void(const OperationalStatusEnum new_status)>& callback)); | ||
|
||
MOCK_METHOD(void, set_evse_effective_availability_changed_callback, | ||
(const std::function<void(const int32_t evse_id, const OperationalStatusEnum new_status)>& callback)); | ||
|
||
MOCK_METHOD(void, set_connector_effective_availability_changed_callback, | ||
(const std::function<void(const int32_t evse_id, const int32_t connector_id, | ||
const OperationalStatusEnum new_status)>& callback)); | ||
|
||
MOCK_METHOD(OperationalStatusEnum, get_cs_individual_operational_status, ()); | ||
MOCK_METHOD(OperationalStatusEnum, get_evse_individual_operational_status, (int32_t evse_id)); | ||
MOCK_METHOD(OperationalStatusEnum, get_connector_individual_operational_status, | ||
(int32_t evse_id, int32_t connector_id)); | ||
MOCK_METHOD(OperationalStatusEnum, get_cs_persisted_operational_status, ()); | ||
MOCK_METHOD(OperationalStatusEnum, get_evse_persisted_operational_status, (int32_t evse_id)); | ||
MOCK_METHOD(OperationalStatusEnum, get_connector_persisted_operational_status, | ||
(int32_t evse_id, int32_t connector_id)); | ||
MOCK_METHOD(void, set_cs_individual_operational_status, (OperationalStatusEnum new_status, bool persist)); | ||
MOCK_METHOD(void, set_evse_individual_operational_status, | ||
(int32_t evse_id, OperationalStatusEnum new_status, bool persist)); | ||
MOCK_METHOD(void, set_connector_individual_operational_status, | ||
(int32_t evse_id, int32_t connector_id, OperationalStatusEnum new_status, bool persist)); | ||
MOCK_METHOD(OperationalStatusEnum, get_evse_effective_operational_status, (int32_t evse_id)); | ||
MOCK_METHOD(OperationalStatusEnum, get_connector_effective_operational_status, | ||
(int32_t evse_id, int32_t connector_id)); | ||
MOCK_METHOD(ConnectorStatusEnum, get_connector_effective_status, (int32_t evse_id, int32_t connector_id)); | ||
MOCK_METHOD(void, set_connector_occupied, (int32_t evse_id, int32_t connector_id, bool is_occupied)); | ||
MOCK_METHOD(void, set_connector_reserved, (int32_t evse_id, int32_t connector_id, bool is_reserved)); | ||
MOCK_METHOD(void, set_connector_faulted, (int32_t evse_id, int32_t connector_id, bool is_faulted)); | ||
MOCK_METHOD(void, set_connector_unavailable, (int32_t evse_id, int32_t connector_id, bool is_unavailable)); | ||
MOCK_METHOD(void, trigger_all_effective_availability_changed_callbacks, ()); | ||
MOCK_METHOD(void, send_status_notification_all_connectors, ()); | ||
MOCK_METHOD(void, send_status_notification_changed_connectors, ()); | ||
MOCK_METHOD(void, send_status_notification_single_connector, (int32_t evse_id, int32_t connector_id)); | ||
}; | ||
|
||
} // namespace ocpp::v201 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#include <gmock/gmock.h> | ||
|
||
#include "ocpp/v201/device_model_storage.hpp" | ||
|
||
namespace ocpp::v201 { | ||
class DeviceModelStorageMock : public DeviceModelStorage { | ||
public: | ||
MOCK_METHOD(DeviceModelMap, get_device_model, ()); | ||
MOCK_METHOD(std::optional<VariableAttribute>, get_variable_attribute, | ||
(const Component&, const Variable&, const AttributeEnum&)); | ||
MOCK_METHOD(std::vector<VariableAttribute>, get_variable_attributes, | ||
(const Component&, const Variable&, const std::optional<AttributeEnum>&)); | ||
MOCK_METHOD(bool, set_variable_attribute_value, | ||
(const Component&, const Variable&, const AttributeEnum&, const std::string&)); | ||
MOCK_METHOD(void, check_integrity, ()); | ||
}; | ||
} // namespace ocpp::v201 |
Oops, something went wrong.