Skip to content

Commit

Permalink
Implemented a working mechanism for pausing and resuming a charging s…
Browse files Browse the repository at this point in the history
…ession
  • Loading branch information
Marc Mültin committed Oct 1, 2019
1 parent 7d7cbf9 commit e6f7b4f
Show file tree
Hide file tree
Showing 29 changed files with 382 additions and 220 deletions.
8 changes: 4 additions & 4 deletions RISE-V2G-EVCC/EVCCConfig.properties
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ contract.certificate.update.timespan = 14
# SessionID
#----------
#
# If this value is unequal to zero, then it represents a previously
# paused V2G communication session
session.id = 0
# Hexadecimal string representing a byte array. If this value is unequal to "00", then it represents a
# previously paused V2G communication session
session.id = 00


# Selected payment option
Expand Down Expand Up @@ -141,4 +141,4 @@ exi.codec = exificient
# Used for the PreCharge target voltage. The present voltage indicated by the charging station in PreChargeRes can deviate from the present voltage
# set in PreChargeReq by an EV-specific deviation factor. This value is given in percent.
# Example: voltage.accuracy = 10 means: present voltage may deviate from target voltage by 10 percent in order to successfully stop PreCharge
voltage.accuracy = 5
voltage.accuracy = 5
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@
import org.apache.logging.log4j.Logger;
import com.v2gclarity.risev2g.evcc.session.V2GCommunicationSessionEVCC;
import com.v2gclarity.risev2g.shared.enumerations.CPStates;
import com.v2gclarity.risev2g.shared.utils.MiscUtils;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ACEVChargeParameterType;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ChargingProfileType;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ChargingSessionType;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.DCEVChargeParameterType;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.DCEVErrorCodeType;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.DCEVPowerDeliveryParameterType;
Expand Down Expand Up @@ -63,21 +65,31 @@ public DummyEVController() {
}

@Override
public PaymentOptionType getPaymentOption(PaymentOptionListType paymentOptionsOffered) {
// Contract payment option may only be chosen if offered by SECC AND if communication is secured by TLS
if (paymentOptionsOffered.getPaymentOption().contains(PaymentOptionType.CONTRACT)) {
if (!getCommSessionContext().isTlsConnection()) {
getLogger().warn("SECC offered CONTRACT based payment although no TLS connectionis used. Choosing EIM instead");
return PaymentOptionType.EXTERNAL_PAYMENT;
} else return PaymentOptionType.CONTRACT;
} else return PaymentOptionType.EXTERNAL_PAYMENT;
public PaymentOptionType getPaymentOption() {
/*
* The payment options offered by the SECC should probably be displayed on a HMI in the EV.
* A request to the EVController should then be initiated here in order to let the user
* choose which offered payment option to use.
*
* TODO check [V2G2-828] (selecting payment option related to state B, C)
*/

// Set default to Plug & Charge
return PaymentOptionType.CONTRACT;
}


@Override
public EnergyTransferModeType getRequestedEnergyTransferMode() {
return EnergyTransferModeType.AC_SINGLE_PHASE_CORE;
// Set default to AC_THREE_PHASE_CORE. Should normally depend on type of cable plugged into the vehicle inlet
EnergyTransferModeType requestedEnergyTransferMode = (EnergyTransferModeType) MiscUtils.getPropertyValue("energy.transfermode.requested");

if (requestedEnergyTransferMode == null)
return EnergyTransferModeType.AC_THREE_PHASE_CORE;
else
return requestedEnergyTransferMode;
}


@Override
public JAXBElement<ACEVChargeParameterType> getACEVChargeParamter() {
Expand Down Expand Up @@ -320,6 +332,13 @@ public boolean isChargingLoopActive() {

return true;
} else

/*
* OPTIONAL:
* If you want to trigger a pause of the charging session, then uncomment this line
*/
//getCommSessionContext().setChargingSession(ChargingSessionType.PAUSE);

return false;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public interface IEVController {
* RFID card or via Plug-and-Charge (PnC)
* @return The payment option Contract or ExternalPayment
*/
public PaymentOptionType getPaymentOption(PaymentOptionListType paymentOptionsOffered);
public PaymentOptionType getPaymentOption();


/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
public class StartEVCC {

public static void main(String[] args) {
MiscUtils.setV2gEntityConfig(GlobalValues.EVCC_CONFIG_PROPERTIES_PATH.toString());
MiscUtils.loadProperties(GlobalValues.EVCC_CONFIG_PROPERTIES_PATH.toString());
new V2GCommunicationSessionHandlerEVCC();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,14 @@
import com.v2gclarity.risev2g.shared.messageHandling.TerminateSession;
import com.v2gclarity.risev2g.shared.misc.V2GCommunicationSession;
import com.v2gclarity.risev2g.shared.misc.V2GTPMessage;
import com.v2gclarity.risev2g.shared.utils.ByteUtils;
import com.v2gclarity.risev2g.shared.utils.MiscUtils;
import com.v2gclarity.risev2g.shared.utils.SecurityUtils.ContractCertificateStatus;
import com.v2gclarity.risev2g.shared.v2gMessages.appProtocol.AppProtocolType;
import com.v2gclarity.risev2g.shared.v2gMessages.appProtocol.SupportedAppProtocolRes;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ChargeParameterDiscoveryReqType;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ChargingProfileType;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ChargingSessionType;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.EnergyTransferModeType;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.PaymentOptionType;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.SAScheduleListType;
Expand All @@ -87,9 +90,8 @@ public class V2GCommunicationSessionEVCC extends V2GCommunicationSession impleme
* (saves some processing time)
*/
private ChargeParameterDiscoveryReqType chargeParameterDiscoveryReq;
private boolean stopChargingRequested;
private ChargingSessionType chargingSession;
private boolean renegotiationRequested;
private boolean pausingV2GCommSession;
private ChargingProfileType chargingProfile;
private ServiceListType offeredServices;
private SelectedServiceListType selectedServices;
Expand Down Expand Up @@ -148,6 +150,9 @@ public V2GCommunicationSessionEVCC(StatefulTransportLayerClient transportLayerCl

// Set default value for contract certificate status to UNKNOWN
setContractCertStatus(ContractCertificateStatus.UNKNOWN);

// ChargingSessionType only takes enum values "Pause" and "Terminate". Therefore, set it to null at beginning of charging session
setChargingSession(null);

getLogger().debug("\n*******************************************" +
"\n* New V2G communication session initialized" +
Expand Down Expand Up @@ -231,12 +236,21 @@ public void send(SendMessage sendingParams) {


private void saveSessionProperties() {
// TODO save respective parameters to properties file
// According to [V2G2-740]
MiscUtils.getProperties().setProperty("session.id", "" + ByteUtils.toHexString(getSessionID()));
MiscUtils.getProperties().setProperty("authentication.mode", getSelectedPaymentOption().value());
MiscUtils.getProperties().setProperty("energy.transfermode.requested", getRequestedEnergyTransferMode().value());

MiscUtils.storeProperties(GlobalValues.EVCC_CONFIG_PROPERTIES_PATH.toString());
}


private void deleteSessionProperties() {
// TODO delete the respective parameters from properties file
// Reset the session ID and the authentication mode
MiscUtils.getProperties().setProperty("session.id", "00");
MiscUtils.getProperties().setProperty("authentication.mode", "");

MiscUtils.storeProperties(GlobalValues.EVCC_CONFIG_PROPERTIES_PATH.toString());
}


Expand Down Expand Up @@ -283,13 +297,6 @@ public void setReactionToIncomingMessage(ReactionToIncomingMessage reactionToInc
this.reactionToIncomingMessage = reactionToIncomingMessage;
}

public boolean isStopChargingRequested() {
return stopChargingRequested;
}

public void setStopChargingRequested(boolean stopChargingRequested) {
this.stopChargingRequested = stopChargingRequested;
}

public boolean isRenegotiationRequested() {
return renegotiationRequested;
Expand All @@ -299,13 +306,6 @@ public void setRenegotiationRequested(boolean renegotiationRequested) {
this.renegotiationRequested = renegotiationRequested;
}

public boolean isPausingV2GCommSession() {
return pausingV2GCommSession;
}

public void setPausingV2GCommSession(boolean pausingV2GCommSession) {
this.pausingV2GCommSession = pausingV2GCommSession;
}

public long getEvseScheduleReceived() {
return evseScheduleReceived;
Expand Down Expand Up @@ -508,4 +508,15 @@ public byte[] getSentGenChallenge() {
public void setSentGenChallenge(byte[] sentGenChallenge) {
this.sentGenChallenge = sentGenChallenge;
}


public ChargingSessionType getChargingSession() {
return chargingSession;
}


public void setChargingSession(ChargingSessionType chargingSession) {
this.chargingSession = chargingSession;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -454,28 +454,19 @@ protected SessionStopReqType getSessionStopReq(ChargingSessionType chargingSessi


protected EnergyTransferModeType getRequestedEnergyTransferMode() {
// Check if an EnergyTransferModeType has been requested in a previously paused session
EnergyTransferModeType requestedEnergyTransferMode =
(EnergyTransferModeType) MiscUtils.getPropertyValue("energy.transfermode.requested");
EnergyTransferModeType requestedEnergyTransferMode = null;

if (requestedEnergyTransferMode == null) {
// Check if an EnergyTransferModeType has been requested in a previously paused session
if (getCommSessionContext().isOldSessionJoined())
requestedEnergyTransferMode = (EnergyTransferModeType) MiscUtils.getPropertyValue("energy.transfermode.requested");

if (requestedEnergyTransferMode == null)
requestedEnergyTransferMode = getCommSessionContext().getEvController().getRequestedEnergyTransferMode();
getCommSessionContext().setRequestedEnergyTransferMode(requestedEnergyTransferMode);
}

// We need to save the requested energy transfer mode in the session variable to be able to store in the properties file during pausing
getCommSessionContext().setRequestedEnergyTransferMode(requestedEnergyTransferMode);

return requestedEnergyTransferMode;
}


protected PaymentOptionType getSelectedPaymentOption() {
// Check if a PaymentOptionType has been requested in a previously paused session
PaymentOptionType selectedPaymentOption = (PaymentOptionType) MiscUtils.getPropertyValue("authentication.mode");

if (selectedPaymentOption == null) {
selectedPaymentOption = getCommSessionContext().getEvController().getPaymentOption(getCommSessionContext().getPaymentOptions());
getCommSessionContext().setSelectedPaymentOption(selectedPaymentOption);
}

return selectedPaymentOption;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ACEVSEChargeParameterType;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ChargeParameterDiscoveryResType;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ChargeProgressType;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ChargingSessionType;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.DCEVSEChargeParameterType;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.EVSENotificationType;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.EVSEProcessingType;
Expand Down Expand Up @@ -105,7 +106,7 @@ public ReactionToIncomingMessage processIncomingMessage(Object message) {

if (evseNotification.equals(EVSENotificationType.STOP_CHARGING)) {
getLogger().debug("The EVSE requested to stop the charging process");
getCommSessionContext().setStopChargingRequested(true);
getCommSessionContext().setChargingSession(ChargingSessionType.TERMINATE);

return getSendMessage(getPowerDeliveryReq(ChargeProgressType.STOP), V2GMessages.POWER_DELIVERY_RES);
} else {
Expand Down Expand Up @@ -134,7 +135,23 @@ public ReactionToIncomingMessage processIncomingMessage(Object message) {
// Save the list of SASchedules (saves the time of reception as well)
getCommSessionContext().setSaSchedules(saSchedules);

if (getCommSessionContext().getEvController().getCPState().equals(CPStates.STATE_B)) {
/*
* The following states are possible (and will not raise the termination of a charging session):
* - State B:
* - In AC charging, when exchanging the first ChargeParameterDiscoveryReq/Res message pair, before the charging loop
* was initiated
* - State C:
* - In DC charging, when exchanging the first ChargeParameterDiscoveryReq/Res message pair, before the charging loop
* was initiated
* - In AC charging, after the charging loop was initiated and a renegotiation was triggered
*/
if (getCommSessionContext().getEvController().getCPState().equals(CPStates.STATE_B) ||
(getCommSessionContext().getEvController().getCPState().equals(CPStates.STATE_C) &&
getCommSessionContext().isRenegotiationRequested())) {

// We need to reset the renegotiation trigger (in case of State C and a renegotiation was triggered)
getCommSessionContext().setRenegotiationRequested(false);

if (getCommSessionContext().getRequestedEnergyTransferMode().toString().startsWith("AC")) {
return getSendMessage(getPowerDeliveryReq(ChargeProgressType.START), V2GMessages.POWER_DELIVERY_RES);
} else if (getCommSessionContext().getRequestedEnergyTransferMode().toString().startsWith("DC")) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import com.v2gclarity.risev2g.shared.messageHandling.TerminateSession;
import com.v2gclarity.risev2g.shared.utils.SecurityUtils;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ChargeProgressType;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ChargingSessionType;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ChargingStatusReqType;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ChargingStatusResType;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.MeteringReceiptReqType;
Expand Down Expand Up @@ -94,7 +95,8 @@ public ReactionToIncomingMessage processIncomingMessage(Object message) {

switch (chargingStatusRes.getACEVSEStatus().getEVSENotification()) {
case STOP_CHARGING:
getCommSessionContext().setStopChargingRequested(true);
getCommSessionContext().setChargingSession(ChargingSessionType.TERMINATE);

return getSendMessage(getPowerDeliveryReq(ChargeProgressType.STOP),
V2GMessages.POWER_DELIVERY_RES,
" (ChargeProgress = STOP_CHARGING)");
Expand All @@ -117,7 +119,13 @@ public ReactionToIncomingMessage processIncomingMessage(Object message) {
return getSendMessage(chargingStatusReq, V2GMessages.CHARGING_STATUS_RES);
}
} else {
getCommSessionContext().setStopChargingRequested(true);
/* Check if the EV controller triggered a pause of a charging session.
* If not, indicate a termination of the charging session. This will be
* evaluated in the state WaitForPowerDeliveryRes
*/
if (getCommSessionContext().getChargingSession() == null)
getCommSessionContext().setChargingSession(ChargingSessionType.TERMINATE);

return getSendMessage(getPowerDeliveryReq(ChargeProgressType.STOP),
V2GMessages.POWER_DELIVERY_RES,
" (ChargeProgress = STOP_CHARGING)");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import com.v2gclarity.risev2g.shared.messageHandling.TerminateSession;
import com.v2gclarity.risev2g.shared.utils.SecurityUtils;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ChargeProgressType;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ChargingSessionType;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ChargingStatusReqType;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.CurrentDemandResType;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.DCEVSEStatusType;
Expand Down Expand Up @@ -88,7 +89,8 @@ public ReactionToIncomingMessage processIncomingMessage(Object message) {

switch ((EVSENotificationType) dcEVSEStatus.getEVSENotification()) {
case STOP_CHARGING:
getCommSessionContext().setStopChargingRequested(true);
getCommSessionContext().setChargingSession(ChargingSessionType.TERMINATE);

return getSendMessage(getPowerDeliveryReq(ChargeProgressType.STOP),
V2GMessages.POWER_DELIVERY_RES,
" (ChargeProgress = STOP_CHARGING)");
Expand All @@ -110,7 +112,13 @@ public ReactionToIncomingMessage processIncomingMessage(Object message) {
return getSendMessage(getCurrentDemandReq(), V2GMessages.CURRENT_DEMAND_RES);
}
} else {
getCommSessionContext().setStopChargingRequested(true);
/* Check if the EV controller triggered a pause of a charging session.
* If not, indicate a termination of the charging session. This will be
* evaluated in the state WaitForPowerDeliveryRes
*/
if (getCommSessionContext().getChargingSession() == null)
getCommSessionContext().setChargingSession(ChargingSessionType.TERMINATE);

return getSendMessage(getPowerDeliveryReq(ChargeProgressType.STOP),
V2GMessages.POWER_DELIVERY_RES,
" (ChargeProgress = STOP_CHARGING)");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import com.v2gclarity.risev2g.shared.messageHandling.TerminateSession;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ACEVSEStatusType;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ChargeProgressType;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ChargingSessionType;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ChargingStatusReqType;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.DCEVSEStatusType;
import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.EVSENotificationType;
Expand Down Expand Up @@ -65,7 +66,8 @@ public ReactionToIncomingMessage processIncomingMessage(Object message) {

switch (evseNotification) {
case STOP_CHARGING:
getCommSessionContext().setStopChargingRequested(true);
getCommSessionContext().setChargingSession(ChargingSessionType.TERMINATE);

return getSendMessage(getPowerDeliveryReq(ChargeProgressType.STOP),
V2GMessages.POWER_DELIVERY_RES,
" (ChargeProgress = STOP_CHARGING)");
Expand Down Expand Up @@ -97,7 +99,6 @@ public ReactionToIncomingMessage processIncomingMessage(Object message) {
return getSendMessage(getCurrentDemandReq(), V2GMessages.CURRENT_DEMAND_RES);
}
} else {
getCommSessionContext().setStopChargingRequested(true);
return getSendMessage(getPowerDeliveryReq(ChargeProgressType.STOP),
V2GMessages.POWER_DELIVERY_RES,
" (ChargeProgress = STOP_CHARGING)");
Expand Down
Loading

0 comments on commit e6f7b4f

Please sign in to comment.