Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set update / Clear external charging limits #828

Draft
wants to merge 18 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
4cf7ca0
smart_charging, charge_point: Implement K12FR02
christopher-davis-afs Oct 1, 2024
7cbfaed
smart_charging: Implement K12FR03
christopher-davis-afs Oct 1, 2024
82da45e
smart_charging, charge_point: Implement K12.FR.04
christopher-davis-afs Oct 1, 2024
47a7f0a
smart_charging: Add type for constant limits
christopher-davis-afs Oct 1, 2024
f288997
misc: Add evse_id to external limits handler
christopher-davis-afs Oct 7, 2024
9cb819a
misc: Move evse_id param for external limits funcs
christopher-davis-afs Oct 8, 2024
17fe4ca
smartcharging: added handler for clearing external constraint
couryrr-afs Oct 3, 2024
287b4b0
smartcharging: updated return to handle both request types
couryrr-afs Oct 3, 2024
2e95cf4
smartcharging: added logic to check limit change significance and sen…
couryrr-afs Oct 3, 2024
ba21483
charge point: added public method to notify csms when external limit …
couryrr-afs Oct 3, 2024
33437bd
smart charging: updated transaction even with additional attributes b…
couryrr-afs Oct 3, 2024
8a9854a
updated: using vector to pass back multiple TransactionEventRequest.
couryrr-afs Oct 7, 2024
2f2267f
updated: added optional evse_id to on_handle method
couryrr-afs Oct 7, 2024
1038766
updated: added optional evse_id to handler and passed
couryrr-afs Oct 7, 2024
025de7a
updated: check for open transaction on an evse
couryrr-afs Oct 7, 2024
f0b3746
updated: moved duplicated code to method
couryrr-afs Oct 8, 2024
075ab82
updated: incorrect test fixture name
couryrr-afs Oct 9, 2024
719772e
added: logic for K11FR04 to existing handle_external_limits_changed
couryrr-afs Oct 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 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 @@ -1390,18 +1390,18 @@ This document contains the status of which OCPP 2.0.1 numbered functional requir
| ID | Status | Remark |
|-----------|--------|--------|
| K12.FR.01 | | |
| K12.FR.02 | | |
| K12.FR.03 | | |
| K12.FR.04 | | |
| K12.FR.02 | | |
| K12.FR.03 | | |
| 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

| ID | Status | Remark |
|-----------|--------|--------|
| K13.FR.01 | | |
| K13.FR.02 | | |
| K13.FR.03 | | |
| K13.FR.02 | | |
| K13.FR.03 | | |

## SmartCharging - External Charging Limit with Local Controller

Expand Down
26 changes: 26 additions & 0 deletions include/ocpp/v201/charge_point.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,25 @@ class ChargePointInterface {
///
virtual void on_variable_changed(const SetVariableData& set_variable_data) = 0;

/// \brief Notifies the ChargePoint that a new external limit has been set. This may send a
/// NotifyChargingLimitRequest if the \p percentage_delta is greater than our LimitChangeSignificance.
/// \param evse_id ID of the EVSE with the external limit
/// \param limit the new external limit
/// \param percentage_delta the percent changed from the existing limits
/// \param source the source of the external limit (NOTE: Should never be CSO)
virtual void on_external_limits_changed(const std::variant<ConstantChargingLimit, ChargingSchedule>& limit,
double percentage_delta, ChargingLimitSourceEnum source,
std::optional<int32_t> evse_id) = 0;

/// \brief Notifies the ChargePoint that an external limit has been cleared.
/// This shall send a ClearedChargingLimitRequest when called.
// This may send TransactionEventRequest if the \p percentage_delta is greater than our LimitChangeSignificance.
/// \param percentage_delta the percent changed from the existing limits
/// \param source the source of the external limit
/// \param evse_id if provided checks for transactions on the provided evse
virtual void on_external_limit_cleared(double percentage_delta, ChargingLimitSourceEnum source,
std::optional<int32_t> evse_id) = 0;

/// \brief Data transfer mechanism initiated by charger
/// \param vendorId
/// \param messageId
Expand Down Expand Up @@ -819,6 +838,13 @@ class ChargePoint : public ChargePointInterface, private ocpp::ChargingStationBa

void on_variable_changed(const SetVariableData& set_variable_data) override;

void on_external_limits_changed(const std::variant<ConstantChargingLimit, ChargingSchedule>& limit,
double percentage_delta, ChargingLimitSourceEnum source,
std::optional<int32_t> evse_id) override;

void on_external_limit_cleared(double percentage_delta, ChargingLimitSourceEnum source,
std::optional<int32_t> evse_id) override;

std::optional<DataTransferResponse> data_transfer_req(const CiString<255>& vendorId,
const std::optional<CiString<50>>& messageId,
const std::optional<json>& data) override;
Expand Down
44 changes: 44 additions & 0 deletions include/ocpp/v201/smart_charging.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,21 @@
#ifndef OCPP_V201_SMART_CHARGING_HPP
#define OCPP_V201_SMART_CHARGING_HPP

#include "ocpp/v201/comparators.hpp"
#include "ocpp/v201/messages/ClearedChargingLimit.hpp"
#include "ocpp/v201/messages/TransactionEvent.hpp"
#include <limits>
#include <memory>
#include <optional>
#include <utility>
#include <variant>

#include <ocpp/v201/database_handler.hpp>
#include <ocpp/v201/device_model.hpp>
#include <ocpp/v201/evse_manager.hpp>
#include <ocpp/v201/messages/ClearChargingProfile.hpp>
#include <ocpp/v201/messages/GetChargingProfiles.hpp>
#include <ocpp/v201/messages/NotifyChargingLimit.hpp>
#include <ocpp/v201/messages/SetChargingProfile.hpp>
#include <ocpp/v201/ocpp_enums.hpp>
#include <ocpp/v201/ocpp_types.hpp>
Expand Down Expand Up @@ -56,6 +63,13 @@
RequestStartTransactionRequest
};

struct ConstantChargingLimit {
float limit;

Check notice on line 67 in include/ocpp/v201/smart_charging.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

include/ocpp/v201/smart_charging.hpp#L67

struct member 'ConstantChargingLimit::limit' is never used.
ChargingRateUnitEnum charging_rate_unit;
};

bool operator==(const ConstantChargingLimit& a, const ConstantChargingLimit& b);

namespace conversions {
/// \brief Converts the given ProfileValidationResultEnum \p e to human readable string
/// \returns a string representation of the ProfileValidationResultEnum
Expand Down Expand Up @@ -97,6 +111,15 @@
const ocpp::DateTime& start_time,
const ocpp::DateTime& end_time, const int32_t evse_id,
std::optional<ChargingRateUnitEnum> charging_rate_unit) = 0;

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;

virtual std::optional<std::pair<ClearedChargingLimitRequest, std::vector<TransactionEventRequest>>>
handle_external_limit_cleared(double percentage_delta, ChargingLimitSourceEnum source,
std::optional<int32_t> evse_id) const = 0;
};

/// \brief This class handles and maintains incoming ChargingProfiles and contains the logic
Expand Down Expand Up @@ -165,6 +188,23 @@
const int32_t evse_id,
std::optional<ChargingRateUnitEnum> charging_rate_unit) override;

///
/// \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<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;

///
/// \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;

protected:
///
/// \brief validates the existence of the given \p evse_id according to the specification
Expand Down Expand Up @@ -218,6 +258,10 @@
std::vector<ChargingProfile> get_valid_profiles_for_evse(int32_t evse_id);
void conform_validity_periods(ChargingProfile& profile) const;
CurrentPhaseType get_current_phase_type(const std::optional<EvseInterface*> evse_opt) const;
TransactionEventRequest create_transaction_event_request(std::unique_ptr<EnhancedTransaction>& tx) const;
bool process_evses_with_active_transactions(const bool limit_change_significance_exceeded,
std::vector<TransactionEventRequest>& transaction_event_requests,
std::optional<int32_t> evse_id) const;
};

} // namespace ocpp::v201
Expand Down
45 changes: 45 additions & 0 deletions lib/ocpp/v201/charge_point.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest

#include <cstdint>
#include <ocpp/common/types.hpp>
#include <ocpp/v201/charge_point.hpp>
#include <ocpp/v201/ctrlr_component_variables.hpp>
Expand Down Expand Up @@ -1013,6 +1014,50 @@ void ChargePoint::on_variable_changed(const SetVariableData& set_variable_data)
this->handle_variable_changed(set_variable_data);
}

void ChargePoint::on_external_limits_changed(const std::variant<ConstantChargingLimit, ChargingSchedule>& limit,
double percentage_delta, ChargingLimitSourceEnum source,
std::optional<int32_t> evse_id) {
auto request =
this->smart_charging_handler->handle_external_limits_changed(limit, percentage_delta, source, evse_id);
if (request.has_value()) {
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);
}
}
}
}

void ChargePoint::on_external_limit_cleared(double percentage_delta, ChargingLimitSourceEnum source,
std::optional<int32_t> evse_id) {
auto request = this->smart_charging_handler->handle_external_limit_cleared(percentage_delta, source, evse_id);

if (request.has_value()) {

auto [cleared_charging_limit_request, transaction_event_requests] = request.value();

ocpp::Call<ClearedChargingLimitRequest> call(cleared_charging_limit_request,
this->message_queue->createMessageId());
this->send<ClearedChargingLimitRequest>(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);
}
}
}
}

bool ChargePoint::send(CallError call_error) {
this->message_queue->push(call_error);
return true;
Expand Down
Loading
Loading