Skip to content

Commit

Permalink
WIP: TxStartPoint EnergyTransfer support
Browse files Browse the repository at this point in the history
Signed-off-by: Kai-Uwe Hermann <[email protected]>
  • Loading branch information
hikinggrass committed Jan 17, 2024
1 parent 04a1979 commit 4de2cd9
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 10 deletions.
87 changes: 79 additions & 8 deletions modules/OCPP201/OCPP201.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,25 @@ ocpp::v201::IdToken get_id_token(const types::authorization::ProvidedIdToken& pr
return id_token;
}

TxStartPoint get_tx_start_point(const std::string& tx_start_point_string) {
if (tx_start_point_string == "ParkingBayOccupancy") {
return TxStartPoint::ParkingBayOccupancy;
} else if (tx_start_point_string == "EVConnected") {
return TxStartPoint::EVConnected;
} else if (tx_start_point_string == "Authorized") {
return TxStartPoint::Authorized;
} else if (tx_start_point_string == "PowerPathClosed") {
return TxStartPoint::PowerPathClosed;
} else if (tx_start_point_string == "EnergyTransfer") {
return TxStartPoint::EnergyTransfer;
} else if (tx_start_point_string == "DataSigned") {
return TxStartPoint::DataSigned;
}

// default to PowerPathClosed for now
return TxStartPoint::PowerPathClosed;
}

void OCPP201::init_evse_ready_map() {
std::lock_guard<std::mutex> lk(this->evse_ready_mutex);
for (size_t evse_id = 1; evse_id <= this->r_evse_manager.size(); evse_id++) {
Expand Down Expand Up @@ -873,6 +892,17 @@ void OCPP201::ready() {
this->r_auth->call_set_connection_timeout(ev_connection_timeout_request_value_response.value.value());
}

const auto tx_start_point_request_value_response = this->charge_point->request_value<std::string>(
ocpp::v201::Component{"TxCtrlr"}, ocpp::v201::Variable{"TxStartPoint"}, ocpp::v201::AttributeEnum::Actual);
if (tx_start_point_request_value_response.status == ocpp::v201::GetVariableStatusEnum::Accepted and
tx_start_point_request_value_response.value.has_value()) {
auto tx_start_point_string = tx_start_point_request_value_response.value.value();
this->tx_start_point = get_tx_start_point(tx_start_point_string);
EVLOG_info << "TxStartPoint from device model: " << tx_start_point_string;
} else {
this->tx_start_point = TxStartPoint::PowerPathClosed;
}

if (this->config.EnableExternalWebsocketControl) {
const std::string connect_topic = "everest_api/ocpp/cmd/connect";
this->mqtt.subscribe(connect_topic,
Expand All @@ -887,10 +917,28 @@ void OCPP201::ready() {
for (const auto& evse : this->r_evse_manager) {
evse->subscribe_session_event([this, evse_id](types::evse_manager::SessionEvent session_event) {
const auto connector_id = session_event.connector_id.value_or(1);
const auto evse_connector = std::make_pair(evse_id, connector_id);
switch (session_event.event) {
case types::evse_manager::SessionEventEnum::SessionStarted: {
this->session_started_reason = session_event.session_started.value().reason;
this->charge_point->on_session_started(evse_id, connector_id);
if (!session_event.session_started.has_value()) {
this->session_started_reasons[evse_connector] =
types::evse_manager::StartSessionReason::EVConnected;
} else {
this->session_started_reasons[evse_connector] = session_event.session_started.value().reason;
}

switch (this->tx_start_point) {
case TxStartPoint::EVConnected:
[[fallthrough]];
case TxStartPoint::Authorized:
[[fallthrough]];
case TxStartPoint::PowerPathClosed:
this->charge_point->on_session_started(evse_id, connector_id);
break;
case TxStartPoint::EnergyTransfer:
// TODO: does this need a session_started/PlugIn event later?
break;
}
break;
}
case types::evse_manager::SessionEventEnum::SessionFinished: {
Expand All @@ -913,19 +961,27 @@ void OCPP201::ready() {
auto trigger_reason = ocpp::v201::TriggerReasonEnum::Authorized;

// if session started reason was Authorized, Transaction is started because of EV plug in event
if (this->session_started_reason == types::evse_manager::StartSessionReason::Authorized) {
if (this->session_started_reasons[evse_connector] ==
types::evse_manager::StartSessionReason::Authorized) {
trigger_reason = ocpp::v201::TriggerReasonEnum::CablePluggedIn;
}

if (transaction_started.id_tag.authorization_type == types::authorization::AuthorizationType::OCPP) {
trigger_reason = ocpp::v201::TriggerReasonEnum::RemoteStart;
}

this->charge_point->on_transaction_started(
evse_id, connector_id, session_id, timestamp, trigger_reason, meter_value, id_token, std::nullopt,
reservation_id, remote_start_id,
ocpp::v201::ChargingStateEnum::EVConnected); // FIXME(piet): add proper groupIdToken +
// ChargingStateEnum
if (this->tx_start_point == TxStartPoint::EnergyTransfer) {
this->transaction_starts[evse_connector].emplace(TransactionStart{
evse_id, connector_id, session_id, timestamp, trigger_reason, meter_value, id_token,
std::nullopt, reservation_id, remote_start_id, ocpp::v201::ChargingStateEnum::Charging});
} else {
this->charge_point->on_transaction_started(
evse_id, connector_id, session_id, timestamp, trigger_reason, meter_value, id_token,
std::nullopt, reservation_id, remote_start_id,
ocpp::v201::ChargingStateEnum::EVConnected); // FIXME(piet): add proper groupIdToken +
// ChargingStateEnum
}

break;
}
case types::evse_manager::SessionEventEnum::TransactionFinished: {
Expand All @@ -952,6 +1008,21 @@ void OCPP201::ready() {
break;
}
case types::evse_manager::SessionEventEnum::ChargingStarted: {
if (this->tx_start_point == TxStartPoint::EnergyTransfer) {
if (this->transaction_starts[evse_connector].has_value()) {
auto transaction_start = this->transaction_starts[evse_connector].value();
this->charge_point->on_transaction_started(
transaction_start.evse_id, transaction_start.connector_id, transaction_start.session_id,
transaction_start.timestamp, transaction_start.trigger_reason,
transaction_start.meter_start, transaction_start.id_token, transaction_start.group_id_token,
transaction_start.reservation_id, transaction_start.remote_start_id,
transaction_start.charging_state);
this->transaction_starts[evse_connector].reset();
} else {
EVLOG_error
<< "ChargingStarted with TxStartPoint EnergyTransfer but no TransactionStart was available";
}
}
this->charge_point->on_charging_state_changed(evse_id, ocpp::v201::ChargingStateEnum::Charging);
break;
}
Expand Down
34 changes: 32 additions & 2 deletions modules/OCPP201/OCPP201.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@

// ev@4bf81b14-a215-475c-a1d3-0a484ae48918:v1
// insert your custom include headers here
#include <tuple>

#include <ocpp/v201/charge_point.hpp>

struct Evse {
Expand All @@ -36,6 +38,29 @@ struct Evse {
return connectors.at(connector_id);
}
};

enum class TxStartPoint {
ParkingBayOccupancy,
EVConnected,
Authorized,
PowerPathClosed,
EnergyTransfer,
DataSigned
};

struct TransactionStart {
int32_t evse_id;

Check notice on line 52 in modules/OCPP201/OCPP201.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

modules/OCPP201/OCPP201.hpp#L52

struct member 'TransactionStart::evse_id' is never used.
int32_t connector_id;

Check notice on line 53 in modules/OCPP201/OCPP201.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

modules/OCPP201/OCPP201.hpp#L53

struct member 'TransactionStart::connector_id' is never used.
std::string session_id;

Check notice on line 54 in modules/OCPP201/OCPP201.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

modules/OCPP201/OCPP201.hpp#L54

struct member 'TransactionStart::session_id' is never used.
ocpp::DateTime timestamp;
ocpp::v201::TriggerReasonEnum trigger_reason;
ocpp::v201::MeterValue meter_start;
ocpp::v201::IdToken id_token;
std::optional<ocpp::v201::IdToken> group_id_token;
std::optional<int32_t> reservation_id;
std::optional<int32_t> remote_start_id;
ocpp::v201::ChargingStateEnum charging_state;
};
// ev@4bf81b14-a215-475c-a1d3-0a484ae48918:v1

namespace module {
Expand Down Expand Up @@ -105,8 +130,13 @@ class OCPP201 : public Everest::ModuleBase {

// ev@211cfdbe-f69a-4cd6-a4ec-f8aaa3d1b6c8:v1
// insert your private definitions here
types::evse_manager::StartSessionReason session_started_reason; // keep track of this to be able to report correct
// trigger reason in TransactionStarted event
// track the session started reasons for every EVSE+Connector combination to be able to report correct trigger
// reason in TransactionStarted event
std::map<std::pair<int32_t, int32_t>, types::evse_manager::StartSessionReason> session_started_reasons;

Check notice on line 135 in modules/OCPP201/OCPP201.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

modules/OCPP201/OCPP201.hpp#L135

class member 'OCPP201::session_started_reasons' is never used.
std::map<std::pair<int32_t, int32_t>, std::optional<TransactionStart>> transaction_starts;

Check notice on line 136 in modules/OCPP201/OCPP201.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

modules/OCPP201/OCPP201.hpp#L136

class member 'OCPP201::transaction_starts' is never used.

TxStartPoint tx_start_point;

Check notice on line 138 in modules/OCPP201/OCPP201.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

modules/OCPP201/OCPP201.hpp#L138

class member 'OCPP201::tx_start_point' is never used.

std::filesystem::path ocpp_share_path;

// holds operational states of EVSE
Expand Down

0 comments on commit 4de2cd9

Please sign in to comment.