Files
cariflex/tools/EVerest-main/modules/EVSE/OCPP201/transaction_handler.hpp
Eric F d398a6ced2 Add extracted tools: CitrineOS, OpenOCPP, ShapeShifter
- CitrineOS core extracted (CSMS OCPP 2.0.1)
- OpenOCPP extracted (firmware OCPP 1.6J/2.0.1)
- ShapeShifter library installed (pip install -e)
- ShapeShifter specification extracted
- EVerest extracted

TODO updated with progress
2026-06-08 00:38:27 -04:00

224 lines
8.0 KiB
C++

// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest
#pragma once
#include <cstdint>
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <vector>
#include <ocpp/v2/ocpp_types.hpp>
namespace module {
/// \brief TxStartStopPoint of OCPP2.0.1
enum class TxStartStopPoint {
ParkingBayOccupancy,
EVConnected,
Authorized,
PowerPathClosed,
EnergyTransfer,
DataSigned
};
/// \brief TxEvents that influence if conditions for TxStartStopPoints are fullfilled
enum class TxEvent {
NONE,
EV_CONNECTED,
EV_DISCONNECTED,
AUTHORIZED,
DEAUTHORIZED,
PARKING_BAY_OCCUPIED,
PARKING_BAY_UNOCCUPIED,
ENERGY_TRANSFER_STARTED,
ENERGY_TRANSFER_STOPPED,
SIGNED_START_DATA_RECEIVED,
IMMEDIATE_RESET
};
/// \brief Effect to an TxEvent. An effect can either trigger the start of a Transaction, the stop of a transaction or
/// it can have no effect
enum class TxEventEffect {
START_TRANSACTION,
STOP_TRANSACTION,
NONE
};
/// \brief Struct that contains boolean conditions from which a TxEventEffect can be derived
struct TxStartStopConditions {
bool is_authorized = false;
bool is_ev_connected = false;
bool is_parking_bay_occupied = false;
bool is_energy_transfered = false;
bool is_signed_data_received = false;
bool is_immediate_reset = false;
void submit_event(const TxEvent tx_event) {
switch (tx_event) {
case TxEvent::EV_CONNECTED:
is_ev_connected = true;
break;
case TxEvent::EV_DISCONNECTED:
is_ev_connected = false;
is_energy_transfered = false;
break;
case TxEvent::AUTHORIZED:
is_authorized = true;
break;
case TxEvent::DEAUTHORIZED:
is_authorized = false;
break;
case TxEvent::PARKING_BAY_OCCUPIED:
is_parking_bay_occupied = true;
break;
case TxEvent::PARKING_BAY_UNOCCUPIED:
is_parking_bay_occupied = false;
break;
case TxEvent::ENERGY_TRANSFER_STARTED:
is_energy_transfered = true;
break;
case TxEvent::ENERGY_TRANSFER_STOPPED:
is_energy_transfered = false;
break;
case TxEvent::SIGNED_START_DATA_RECEIVED:
is_signed_data_received = true;
break;
case TxEvent::IMMEDIATE_RESET:
is_immediate_reset = true;
break;
case TxEvent::NONE:
break;
}
};
bool is_start_condition_fullfilled(const TxStartStopPoint tx_start_point) {
switch (tx_start_point) {
case TxStartStopPoint::ParkingBayOccupancy:
return is_parking_bay_occupied;
case TxStartStopPoint::EVConnected:
return is_ev_connected;
case TxStartStopPoint::Authorized:
return is_authorized;
case TxStartStopPoint::PowerPathClosed:
return is_authorized and is_ev_connected;
case TxStartStopPoint::EnergyTransfer:
return is_energy_transfered;
case TxStartStopPoint::DataSigned:
return is_signed_data_received;
default:
return false;
}
};
bool is_stop_condition_fullfilled(const TxStartStopPoint tx_stop_point) {
if (is_immediate_reset) {
return true;
}
switch (tx_stop_point) {
case TxStartStopPoint::ParkingBayOccupancy:
return !is_parking_bay_occupied;
case TxStartStopPoint::EVConnected:
return !is_ev_connected;
case TxStartStopPoint::Authorized:
return !is_authorized;
case TxStartStopPoint::PowerPathClosed:
return !is_authorized or !is_ev_connected;
case TxStartStopPoint::EnergyTransfer:
return !is_energy_transfered;
case TxStartStopPoint::DataSigned:
return false;
}
return false;
};
};
/// \brief Contains information that is required for a TransactionEvent (Started / Stopped) message in OCPP2.0.1.
struct TransactionData {
bool started = false;
int32_t connector_id;
std::string session_id;
ocpp::DateTime timestamp;
ocpp::v2::TriggerReasonEnum trigger_reason;
ocpp::v2::MeterValue meter_value;
ocpp::v2::ChargingStateEnum charging_state;
ocpp::v2::ReasonEnum stop_reason = ocpp::v2::ReasonEnum::Other;
std::optional<ocpp::v2::IdToken> id_token;
std::optional<ocpp::v2::IdToken> group_id_token;
std::optional<int32_t> reservation_id;
std::optional<int32_t> remote_start_id;
TransactionData(const int32_t connector_id, const std::string& session_id, const ocpp::DateTime timestamp,
const ocpp::v2::TriggerReasonEnum trigger_reason,
const ocpp::v2::ChargingStateEnum charging_state) :
connector_id(connector_id),
session_id(session_id),
timestamp(timestamp),
trigger_reason(trigger_reason),
charging_state(charging_state){};
};
/// \brief OCPP2.0.1 defines configurable TxStartPoints and TxStopPoints. This class handles TxEvents to determine when
/// OCPP2.0.1 transactions shall start and stop.
class TransactionHandler {
public:
TransactionHandler(const int32_t nr_of_evses, const std::set<TxStartStopPoint>& tx_start_points,
const std::set<TxStartStopPoint>& tx_stop_points);
/// \brief Submits the given \p tx_event at the given \p evse_id . Based on the configured \ref tx_start_points and
/// \ref tx_stop_points, this function determines if a Transaction shall start or stop. The effect of the event is
/// returned
/// \param evse_id
/// \param tx_event
/// \return
TxEventEffect submit_event(const int32_t evse_id, const TxEvent tx_event);
/// \brief Sets the given \p tx_start_points
void set_tx_start_points(const std::set<TxStartStopPoint>& tx_start_points);
/// \brief Sets the given \p tx_stop_points
void set_tx_stop_points(const std::set<TxStartStopPoint>& tx_stop_points);
/// \brief Adds \p transaction_data to \ref evse_id_transaction_data_map for the given \p evse_id
/// \param evse_id
/// \param transaction_data
void add_transaction_data(const int32_t evse_id, const std::shared_ptr<TransactionData>& transaction_data);
/// \brief Gets evse_id associated to a specific transaction id.
std::shared_ptr<TransactionData> get_transaction_data(const int32_t evse_id);
/// \brief Gets transaction_data for the given \p evse_id from the \ref evse_id_transaction_data_map
/// \param transaction_id string corresponding to the id of the transaction
/// \return will return -1 if not found, else will return associated evse_id
int get_evse_id(const std::string& transaction_id);
/// \brief Resets transaction_data for the given \p evse_id in the \ref evse_id_transaction_data_map. It efectively
/// sets the value for the \p evse_id to nullptr
void reset_transaction_data(const int32_t evse_id);
private:
std::set<TxStartStopPoint> tx_start_points;
std::set<TxStartStopPoint> tx_stop_points;
// map that holds information about states that are relevant in order to determine start and stop of OCPP2.0.1
// transactions
std::map<int32_t, TxStartStopConditions> tx_start_stop_conditions;
// map that holds transaction_data for each evse_id . The transaction_data shall be updated based on the present
// information available on the charge point
std::map<int32_t, std::shared_ptr<TransactionData>> evse_id_transaction_data_map;
/// \brief Determines if a transaction shall start for the given \p evse_id based on the present \ref
/// tx_start_stop_conditions for this \p evse_id
bool should_transaction_start(const int32_t evse_id);
/// \brief Determines if a transaction shall stop for the given \p evse_id based on the present \ref
/// tx_start_stop_conditions for this \p evse_id
bool should_transaction_stop(const int32_t evse_id);
};
} // namespace module