Skip to content

Commit

Permalink
added: logic for K11FR04 to existing handle_external_limits_changed
Browse files Browse the repository at this point in the history
Signed-off-by: Coury Richards <146002925+couryrr-afs@users.noreply.github.com>
  • Loading branch information
couryrr-afs committed Oct 15, 2024
1 parent 075ab82 commit 719772e
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 29 deletions.
6 changes: 3 additions & 3 deletions doc/ocpp_201_status.md
Original file line number Diff line number Diff line change
Expand Up @@ -1266,7 +1266,7 @@ This document contains the status of which OCPP 2.0.1 numbered functional requir
| K01.FR.40 || `Absolute`/`Recurring` profiles without `startSchedule` fields are rejected. |
| K01.FR.41 || `Relative` profiles with `startSchedule` fields are rejected. |
| K01.FR.42 | ⛽️ | |
| K01.FR.43 | | Open question to OCA - https://oca.causewaynow.com/wg/OCA-TWG/mail/thread/4254 |
| K01.FR.43 | | Open question to OCA - <https://oca.causewaynow.com/wg/OCA-TWG/mail/thread/4254> |
| K01.FR.44 || We reject invalid profiles instead of modifying and accepting them. |
| K01.FR.45 || We reject invalid profiles instead of modifying and accepting them. |
| K01.FR.46 | ⛽️ | K08 |
Expand Down Expand Up @@ -1381,7 +1381,7 @@ This document contains the status of which OCPP 2.0.1 numbered functional requir
| K11.FR.01 | | |
| K11.FR.02 | | |
| K11.FR.03 | | |
| K11.FR.04 | | |
| K11.FR.04 | | |
| K11.FR.05 | | |
| K11.FR.06 | | |

Expand All @@ -1392,7 +1392,7 @@ This document contains the status of which OCPP 2.0.1 numbered functional requir
| K12.FR.01 | | |
| K12.FR.02 || |
| K12.FR.03 || |
| K12.FR.04 || |
| K12.FR.04 || The spec does not define what we should do when the source given is CSO. The system currently throws and exception. |
| K12.FR.05 | | |

## SmartCharging - Reset / Release External Charging Limit
Expand Down
12 changes: 8 additions & 4 deletions include/ocpp/v201/smart_charging.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ class SmartChargingHandlerInterface {
const ocpp::DateTime& end_time, const int32_t evse_id,
std::optional<ChargingRateUnitEnum> charging_rate_unit) = 0;

virtual std::optional<NotifyChargingLimitRequest>
virtual std::optional<std::pair<NotifyChargingLimitRequest, std::vector<TransactionEventRequest>>>
handle_external_limits_changed(const std::variant<ConstantChargingLimit, ChargingSchedule>& limit,
double percentage_delta, ChargingLimitSourceEnum source,
std::optional<int32_t> evse_id) const = 0;
Expand Down Expand Up @@ -189,15 +189,19 @@ class SmartChargingHandler : public SmartChargingHandlerInterface {
std::optional<ChargingRateUnitEnum> charging_rate_unit) override;

///
/// \brief Determines whether or not we should notify the CSMS of a cleared external limit
/// \brief Determines whether or not we should notify the CSMS of a changed external limit
/// based on \p percentage_delta and builds the notification.
///
std::optional<NotifyChargingLimitRequest>
std::optional<std::pair<NotifyChargingLimitRequest, std::vector<TransactionEventRequest>>>
handle_external_limits_changed(const std::variant<ConstantChargingLimit, ChargingSchedule>& limit,
double percentage_delta, ChargingLimitSourceEnum source,
std::optional<int32_t> evse_id) const override;

virtual std::optional<std::pair<ClearedChargingLimitRequest, std::vector<TransactionEventRequest>>>
///
/// \brief Determines whether or not we should notify the CSMS of a cleared external limit
/// based on \p percentage_delta and builds the notification.
///
std::optional<std::pair<ClearedChargingLimitRequest, std::vector<TransactionEventRequest>>>
handle_external_limit_cleared(double percentage_delta, ChargingLimitSourceEnum source,
std::optional<int32_t> evse_id) const override;

Expand Down
13 changes: 12 additions & 1 deletion lib/ocpp/v201/charge_point.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1020,8 +1020,19 @@ void ChargePoint::on_external_limits_changed(const std::variant<ConstantCharging
auto request =
this->smart_charging_handler->handle_external_limits_changed(limit, percentage_delta, source, evse_id);
if (request.has_value()) {
ocpp::Call<NotifyChargingLimitRequest> call(request.value(), this->message_queue->createMessageId());
auto [cleared_charging_limit_request, transaction_event_requests] = request.value();

ocpp::Call<NotifyChargingLimitRequest> call(cleared_charging_limit_request,
this->message_queue->createMessageId());
this->send<NotifyChargingLimitRequest>(call);

if (transaction_event_requests.size() > 0) {
for (auto transaction_event_request : transaction_event_requests) {
ocpp::Call<TransactionEventRequest> call(transaction_event_request,
this->message_queue->createMessageId());
this->send<TransactionEventRequest>(call);
}
}
}
}

Expand Down
31 changes: 22 additions & 9 deletions lib/ocpp/v201/smart_charging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -636,7 +636,7 @@ ChargingSchedule create_schedule_from_limit(const ConstantChargingLimit limit) {
};
}

std::optional<NotifyChargingLimitRequest>
std::optional<std::pair<NotifyChargingLimitRequest, std::vector<TransactionEventRequest>>>
SmartChargingHandler::handle_external_limits_changed(const std::variant<ConstantChargingLimit, ChargingSchedule>& limit,
double percentage_delta, ChargingLimitSourceEnum source,
std::optional<int32_t> evse_id) const {
Expand All @@ -647,7 +647,8 @@ SmartChargingHandler::handle_external_limits_changed(const std::variant<Constant
throw std::invalid_argument("The source of an external limit should not be CSO.");
}

std::optional<NotifyChargingLimitRequest> request = {};
NotifyChargingLimitRequest notify_charging_limit_request = {};
std::vector<TransactionEventRequest> transaction_event_requests = {};

const auto& limit_change_cv = ControllerComponentVariables::LimitChangeSignificance;
const float limit_change_significance = this->device_model->get_value<double>(limit_change_cv);
Expand All @@ -656,19 +657,31 @@ SmartChargingHandler::handle_external_limits_changed(const std::variant<Constant
const std::optional<bool> notify_with_schedules =
this->device_model->get_optional_value<bool>(notify_charging_limit_cv);

if (percentage_delta > limit_change_significance) {
request = NotifyChargingLimitRequest{};
request->evseId = evse_id;
request->chargingLimit = {.chargingLimitSource = source};
std::optional<std::pair<NotifyChargingLimitRequest, std::vector<TransactionEventRequest>>> request = {};
std::pair<NotifyChargingLimitRequest, std::vector<TransactionEventRequest>> pair;

const bool limit_change_significance_exceeded = percentage_delta > limit_change_significance;

if (limit_change_significance_exceeded) {
notify_charging_limit_request = NotifyChargingLimitRequest{};
notify_charging_limit_request.evseId = evse_id;
notify_charging_limit_request.chargingLimit = {.chargingLimitSource = source};
if (notify_with_schedules.has_value() && notify_with_schedules.value()) {
if (const auto* limit_c = std::get_if<ConstantChargingLimit>(&limit)) {
request->chargingSchedule = {{create_schedule_from_limit(*limit_c)}};
notify_charging_limit_request.chargingSchedule = {{create_schedule_from_limit(*limit_c)}};
} else if (const auto* limit_s = std::get_if<ChargingSchedule>(&limit)) {
request->chargingSchedule = {{*limit_s}};
notify_charging_limit_request.chargingSchedule = {{*limit_s}};
}
}
}
pair.first = notify_charging_limit_request;

// K11.FR.04
this->process_evses_with_active_transactions(limit_change_significance_exceeded, transaction_event_requests,
evse_id);

pair.second = transaction_event_requests;
request.emplace(pair);
}
return request;
}

Expand Down
3 changes: 2 additions & 1 deletion tests/lib/ocpp/v201/mocks/smart_charging_handler_mock.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ class SmartChargingHandlerMock : public SmartChargingHandlerInterface {
(std::vector<ChargingProfile> & valid_profiles, const ocpp::DateTime& start_time,
const ocpp::DateTime& end_time, const int32_t evse_id,
std::optional<ChargingRateUnitEnum> charging_rate_unit));
MOCK_METHOD(std::optional<NotifyChargingLimitRequest>, handle_external_limits_changed,
MOCK_METHOD((std::optional<std::pair<NotifyChargingLimitRequest, std::vector<TransactionEventRequest>>>),
handle_external_limits_changed,
(const ChargingLimitVariant& limit, double percentage_delta, ChargingLimitSourceEnum source,
std::optional<int32_t> evse_id),
(const, override));
Expand Down
79 changes: 68 additions & 11 deletions tests/lib/ocpp/v201/test_smart_charging_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1683,6 +1683,49 @@ TEST_F(SmartChargingHandlerTestFixtureV201, K05FR02_RequestStartTransactionReque
ASSERT_THAT(sut, testing::Eq(ProfileValidationResultEnum::RequestStartTransactionNonTxProfile));
}

TEST_F(SmartChargingHandlerTestFixtureV201, K11FR04_HandleChangedChargingLimitRequest_NoTransactionExists) {
const auto& limit_change_cv = ControllerComponentVariables::LimitChangeSignificance;
device_model->set_value(limit_change_cv.component, limit_change_cv.variable.value(), AttributeEnum::Actual, "0.1",
"test");

ConstantChargingLimit new_limit = {
.limit = 100.0,
.charging_rate_unit = ChargingRateUnitEnum::A,
};

double deltaChanged = 0.2;
auto source = ChargingLimitSourceEnum::Other;

auto resp = handler.handle_external_limits_changed(new_limit, deltaChanged, source, std::nullopt);
ASSERT_THAT(resp.has_value(), testing::IsTrue());

auto [notify_charging_limit_request, transaction_event_requests] = resp.value();
ASSERT_THAT(transaction_event_requests.size(), testing::Eq(0));
}

TEST_F(SmartChargingHandlerTestFixtureV201, K11FR04_HandleChangedChargingLimitRequest_OneTransactionExists) {
const auto& limit_change_cv = ControllerComponentVariables::LimitChangeSignificance;
device_model->set_value(limit_change_cv.component, limit_change_cv.variable.value(), AttributeEnum::Actual, "0.1",
"test");

std::string transaction_id = uuid();
this->evse_manager->open_transaction(DEFAULT_EVSE_ID, transaction_id);

ConstantChargingLimit new_limit = {
.limit = 100.0,
.charging_rate_unit = ChargingRateUnitEnum::A,
};

double deltaChanged = 0.2;
auto source = ChargingLimitSourceEnum::Other;

auto resp = handler.handle_external_limits_changed(new_limit, deltaChanged, source, std::nullopt);
ASSERT_THAT(resp.has_value(), testing::IsTrue());

auto [notify_charging_limit_request, transaction_event_requests] = resp.value();
ASSERT_THAT(transaction_event_requests.size(), testing::Eq(1));
}

TEST_F(SmartChargingHandlerTestFixtureV201,
K12FR02_HandleExternalLimitsChanged_LimitChangeSignificanceNotMet_ReturnNone) {
const auto& limit_change_cv = ControllerComponentVariables::LimitChangeSignificance;
Expand Down Expand Up @@ -1764,8 +1807,10 @@ TEST_F(
auto resp = handler.handle_external_limits_changed(new_limit, deltaChanged, source, DEFAULT_EVSE_ID);

ASSERT_THAT(resp.has_value(), testing::IsTrue());
ASSERT_THAT(resp->chargingSchedule.has_value(), testing::IsTrue());
ASSERT_THAT(resp->chargingSchedule.value(), testing::Contains(charging_schedule));
auto [notify_charging_limit_request, s] = resp.value();

ASSERT_THAT(notify_charging_limit_request.chargingSchedule.has_value(), testing::IsTrue());
ASSERT_THAT(notify_charging_limit_request.chargingSchedule.value(), testing::Contains(charging_schedule));
}

TEST_F(
Expand All @@ -1791,8 +1836,11 @@ TEST_F(
auto resp = handler.handle_external_limits_changed(charging_schedule, deltaChanged, source, DEFAULT_EVSE_ID);

ASSERT_THAT(resp.has_value(), testing::IsTrue());
ASSERT_THAT(resp->chargingSchedule.has_value(), testing::IsTrue());
ASSERT_THAT(resp->chargingSchedule.value(), testing::Contains(charging_schedule));

auto [notify_charging_limit_request, s] = resp.value();

ASSERT_THAT(notify_charging_limit_request.chargingSchedule.has_value(), testing::IsTrue());
ASSERT_THAT(notify_charging_limit_request.chargingSchedule.value(), testing::Contains(charging_schedule));
}

TEST_F(
Expand All @@ -1812,7 +1860,9 @@ TEST_F(
auto resp = handler.handle_external_limits_changed(new_limit, deltaChanged, source, DEFAULT_EVSE_ID);

ASSERT_THAT(resp.has_value(), testing::IsTrue());
ASSERT_THAT(resp->chargingSchedule.has_value(), testing::IsFalse());
auto [notify_charging_limit_request, s] = resp.value();

ASSERT_THAT(notify_charging_limit_request.chargingSchedule.has_value(), testing::IsFalse());
}

TEST_F(
Expand All @@ -1835,7 +1885,9 @@ TEST_F(
auto resp = handler.handle_external_limits_changed(new_limit, deltaChanged, source, DEFAULT_EVSE_ID);

ASSERT_THAT(resp.has_value(), testing::IsTrue());
ASSERT_THAT(resp->chargingSchedule.has_value(), testing::IsFalse());
auto [notify_charging_limit_request, s] = resp.value();

ASSERT_THAT(notify_charging_limit_request.chargingSchedule.has_value(), testing::IsFalse());
}

TEST_F(SmartChargingHandlerTestFixtureV201, K12FR04_HandleExternalLimitsChanged_NotificationIncludesSource) {
Expand All @@ -1853,7 +1905,9 @@ TEST_F(SmartChargingHandlerTestFixtureV201, K12FR04_HandleExternalLimitsChanged_
auto resp = handler.handle_external_limits_changed(new_limit, deltaChanged, source, DEFAULT_EVSE_ID);

ASSERT_THAT(resp.has_value(), testing::IsTrue());
ASSERT_THAT(resp->chargingLimit.chargingLimitSource, testing::Eq(source));
auto [notify_charging_limit_request, s] = resp.value();

ASSERT_THAT(notify_charging_limit_request.chargingLimit.chargingLimitSource, testing::Eq(source));
}

TEST_F(SmartChargingHandlerTestFixtureV201, K12FR04_HandleExternalLimitsChanged_ThrowsIfSourceIsCSO) {
Expand All @@ -1877,7 +1931,7 @@ TEST_F(SmartChargingHandlerTestFixtureV201, K12_HandleExternalLimitsChanged_Requ
device_model->set_value(limit_change_cv.component, limit_change_cv.variable.value(), AttributeEnum::Actual, "0.1",
"test");

auto evse_id = 12;
auto evse_id = 2;

ConstantChargingLimit new_limit = {
.limit = 100.0,
Expand All @@ -1889,9 +1943,12 @@ TEST_F(SmartChargingHandlerTestFixtureV201, K12_HandleExternalLimitsChanged_Requ
auto resp = handler.handle_external_limits_changed(new_limit, deltaChanged, source, evse_id);

ASSERT_THAT(resp.has_value(), testing::IsTrue());
ASSERT_THAT(resp->chargingLimit.chargingLimitSource, testing::Eq(source));
ASSERT_THAT(resp->evseId.has_value(), testing::IsTrue());
ASSERT_THAT(resp->evseId.value(), testing::Eq(evse_id));

auto [notify_charging_limit_request, s] = resp.value();

ASSERT_THAT(notify_charging_limit_request.chargingLimit.chargingLimitSource, testing::Eq(source));
ASSERT_THAT(notify_charging_limit_request.evseId.has_value(), testing::IsTrue());
ASSERT_THAT(notify_charging_limit_request.evseId.value(), testing::Eq(evse_id));
}

TEST_F(SmartChargingHandlerTestFixtureV201,
Expand Down

0 comments on commit 719772e

Please sign in to comment.