- 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
224 lines
8.0 KiB
C++
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
|