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
This commit is contained in:
425
tools/EVerest-main/modules/EVSE/EvseV2G/v2g.hpp
Normal file
425
tools/EVerest-main/modules/EVSE/EvseV2G/v2g.hpp
Normal file
@@ -0,0 +1,425 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright (C) 2022-2023 chargebyte GmbH
|
||||
// Copyright (C) 2022-2023 Contributors to EVerest
|
||||
#ifndef V2G_H
|
||||
#define V2G_H
|
||||
|
||||
#include <generated/interfaces/ISO15118_charger/Implementation.hpp>
|
||||
#include <generated/interfaces/ISO15118_vas/Interface.hpp>
|
||||
#include <generated/interfaces/evse_security/Interface.hpp>
|
||||
#include <generated/interfaces/iso15118_extensions/Implementation.hpp>
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <netinet/in.h>
|
||||
#include <pthread.h>
|
||||
#include <vector>
|
||||
|
||||
#include <everest/tls/openssl_util.hpp>
|
||||
#include <everest/tls/tls.hpp>
|
||||
|
||||
#include <cbv2g/app_handshake/appHand_Datatypes.h>
|
||||
#include <cbv2g/common/exi_basetypes.h>
|
||||
#include <cbv2g/common/exi_bitstream.h>
|
||||
#include <cbv2g/din/din_msgDefDatatypes.h>
|
||||
#include <cbv2g/iso_2/iso2_msgDefDatatypes.h>
|
||||
|
||||
#include <event2/event.h>
|
||||
#include <event2/thread.h>
|
||||
|
||||
/* timeouts in milliseconds */
|
||||
#define V2G_SEQUENCE_TIMEOUT_60S 60000 /* [V2G2-443] et.al. */
|
||||
#define V2G_SEQUENCE_TIMEOUT_10S 10000
|
||||
#define V2G_CP_STATE_B_TO_C_D_TIMEOUT 250 /* [V2G2-847] */
|
||||
#define V2G_CP_STATE_B_TO_C_D_TIMEOUT_RELAXED 500 /* [V2G2-847] */
|
||||
#define V2G_CP_STATE_C_D_TO_B_TIMEOUT 250 /* [V2G2-848] */
|
||||
#define V2G_CONTACTOR_CLOSE_TIMEOUT 3000 /* [V2G2-862] [V2G2-865] 4.5 s for PowerDeliveryRes */
|
||||
#define V2G_COMMUNICATION_SETUP_TIMEOUT \
|
||||
18000 /* [V2G2-723] [V2G2-029] [V2G2-032] [V2G2-714] [V2G2-716] V2G_SECC_CommunicationSetup_Performance_Time */
|
||||
#define V2G_CPSTATE_DETECTION_TIMEOUT \
|
||||
1500 /* [V2G-DC-547] not (yet) defined for ISO and not implemented, but may be implemented */
|
||||
#define V2G_CPSTATE_DETECTION_TIMEOUT_RELAXED \
|
||||
3000 /* [V2G-DC-547] not (yet) defined for ISO and not implemented, but may be implemented */
|
||||
|
||||
#define SA_SCHEDULE_DURATION 86400
|
||||
|
||||
#define ISO_15118_2013_MSG_DEF "urn:iso:15118:2:2013:MsgDef"
|
||||
#define ISO_15118_2013_MAJOR 2
|
||||
#define ISO_15118_2013_MINOR 0
|
||||
|
||||
#define ISO_15118_2010_MSG_DEF "urn:iso:15118:2:2010:MsgDef"
|
||||
#define ISO_15118_2010_MAJOR 1
|
||||
|
||||
#define DIN_70121_MSG_DEF "urn:din:70121:2012:MsgDef"
|
||||
#define DIN_70121_MAJOR 2
|
||||
#define DIN_70121_MINOR 0
|
||||
|
||||
#define EVSE_LEAF_KEY_FILE_NAME "CPO_EVSE_LEAF.key"
|
||||
#define EVSE_PROV_KEY_FILE_NAME "PROV_LEAF.key"
|
||||
#define MO_ROOT_CRT_NAME "MO_ROOT_CRT"
|
||||
#define V2G_ROOT_CRT_NAME "V2G_ROOT_CRT"
|
||||
#define MAX_V2G_ROOT_CERTS 10
|
||||
#define MAX_KEY_PW_LEN 32
|
||||
#define FORCE_PUB_MSG 25 // max msg cycles when topics values must be udpated
|
||||
#define MAX_PCID_LEN 17
|
||||
|
||||
#define GEN_CHALLENGE_SIZE 16
|
||||
|
||||
#define DEFAULT_BUFFER_SIZE 8192
|
||||
|
||||
#define DEBUG 1
|
||||
|
||||
enum tls_security_level {
|
||||
TLS_SECURITY_ALLOW = 0,
|
||||
TLS_SECURITY_PROHIBIT,
|
||||
TLS_SECURITY_FORCE
|
||||
};
|
||||
|
||||
enum v2g_event {
|
||||
V2G_EVENT_NO_EVENT = 0,
|
||||
V2G_EVENT_TERMINATE_CONNECTION, // Terminate the connection immediately
|
||||
V2G_EVENT_SEND_AND_TERMINATE, // Send next msg and terminate the connection
|
||||
V2G_EVENT_SEND_RECV_EXI_MSG, // If msg must not be exi-encoded and can be sent directly
|
||||
V2G_EVENT_IGNORE_MSG // Received message can't be handled
|
||||
};
|
||||
|
||||
enum v2g_protocol {
|
||||
V2G_PROTO_DIN70121 = 0,
|
||||
V2G_PROTO_ISO15118_2010,
|
||||
V2G_PROTO_ISO15118_2013,
|
||||
V2G_PROTO_ISO15118_2015,
|
||||
V2G_UNKNOWN_PROTOCOL
|
||||
};
|
||||
|
||||
/* ISO 15118 table 105 */
|
||||
enum v2g_service {
|
||||
V2G_SERVICE_ID_CHARGING = 1,
|
||||
V2G_SERVICE_ID_CERTIFICATE = 2,
|
||||
V2G_SERVICE_ID_INTERNET = 3,
|
||||
V2G_SERVICE_ID_USECASEINFORMATION = 4,
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief The charging_phase enum to identify the actual charing phase.
|
||||
*/
|
||||
enum charging_phase {
|
||||
PHASE_INIT = 0,
|
||||
PHASE_AUTH,
|
||||
PHASE_PARAMETER,
|
||||
PHASE_ISOLATION,
|
||||
PHASE_PRECHARGE,
|
||||
PHASE_CHARGE,
|
||||
PHASE_WELDING,
|
||||
PHASE_STOP,
|
||||
PHASE_LENGTH
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief The res_msg_ids enum is a list of response msg ids
|
||||
*/
|
||||
enum V2gMsgTypeId {
|
||||
V2G_SUPPORTED_APP_PROTOCOL_MSG = 0,
|
||||
V2G_SESSION_SETUP_MSG,
|
||||
V2G_SERVICE_DISCOVERY_MSG,
|
||||
V2G_SERVICE_DETAIL_MSG,
|
||||
V2G_PAYMENT_SERVICE_SELECTION_MSG,
|
||||
V2G_PAYMENT_DETAILS_MSG,
|
||||
V2G_AUTHORIZATION_MSG,
|
||||
V2G_CHARGE_PARAMETER_DISCOVERY_MSG,
|
||||
V2G_METERING_RECEIPT_MSG,
|
||||
V2G_CERTIFICATE_UPDATE_MSG,
|
||||
V2G_CERTIFICATE_INSTALLATION_MSG,
|
||||
V2G_CHARGING_STATUS_MSG,
|
||||
V2G_CABLE_CHECK_MSG,
|
||||
V2G_PRE_CHARGE_MSG,
|
||||
V2G_POWER_DELIVERY_MSG,
|
||||
V2G_CURRENT_DEMAND_MSG,
|
||||
V2G_WELDING_DETECTION_MSG,
|
||||
V2G_SESSION_STOP_MSG,
|
||||
V2G_UNKNOWN_MSG
|
||||
};
|
||||
|
||||
/* EVSE ID */
|
||||
struct v2g_evse_id {
|
||||
uint8_t bytes[iso2_EVSEID_CHARACTER_SIZE];
|
||||
uint16_t bytesLen;
|
||||
};
|
||||
|
||||
/* Meter ID */
|
||||
struct v2g_meter_id {
|
||||
uint8_t bytes[iso2_MeterID_CHARACTER_SIZE];
|
||||
uint16_t bytesLen;
|
||||
};
|
||||
|
||||
/* Struct for tls-session-log-key tracing */
|
||||
typedef struct keylogDebugCtx {
|
||||
FILE* file;
|
||||
bool inClientRandom;
|
||||
bool inMasterSecret;
|
||||
uint8_t hexdumpLinesToProcess;
|
||||
int udp_socket;
|
||||
std::string udp_buffer;
|
||||
} keylogDebugCtx;
|
||||
|
||||
struct SAE_Bidi_Data {
|
||||
bool enabled_sae_v2h;
|
||||
bool enabled_sae_v2g;
|
||||
int8_t sae_v2h_minimal_soc;
|
||||
bool discharging;
|
||||
};
|
||||
|
||||
enum NoEnergyPauseStatus {
|
||||
None,
|
||||
AllowEvToIgnorePause,
|
||||
AfterCableCheckPreCharge,
|
||||
BeforeCableCheck,
|
||||
};
|
||||
|
||||
struct PowerCapabilities {
|
||||
iso2_PhysicalValueType max_current;
|
||||
iso2_PhysicalValueType min_current;
|
||||
iso2_PhysicalValueType max_power;
|
||||
iso2_PhysicalValueType max_voltage;
|
||||
iso2_PhysicalValueType min_voltage;
|
||||
};
|
||||
|
||||
/**
|
||||
* Abstracts a charging port, i.e. a power outlet in this daemon.
|
||||
*
|
||||
* **** NOTE ****
|
||||
* Be very careful about adding C++ objects since constructors and
|
||||
* destructors are not called. (see v2g_ctx_create() and calloc)
|
||||
*/
|
||||
struct v2g_context {
|
||||
std::atomic_bool shutdown;
|
||||
|
||||
evse_securityIntf* r_security;
|
||||
std::vector<ISO15118_vasIntf*> r_vas;
|
||||
ISO15118_chargerImplBase* p_charger;
|
||||
iso15118_extensionsImplBase* p_extensions;
|
||||
|
||||
struct event_base* event_base;
|
||||
pthread_t event_thread;
|
||||
|
||||
const char* if_name;
|
||||
struct sockaddr_in6* local_tcp_addr;
|
||||
struct sockaddr_in6* local_tls_addr;
|
||||
|
||||
std::string tls_key_logging_path;
|
||||
|
||||
uint32_t network_read_timeout; /* in milli seconds */
|
||||
uint32_t network_read_timeout_tls; /* in milli seconds */
|
||||
|
||||
enum tls_security_level tls_security;
|
||||
|
||||
int sdp_socket;
|
||||
int tcp_socket;
|
||||
|
||||
int udp_port;
|
||||
int udp_socket;
|
||||
|
||||
pthread_t tcp_thread;
|
||||
|
||||
struct {
|
||||
int fd;
|
||||
} tls_socket;
|
||||
tls::Server* tls_server;
|
||||
|
||||
bool tls_key_logging;
|
||||
|
||||
pthread_mutex_t mqtt_lock;
|
||||
pthread_cond_t mqtt_cond;
|
||||
pthread_condattr_t mqtt_attr;
|
||||
|
||||
struct {
|
||||
float evse_ac_current_limit; // default is 0
|
||||
float evse_ac_nominal_current; // default is 0
|
||||
float evse_ac_nominal_voltage; // default is 230
|
||||
} basic_config; // This config will not reseted after beginning of a new charging session
|
||||
|
||||
/* actual charging state */
|
||||
enum V2gMsgTypeId last_v2g_msg; /* holds the current v2g msg type */
|
||||
enum V2gMsgTypeId current_v2g_msg; /* holds the last v2g msg type */
|
||||
int state; /* holds the current state id */
|
||||
bool is_dc_charger; /* Is set to true if it is a DC charger. Value is configured after configuration of the
|
||||
supported energy type */
|
||||
bool debugMode; /* To activate/deactivate the debug mode */
|
||||
std::atomic<int8_t>
|
||||
supported_protocols; /* Is an bit mask and holds the supported app protocols. See v2g_protocol enum */
|
||||
enum v2g_protocol selected_protocol; /* Holds the selected protocole after supported app protocol */
|
||||
std::atomic<bool>
|
||||
intl_emergency_shutdown; /* Is set to true if an internal emergency_shutdown has occurred (send failed response,
|
||||
configure emergency shutdown in EVSEStatus and close tcp connection) */
|
||||
std::atomic_bool stop_hlc; /* is set to true if a shutdown of the charging session should be initiated (send failed
|
||||
response and close tcp connection) */
|
||||
std::atomic_bool is_connection_terminated; /* Is set to true if the connection is terminated (CP State A/F, shutdown
|
||||
immediately without response message) */
|
||||
std::atomic<bool> terminate_connection_on_failed_response;
|
||||
std::atomic<bool> contactor_is_closed; /* Actual contactor state */
|
||||
|
||||
struct {
|
||||
bool meter_info_is_used;
|
||||
uint64_t meter_reading;
|
||||
struct v2g_meter_id meter_id;
|
||||
} meter_info;
|
||||
|
||||
struct {
|
||||
/* EVSE V2G values */
|
||||
uint64_t session_id; // Is the evse session id, generated by the evse. This id shall not change during a V2G
|
||||
// Communication Session.
|
||||
uint32_t notification_max_delay;
|
||||
uint8_t evse_isolation_status;
|
||||
unsigned int evse_isolation_status_is_used;
|
||||
uint8_t evse_notification;
|
||||
uint8_t evse_status_code[PHASE_LENGTH];
|
||||
uint8_t evse_processing[PHASE_LENGTH];
|
||||
struct v2g_evse_id evse_id;
|
||||
unsigned int date_time_now_is_used;
|
||||
struct iso2_ChargeServiceType charge_service;
|
||||
std::vector<iso2_ServiceType> evse_service_list;
|
||||
std::map<uint16_t, iso2_ServiceParameterListType> service_parameter_list;
|
||||
|
||||
struct iso2_SAScheduleListType evse_sa_schedule_list;
|
||||
bool evse_sa_schedule_list_is_used;
|
||||
|
||||
std::vector<iso2_paymentOptionType> payment_option_list;
|
||||
bool central_contract_validation_allowed;
|
||||
|
||||
bool cert_install_status;
|
||||
std::string cert_install_res_b64_buffer;
|
||||
|
||||
// AC parameter
|
||||
int rcd;
|
||||
int receipt_required;
|
||||
|
||||
// evse power electronic values
|
||||
struct iso2_PhysicalValueType evse_current_regulation_tolerance;
|
||||
unsigned int evse_current_regulation_tolerance_is_used;
|
||||
struct iso2_PhysicalValueType evse_energy_to_be_delivered;
|
||||
unsigned int evse_energy_to_be_delivered_is_used;
|
||||
struct iso2_PhysicalValueType evse_maximum_current_limit; // DC charging
|
||||
unsigned int evse_maximum_current_limit_is_used;
|
||||
int evse_current_limit_achieved;
|
||||
struct iso2_PhysicalValueType evse_maximum_power_limit;
|
||||
unsigned int evse_maximum_power_limit_is_used;
|
||||
int evse_power_limit_achieved;
|
||||
struct iso2_PhysicalValueType evse_maximum_voltage_limit;
|
||||
unsigned int evse_maximum_voltage_limit_is_used;
|
||||
int evse_voltage_limit_achieved;
|
||||
struct iso2_PhysicalValueType evse_minimum_current_limit;
|
||||
struct iso2_PhysicalValueType evse_minimum_voltage_limit;
|
||||
struct iso2_PhysicalValueType evse_peak_current_ripple;
|
||||
struct iso2_PhysicalValueType evse_present_voltage;
|
||||
struct iso2_PhysicalValueType evse_present_current;
|
||||
|
||||
/* AC only power electronic values */
|
||||
struct iso2_PhysicalValueType evse_nominal_voltage;
|
||||
|
||||
// Specific SAE J2847 bidi values
|
||||
struct SAE_Bidi_Data sae_bidi_data;
|
||||
|
||||
// No energy pause IEC61851-23:2023
|
||||
NoEnergyPauseStatus no_energy_pause{NoEnergyPauseStatus::None};
|
||||
|
||||
// Min and max limits from the dc powersupply
|
||||
PowerCapabilities power_capabilities{};
|
||||
|
||||
} evse_v2g_data;
|
||||
|
||||
struct {
|
||||
/* V2G session values */
|
||||
iso2_paymentOptionType iso_selected_payment_option;
|
||||
long long int auth_start_timeout;
|
||||
int auth_timeout_eim;
|
||||
int auth_timeout_pnc; // for PnC
|
||||
uint8_t gen_challenge[GEN_CHALLENGE_SIZE]; // for PnC
|
||||
bool verify_contract_cert_chain; // for PnC
|
||||
types::authorization::CertificateStatus certificate_status; // for PnC
|
||||
bool authorization_rejected; // for PnC
|
||||
std::optional<types::authorization::ProvidedIdToken> provided_id_token; // for PnC
|
||||
|
||||
bool renegotiation_required; /* Is set to true if renegotiation is required. Only relevant for ISO */
|
||||
bool is_charging; /* set to true if ChargeProgress is set to Start */
|
||||
uint8_t sa_schedule_tuple_id; /* selected SA schedule tuple ID*/
|
||||
} session;
|
||||
|
||||
struct {
|
||||
/* EV V2G values */
|
||||
int bulk_charging_complete;
|
||||
int charging_complete;
|
||||
uint64_t received_session_id; // Is the received ev session id transmitted over the v2g header. This id shall
|
||||
// not change during a V2G Communication Session.
|
||||
|
||||
union {
|
||||
struct din_DC_EVStatusType din_dc_ev_status;
|
||||
struct iso2_DC_EVStatusType iso2_dc_ev_status;
|
||||
};
|
||||
float ev_maximum_current_limit;
|
||||
float ev_maximum_power_limit;
|
||||
float ev_maximum_voltage_limit;
|
||||
float v2g_target_current;
|
||||
float v2g_target_voltage;
|
||||
float remaining_time_to_bulk_soc;
|
||||
float remaining_time_to_full_soc;
|
||||
} ev_v2g_data;
|
||||
|
||||
bool hlc_pause_active;
|
||||
|
||||
std::vector<std::vector<uint16_t>> supported_vas_services_per_provider;
|
||||
|
||||
bool connection_initiated;
|
||||
|
||||
bool sdp_dlink_ready{false};
|
||||
std::atomic<long long int> sdp_dlink_ready_time{0};
|
||||
};
|
||||
|
||||
enum class dLinkAction {
|
||||
D_LINK_ACTION_ERROR,
|
||||
D_LINK_ACTION_TERMINATE,
|
||||
D_LINK_ACTION_PAUSE
|
||||
};
|
||||
|
||||
/**
|
||||
* High-level abstraction of an incoming TCP/TLS connection on a certain charging port.
|
||||
*/
|
||||
struct v2g_connection {
|
||||
pthread_t thread_id;
|
||||
struct v2g_context* ctx;
|
||||
|
||||
bool is_tls_connection;
|
||||
bool tls_handshake_failed; /* true when accept() never returned success */
|
||||
V2gMsgTypeId last_v2g_msg_at_disconnect; /* last V2G message before connection teardown */
|
||||
|
||||
// used for non-TLS connections
|
||||
struct {
|
||||
int socket_fd;
|
||||
} conn;
|
||||
|
||||
tls::Connection* tls_connection;
|
||||
openssl::pkey_ptr* pubkey;
|
||||
|
||||
ssize_t (*read)(struct v2g_connection* conn, unsigned char* buf, std::size_t count);
|
||||
ssize_t (*write)(struct v2g_connection* conn, unsigned char* buf, std::size_t count);
|
||||
|
||||
/* V2GTP EXI encoding/decoding stuff */
|
||||
uint8_t* buffer;
|
||||
uint32_t payload_len;
|
||||
exi_bitstream_t stream;
|
||||
|
||||
struct appHand_exiDocument handshake_req;
|
||||
struct appHand_exiDocument handshake_resp;
|
||||
|
||||
union {
|
||||
struct din_exiDocument* dinEXIDocument;
|
||||
struct iso2_exiDocument* iso2EXIDocument;
|
||||
} exi_in;
|
||||
|
||||
union {
|
||||
struct din_exiDocument* dinEXIDocument;
|
||||
struct iso2_exiDocument* iso2EXIDocument;
|
||||
} exi_out;
|
||||
|
||||
dLinkAction d_link_action; /* signaled data-link action after connection is closed */
|
||||
};
|
||||
|
||||
#endif /* V2G_H */
|
||||
Reference in New Issue
Block a user