1
0
Эх сурвалжийг харах

Implemented a working mechanism for pausing and resuming a charging session

Marc Mültin 6 жил өмнө
parent
commit
e6f7b4fd4e
29 өөрчлөгдсөн 382 нэмэгдсэн , 220 устгасан
  1. 4 4
      RISE-V2G-EVCC/EVCCConfig.properties
  2. 28 9
      RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/evController/DummyEVController.java
  3. 1 1
      RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/evController/IEVController.java
  4. 1 1
      RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/main/StartEVCC.java
  5. 29 18
      RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/session/V2GCommunicationSessionEVCC.java
  6. 9 18
      RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/states/ClientState.java
  7. 19 2
      RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/states/WaitForChargeParameterDiscoveryRes.java
  8. 10 2
      RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/states/WaitForChargingStatusRes.java
  9. 10 2
      RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/states/WaitForCurrentDemandRes.java
  10. 3 2
      RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/states/WaitForMeteringReceiptRes.java
  11. 8 10
      RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/states/WaitForPowerDeliveryRes.java
  12. 39 12
      RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/states/WaitForServiceDiscoveryRes.java
  13. 8 8
      RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/states/WaitForSessionSetupRes.java
  14. 7 1
      RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/states/WaitForSessionStopRes.java
  15. 11 6
      RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/states/WaitForSupportedAppProtocolRes.java
  16. 3 5
      RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/states/WaitForWeldingDetectionRes.java
  17. 15 0
      RISE-V2G-SECC/src/main/java/com/v2gclarity/risev2g/secc/backend/DummyBackendInterface.java
  18. 23 0
      RISE-V2G-SECC/src/main/java/com/v2gclarity/risev2g/secc/backend/IBackendInterface.java
  19. 1 1
      RISE-V2G-SECC/src/main/java/com/v2gclarity/risev2g/secc/main/StartSECC.java
  20. 16 4
      RISE-V2G-SECC/src/main/java/com/v2gclarity/risev2g/secc/session/V2GCommunicationSessionHandlerSECC.java
  21. 48 27
      RISE-V2G-SECC/src/main/java/com/v2gclarity/risev2g/secc/session/V2GCommunicationSessionSECC.java
  22. 3 2
      RISE-V2G-SECC/src/main/java/com/v2gclarity/risev2g/secc/states/ServerState.java
  23. 17 6
      RISE-V2G-SECC/src/main/java/com/v2gclarity/risev2g/secc/states/WaitForChargeParameterDiscoveryReq.java
  24. 3 6
      RISE-V2G-SECC/src/main/java/com/v2gclarity/risev2g/secc/states/WaitForPowerDeliveryReq.java
  25. 12 3
      RISE-V2G-SECC/src/main/java/com/v2gclarity/risev2g/secc/states/WaitForSessionStopReq.java
  26. 3 33
      RISE-V2G-Shared/src/main/java/com/v2gclarity/risev2g/shared/misc/V2GCommunicationSession.java
  27. 1 1
      RISE-V2G-Shared/src/main/java/com/v2gclarity/risev2g/shared/misc/V2GImplementationFactory.java
  28. 4 2
      RISE-V2G-Shared/src/main/java/com/v2gclarity/risev2g/shared/utils/ByteUtils.java
  29. 46 34
      RISE-V2G-Shared/src/main/java/com/v2gclarity/risev2g/shared/utils/MiscUtils.java

+ 4 - 4
RISE-V2G-EVCC/EVCCConfig.properties

@@ -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
@@ -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

+ 28 - 9
RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/evController/DummyEVController.java

@@ -32,8 +32,10 @@ import org.apache.logging.log4j.LogManager;
 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;
@@ -63,21 +65,31 @@ public class DummyEVController implements IACEVController, IDCEVController {
 	}
 	
 	@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() {
@@ -320,6 +332,13 @@ public class DummyEVController implements IACEVController, IDCEVController {
 			
 			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;
 	}
 

+ 1 - 1
RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/evController/IEVController.java

@@ -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();
 	
 	
 	/**

+ 1 - 1
RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/main/StartEVCC.java

@@ -30,7 +30,7 @@ import com.v2gclarity.risev2g.shared.utils.MiscUtils;
 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();
 	}
 

+ 29 - 18
RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/session/V2GCommunicationSessionEVCC.java

@@ -61,11 +61,14 @@ import com.v2gclarity.risev2g.shared.messageHandling.SendMessage;
 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;
@@ -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; 
@@ -148,6 +150,9 @@ public class V2GCommunicationSessionEVCC extends V2GCommunicationSession impleme
 		
 		// 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" +
@@ -231,12 +236,21 @@ public class V2GCommunicationSessionEVCC extends V2GCommunicationSession impleme
 	
 	
 	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());
 	}
 
 	
@@ -283,13 +297,6 @@ public class V2GCommunicationSessionEVCC extends V2GCommunicationSession impleme
 		this.reactionToIncomingMessage = reactionToIncomingMessage;
 	}
 
-	public boolean isStopChargingRequested() {
-		return stopChargingRequested;
-	}
-
-	public void setStopChargingRequested(boolean stopChargingRequested) {
-		this.stopChargingRequested = stopChargingRequested;
-	}
 
 	public boolean isRenegotiationRequested() {
 		return renegotiationRequested;
@@ -299,13 +306,6 @@ public class V2GCommunicationSessionEVCC extends V2GCommunicationSession impleme
 		this.renegotiationRequested = renegotiationRequested;
 	}
 
-	public boolean isPausingV2GCommSession() {
-		return pausingV2GCommSession;
-	}
-
-	public void setPausingV2GCommSession(boolean pausingV2GCommSession) {
-		this.pausingV2GCommSession = pausingV2GCommSession;
-	}
 
 	public long getEvseScheduleReceived() {
 		return evseScheduleReceived;
@@ -508,4 +508,15 @@ public class V2GCommunicationSessionEVCC extends V2GCommunicationSession impleme
 	public void setSentGenChallenge(byte[] sentGenChallenge) {
 		this.sentGenChallenge = sentGenChallenge;
 	}
+	
+
+	public ChargingSessionType getChargingSession() {
+		return chargingSession;
+	}
+
+
+	public void setChargingSession(ChargingSessionType chargingSession) {
+		this.chargingSession = chargingSession;
+	}
+
 }

+ 9 - 18
RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/states/ClientState.java

@@ -454,28 +454,19 @@ public abstract class ClientState extends State {
 		
 		
 	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;
-	}
 }

+ 19 - 2
RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/states/WaitForChargeParameterDiscoveryRes.java

@@ -39,6 +39,7 @@ import com.v2gclarity.risev2g.shared.utils.SecurityUtils;
 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;
@@ -105,7 +106,7 @@ public class WaitForChargeParameterDiscoveryRes extends ClientState {
 				
 				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 {
@@ -134,7 +135,23 @@ public class WaitForChargeParameterDiscoveryRes extends ClientState {
 					// 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")) {

+ 10 - 2
RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/states/WaitForChargingStatusRes.java

@@ -31,6 +31,7 @@ import com.v2gclarity.risev2g.shared.messageHandling.ReactionToIncomingMessage;
 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;
@@ -94,7 +95,8 @@ public class WaitForChargingStatusRes extends ClientState {
 			
 			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)");
@@ -117,7 +119,13 @@ public class WaitForChargingStatusRes extends ClientState {
 							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)");

+ 10 - 2
RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/states/WaitForCurrentDemandRes.java

@@ -30,6 +30,7 @@ import com.v2gclarity.risev2g.shared.messageHandling.ReactionToIncomingMessage;
 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;
@@ -88,7 +89,8 @@ public class WaitForCurrentDemandRes extends ClientState {
 			
 			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)");
@@ -110,7 +112,13 @@ public class WaitForCurrentDemandRes extends ClientState {
 							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)");

+ 3 - 2
RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/states/WaitForMeteringReceiptRes.java

@@ -29,6 +29,7 @@ import com.v2gclarity.risev2g.shared.messageHandling.ReactionToIncomingMessage;
 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;
@@ -65,7 +66,8 @@ public class WaitForMeteringReceiptRes extends ClientState {
 			
 			switch (evseNotification) {
 			case STOP_CHARGING:
-				getCommSessionContext().setStopChargingRequested(true);
+				getCommSessionContext().setChargingSession(ChargingSessionType.TERMINATE);
+				
 				return getSendMessage(getPowerDeliveryReq(ChargeProgressType.STOP), 
 									  V2GMessages.POWER_DELIVERY_RES,
 									  " (ChargeProgress = STOP_CHARGING)");
@@ -97,7 +99,6 @@ public class WaitForMeteringReceiptRes extends ClientState {
 						return getSendMessage(getCurrentDemandReq(), V2GMessages.CURRENT_DEMAND_RES);
 					}
 				} else {
-					getCommSessionContext().setStopChargingRequested(true);
 					return getSendMessage(getPowerDeliveryReq(ChargeProgressType.STOP), 
 										  V2GMessages.POWER_DELIVERY_RES,
 										  " (ChargeProgress = STOP_CHARGING)");

+ 8 - 10
RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/states/WaitForPowerDeliveryRes.java

@@ -66,12 +66,13 @@ public class WaitForPowerDeliveryRes extends ClientState {
 					getCommSessionContext().setChangeToState(CPStates.STATE_B);
 				}
 				
-				getCommSessionContext().setRenegotiationRequested(false);
 				return getSendMessage(getChargeParameterDiscoveryReq(), V2GMessages.CHARGE_PARAMETER_DISCOVERY_RES);
-			} else if (getCommSessionContext().isStopChargingRequested()) {
-				return getSendMessage(ChargingSessionType.TERMINATE, true);
-			} else if (getCommSessionContext().isPausingV2GCommSession()) {
-				return getSendMessage(ChargingSessionType.PAUSE, false);
+			} else if (getCommSessionContext().getChargingSession() != null && 
+					   getCommSessionContext().getChargingSession() == ChargingSessionType.TERMINATE) {
+				return getSendMessage(ChargingSessionType.TERMINATE);
+			} else if (getCommSessionContext().getChargingSession() != null && 
+					   getCommSessionContext().getChargingSession() == ChargingSessionType.PAUSE) {
+				return getSendMessage(ChargingSessionType.PAUSE);
 			} else {
 				if (getCommSessionContext().getRequestedEnergyTransferMode().toString().startsWith("AC")) {
 					ChargingStatusReqType chargingStatusReq = new ChargingStatusReqType();
@@ -86,7 +87,7 @@ public class WaitForPowerDeliveryRes extends ClientState {
 	}
 	
 	
-	private ReactionToIncomingMessage getSendMessage(ChargingSessionType chargingSessionType, boolean stopChargingRequested) {
+	private ReactionToIncomingMessage getSendMessage(ChargingSessionType chargingSessionType) {
 		if (getCommSessionContext().getRequestedEnergyTransferMode().toString().startsWith("DC")) {
 			// CP state B signaling BEFORE sending WeldingDetectionReq message in DC
 			if (getCommSessionContext().getEvController().setCPState(CPStates.STATE_B)) {
@@ -100,10 +101,7 @@ public class WaitForPowerDeliveryRes extends ClientState {
 						getCommSessionContext().getEvController().getCPState() +
 						")");
 			}
-		} else {
-			if (stopChargingRequested) getCommSessionContext().setStopChargingRequested(false);
-			else getCommSessionContext().setPausingV2GCommSession(false);
-			
+		} else {	
 			return getSendMessage(getSessionStopReq(chargingSessionType), 
 								  V2GMessages.SESSION_STOP_RES, "(ChargingSession = " + 
 								  chargingSessionType.toString() + ")");

+ 39 - 12
RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/states/WaitForServiceDiscoveryRes.java

@@ -28,9 +28,11 @@ import com.v2gclarity.risev2g.evcc.transportLayer.TLSClient;
 import com.v2gclarity.risev2g.shared.enumerations.V2GMessages;
 import com.v2gclarity.risev2g.shared.messageHandling.ReactionToIncomingMessage;
 import com.v2gclarity.risev2g.shared.messageHandling.TerminateSession;
+import com.v2gclarity.risev2g.shared.utils.MiscUtils;
 import com.v2gclarity.risev2g.shared.utils.SecurityUtils;
 import com.v2gclarity.risev2g.shared.utils.SecurityUtils.ContractCertificateStatus;
 import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.EnergyTransferModeType;
+import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.PaymentOptionListType;
 import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.PaymentOptionType;
 import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.SelectedServiceType;
 import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ServiceCategoryType;
@@ -60,7 +62,7 @@ public class WaitForServiceDiscoveryRes extends ClientState {
 			 */
 			getCommSessionContext().getServiceDetailsToBeRequested().clear(); // just to be sure
 			
-			// Save offered charge service and optional value added services
+			// Save the list containing information on all other services than charging services offered by the charging station
 			getCommSessionContext().setOfferedServices(serviceDiscoveryRes.getServiceList());
 			
 			if (serviceDiscoveryRes.getChargeService() != null) {
@@ -69,7 +71,6 @@ public class WaitForServiceDiscoveryRes extends ClientState {
 				
 				if (serviceDiscoveryRes.getChargeService().getSupportedEnergyTransferMode()
 						.getEnergyTransferMode().contains(requestedEnergyTransferMode)) {
-					getCommSessionContext().setRequestedEnergyTransferMode(requestedEnergyTransferMode);
 					getCommSessionContext().getOfferedServices().getService().add(serviceDiscoveryRes.getChargeService());
 					addSelectedService(1, null); // Assumption: a charge service is always used
 				} else {
@@ -77,16 +78,7 @@ public class WaitForServiceDiscoveryRes extends ClientState {
 				}
 			} else return new TerminateSession("No charge service available");
 			
-			/*
-			 * 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)
-			 */
-			PaymentOptionType userPaymentOption = 
-					getCommSessionContext().getEvController().getPaymentOption(serviceDiscoveryRes.getPaymentOptionList());
-			getCommSessionContext().setSelectedPaymentOption(userPaymentOption);
+			getCommSessionContext().setSelectedPaymentOption(getSelectedPaymentOption(serviceDiscoveryRes.getPaymentOptionList()));
 			
 			// Check for the usage of value added services (VAS)
 			if (useVAS(serviceDiscoveryRes)) {
@@ -100,6 +92,41 @@ public class WaitForServiceDiscoveryRes extends ClientState {
 	}
 	
 	
+	protected PaymentOptionType getSelectedPaymentOption(PaymentOptionListType authenticationOptions) {
+		/*
+		 * Note that although the type is called "PaymentOptionListType", it's not a list of payment options, but authorization options, 
+		 * namely either Plug & Charge ("Contract") or external identification means (EIM) like an RFID card ("ExternalPayment"). This is 
+		 * why the parameter for this function is called "authenticationOptions" for clarity.
+		 */
+		
+		PaymentOptionType selectedPaymentOption = null;
+		
+		// Check if a PaymentOptionType has been requested in a previously paused session 
+		if (getCommSessionContext().isOldSessionJoined()) 
+			selectedPaymentOption = (PaymentOptionType) MiscUtils.getPropertyValue("authentication.mode");
+		
+		if (selectedPaymentOption == null) 
+			selectedPaymentOption = getCommSessionContext().getEvController().getPaymentOption();
+		
+		// Contract payment option may only be chosen if offered by SECC AND if communication is secured by TLS
+		if (selectedPaymentOption.equals(PaymentOptionType.CONTRACT) &&
+			authenticationOptions.getPaymentOption().contains(PaymentOptionType.CONTRACT)) {
+			
+			if (!getCommSessionContext().isTlsConnection()) {
+				getLogger().warn("SECC offered 'Contract' based payment although no TLS connectionis used. Choosing 'ExternalPayment' instead");
+				getCommSessionContext().setSelectedPaymentOption(PaymentOptionType.EXTERNAL_PAYMENT);
+				return PaymentOptionType.EXTERNAL_PAYMENT;
+			} else {
+				getCommSessionContext().setSelectedPaymentOption(PaymentOptionType.CONTRACT);
+				return PaymentOptionType.CONTRACT; 
+			}
+		} else {
+			getCommSessionContext().setSelectedPaymentOption(PaymentOptionType.EXTERNAL_PAYMENT);
+			return PaymentOptionType.EXTERNAL_PAYMENT;
+		}
+	}
+	
+	
 	/**
 	 * According to [V2G2-422] a ServiceDetailsReq is needed in case VAS (value added services)
 	 * such as certificate installation/update are to be used and offered by the SECC. 

+ 8 - 8
RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/states/WaitForSessionSetupRes.java

@@ -47,14 +47,10 @@ public class WaitForSessionSetupRes extends ClientState {
 					(SessionSetupResType) ((V2GMessage) message).getBody().getBodyElement().getValue();
 					
 			if (sessionSetupRes.getResponseCode().equals(ResponseCodeType.OK_NEW_SESSION_ESTABLISHED)) {
-				getCommSessionContext().setSessionID(receivedSessionID);
-				getLogger().debug("Negotiated session ID is " + ByteUtils.toLongFromByteArray(receivedSessionID));
+				getLogger().debug("Negotiated session ID is " + ByteUtils.toHexString(receivedSessionID));
 				getCommSessionContext().setOldSessionJoined(false);
-				getCommSessionContext().setEvseID(sessionSetupRes.getEVSEID());
-				// EVSETimeStamp is optional
-				if (sessionSetupRes.getEVSETimeStamp() != null)	getCommSessionContext().setEvseTimeStamp(sessionSetupRes.getEVSETimeStamp());
 			} else if (sessionSetupRes.getResponseCode().equals(ResponseCodeType.OK_OLD_SESSION_JOINED)) {
-				getLogger().debug("Previous charging session joined (session ID = " + ByteUtils.toLongFromByteArray(receivedSessionID) + ")");
+				getLogger().debug("Previous charging session joined (session ID = " + ByteUtils.toHexString(receivedSessionID) + ")");
 				
 				/*
 				 * Mark that the old session was joined in order to resend
@@ -63,8 +59,6 @@ public class WaitForSessionSetupRes extends ClientState {
 				 * according to 8.4.2. Those values should be persisted in the properties file.
 				 */
 				getCommSessionContext().setOldSessionJoined(true);
-				getCommSessionContext().setEvseID(sessionSetupRes.getEVSEID());
-				getCommSessionContext().setEvseTimeStamp(sessionSetupRes.getEVSETimeStamp());
 			} else {
 				getCommSessionContext().setOldSessionJoined(false);
 				getLogger().error("No negative response code received, but positive response code '" +
@@ -73,6 +67,12 @@ public class WaitForSessionSetupRes extends ClientState {
 				return new TerminateSession("Positive response code invalid in state WaitForSessionSetupRes");
 			}
 			
+			getCommSessionContext().setSessionID(receivedSessionID);
+			getCommSessionContext().setEvseID(sessionSetupRes.getEVSEID());
+			// EVSETimeStamp is optional
+			if (sessionSetupRes.getEVSETimeStamp() != null) 
+				getCommSessionContext().setEvseTimeStamp(sessionSetupRes.getEVSETimeStamp());
+			
 			ServiceDiscoveryReqType serviceDiscoveryReq = new ServiceDiscoveryReqType();
 			
 			/*

+ 7 - 1
RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/states/WaitForSessionStopRes.java

@@ -24,8 +24,10 @@
 package com.v2gclarity.risev2g.evcc.states;
 
 import com.v2gclarity.risev2g.evcc.session.V2GCommunicationSessionEVCC;
+import com.v2gclarity.risev2g.shared.messageHandling.PauseSession;
 import com.v2gclarity.risev2g.shared.messageHandling.ReactionToIncomingMessage;
 import com.v2gclarity.risev2g.shared.messageHandling.TerminateSession;
+import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ChargingSessionType;
 import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.SessionStopResType;
 
 public class WaitForSessionStopRes extends ClientState {
@@ -37,7 +39,11 @@ public class WaitForSessionStopRes extends ClientState {
 	@Override
 	public ReactionToIncomingMessage processIncomingMessage(Object message) {
 		if (isIncomingMessageValid(message, SessionStopResType.class)) {
-			return new TerminateSession("V2G communication session will be stopped successfully", true);
+			if (getCommSessionContext().getChargingSession() != null &&
+				getCommSessionContext().getChargingSession().equals(ChargingSessionType.PAUSE)) 
+				return new PauseSession();
+			else
+				return new TerminateSession("V2G communication session will be stopped successfully", true);
 		} else {
 			return new TerminateSession("Incoming message raised an error");
 		}

+ 11 - 6
RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/states/WaitForSupportedAppProtocolRes.java

@@ -30,6 +30,7 @@ import com.v2gclarity.risev2g.shared.enumerations.V2GMessages;
 import com.v2gclarity.risev2g.shared.messageHandling.ReactionToIncomingMessage;
 import com.v2gclarity.risev2g.shared.messageHandling.TerminateSession;
 import com.v2gclarity.risev2g.shared.misc.TimeRestrictions;
+import com.v2gclarity.risev2g.shared.utils.ByteUtils;
 import com.v2gclarity.risev2g.shared.utils.MiscUtils;
 import com.v2gclarity.risev2g.shared.v2gMessages.appProtocol.AppProtocolType;
 import com.v2gclarity.risev2g.shared.v2gMessages.appProtocol.ResponseCodeType;
@@ -77,14 +78,18 @@ public class WaitForSupportedAppProtocolRes extends ClientState {
 				/*
 				 * The session ID is taken from the properties file. If a previous charging session has been
 				 * paused, then the previously valid session ID has been written to the properties file
-				 * in order persist the value when the ISO/IEC 15118 controller is shut down for energy
+				 * in order persist the value when the ISO 15118 controller is shut down for energy
 				 * saving reasons.
-				 * The initial value for a completely new charging session must be 0.
+				 * The initial value for a completely new charging session must be 00.
 				 */
-				long sessionID = (long) MiscUtils.getPropertyValue("session.id");
-				getCommSessionContext().setSessionID(
-						getCommSessionContext().generateSessionIDFromValue(sessionID)
-				);
+				String sessionID = (String) MiscUtils.getPropertyValue("session.id");
+				try {
+					getCommSessionContext().setSessionID(ByteUtils.toByteArrayFromHexString(sessionID));
+				} catch (IllegalArgumentException e) {
+					getLogger().warn("Stored session ID '" + sessionID + "' contains illegal character(s) which are not hexadecimal. " +
+									  "Will reset session ID to '00'");
+					getCommSessionContext().setSessionID(ByteUtils.toByteArrayFromHexString("00"));
+				}
 			} else {
 				return new TerminateSession("No supported appProtocol found (positive response code received, " + 
 											"but no valid schemaID. Received schema ID is: " + 

+ 3 - 5
RISE-V2G-EVCC/src/main/java/com/v2gclarity/risev2g/evcc/states/WaitForWeldingDetectionRes.java

@@ -50,15 +50,13 @@ public class WaitForWeldingDetectionRes extends ClientState {
 			 * How to react on DCEVSEStatus values?
 			 */
 			
-			if (getCommSessionContext().isPausingV2GCommSession()) {
-				getCommSessionContext().setPausingV2GCommSession(false);
+			if (getCommSessionContext().getChargingSession() != null && 
+				getCommSessionContext().getChargingSession() == ChargingSessionType.PAUSE) {
 				
 				return getSendMessage(getSessionStopReq(ChargingSessionType.PAUSE), 
 						  V2GMessages.SESSION_STOP_RES, "(ChargingSession = " + 
 						  ChargingSessionType.PAUSE.toString() + ")");
-			} else {
-				getCommSessionContext().setStopChargingRequested(false);
-				
+			} else {	
 				return getSendMessage(getSessionStopReq(ChargingSessionType.TERMINATE), 
 						  V2GMessages.SESSION_STOP_RES, "(ChargingSession = " + 
 						  ChargingSessionType.TERMINATE.toString() + ")");

+ 15 - 0
RISE-V2G-SECC/src/main/java/com/v2gclarity/risev2g/secc/backend/DummyBackendInterface.java

@@ -73,12 +73,27 @@ public class DummyBackendInterface implements IBackendInterface {
 		
 	}
 	
+	
 	@Override
 	public SAScheduleListType getSAScheduleList(
 			int maxEntriesSAScheduleTuple, 
 			long departureTime,
 			HashMap<String, byte[]> xmlSignatureRefElements) {
+		return getSAScheduleList(maxEntriesSAScheduleTuple, departureTime, xmlSignatureRefElements, (short) -1);
+	}
+	
+	
+	@Override
+	public SAScheduleListType getSAScheduleList(
+			int maxEntriesSAScheduleTuple, 
+			long departureTime,
+			HashMap<String, byte[]> xmlSignatureRefElements,
+			short selectedSAScheduleTupleId) {
 		/*
+		 * This is a static list of SASchedules. This means that we always offer the same list and ignore the 
+		 * processing of the parameter selectedSAScheduleTupleId.
+		 * 
+		 * 
 		 * Some important requirements:
 		 * 
 		 * 1. The sum of the individual time intervals described in the PMaxSchedule and

+ 23 - 0
RISE-V2G-SECC/src/main/java/com/v2gclarity/risev2g/secc/backend/IBackendInterface.java

@@ -40,6 +40,7 @@ public interface IBackendInterface {
 	 */
 	public void setCommSessionContext(V2GCommunicationSessionSECC commSessionContext);
 	
+	
 	/**
 	 * Provides a list of schedules coming from a secondary actor (SAScheduleList) with pMax values
 	 * and optional tariff incentives which shall influence the charging behaviour of the EV.
@@ -47,6 +48,7 @@ public interface IBackendInterface {
 	 * @param maxEntriesSAScheduleTuple The maximum number of PMaxEntries and SalesTariff entries allowed by EVCC
 	 * @param departureTime The departure time provided by the EV
 	 * @param xmlSignatureRefElements Signature reference parameter provided to put sales tariff IDs and sales tariffs in
+	 * 
 	 * @return An SASchedulesType element with a list of secondary actor schedules 
 	 */
 	public SAScheduleListType getSAScheduleList(
@@ -55,6 +57,27 @@ public interface IBackendInterface {
 			HashMap<String, byte[]> xmlSignatureRefElements);
 	
 	
+	/**
+	 * Provides a list of schedules coming from a secondary actor (SAScheduleList) with pMax values
+	 * and optional tariff incentives which shall influence the charging behaviour of the EV. 
+	 * 
+	 * The parameter selectedSAScheduleTupleId tells the backend to again offer a schedule with that ID 
+	 * because the EVCC requested it in a previous charging session that has now been resumed after pausing.
+	 * 
+	 * @param maxEntriesSAScheduleTuple The maximum number of PMaxEntries and SalesTariff entries allowed by EVCC
+	 * @param departureTime The departure time provided by the EV
+	 * @param xmlSignatureRefElements Signature reference parameter provided to put sales tariff IDs and sales tariffs in
+	 * @param selectedSAScheduleTupleId The SAScheduleTupleID which the EVCC chose in a previous charging session (optional)
+	 * 
+	 * @return An SASchedulesType element with a list of secondary actor schedules 
+	 */
+	public SAScheduleListType getSAScheduleList(
+			int maxEntriesSAScheduleTuple, 
+			long departureTime,
+			HashMap<String, byte[]> xmlSignatureRefElements,
+			short selectedSAScheduleTupleId);
+	
+	
 	/**
 	 * Provides a certificate chain coming from a secondary actor with the leaf certificate being 
 	 * the contract certificate and possible intermediate certificates (Sub-CAs) included.

+ 1 - 1
RISE-V2G-SECC/src/main/java/com/v2gclarity/risev2g/secc/main/StartSECC.java

@@ -36,7 +36,7 @@ public class StartSECC {
 	
 	public static void main(String[] args) {
 		final Logger logger = LogManager.getLogger(StartSECC.class.getSimpleName());
-		MiscUtils.setV2gEntityConfig(GlobalValues.SECC_CONFIG_PROPERTIES_PATH.toString());
+		MiscUtils.loadProperties(GlobalValues.SECC_CONFIG_PROPERTIES_PATH.toString());
 		
 		UDPServer udpServer = UDPServer.getInstance();
 		TCPServer tcpServer = TCPServer.getInstance();

+ 16 - 4
RISE-V2G-SECC/src/main/java/com/v2gclarity/risev2g/secc/session/V2GCommunicationSessionHandlerSECC.java

@@ -38,6 +38,7 @@ import com.v2gclarity.risev2g.secc.transportLayer.TLSServer;
 import com.v2gclarity.risev2g.secc.transportLayer.UDPServer;
 import com.v2gclarity.risev2g.shared.enumerations.GlobalValues;
 import com.v2gclarity.risev2g.shared.messageHandling.MessageHandler;
+import com.v2gclarity.risev2g.shared.messageHandling.PauseSession;
 import com.v2gclarity.risev2g.shared.messageHandling.TerminateSession;
 import com.v2gclarity.risev2g.shared.misc.V2GTPMessage;
 import com.v2gclarity.risev2g.shared.utils.ByteUtils;
@@ -97,13 +98,19 @@ public class V2GCommunicationSessionHandlerSECC implements Observer {
 				 * before the V2GCommunicationSessionSECC object is instantiated, otherwise it may lead to 
 				 * race conditions. 
 				 */
+				getLogger().debug("Resuming previous communication session ...");
 				V2GCommunicationSessionSECC continuedSession = getV2gCommunicationSessions().get(ipAddress);
+				
+				// Reset charging session state from previous session (namely ChargingSessionType.PAUSE) to avoid confusion in the algorithm
+				continuedSession.setChargingSession(null);
+				
 				continuedSession.setConnectionHandler((ConnectionHandler) obj);
 				continuedSession.setTlsConnection((obs instanceof TLSServer) ? true : false);
 				((ConnectionHandler) obj).addObserver(getV2gCommunicationSessions().get(ipAddress));
 				
 				manageConnectionHandlers((ConnectionHandler) obj);
 			} else { 
+				getLogger().debug("Initiating a new communication session ...");
 				V2GCommunicationSessionSECC newSession = new V2GCommunicationSessionSECC((ConnectionHandler) obj);
 				newSession.setTlsConnection((obs instanceof TLSServer) ? true : false);
 				newSession.addObserver(this);
@@ -112,11 +119,14 @@ public class V2GCommunicationSessionHandlerSECC implements Observer {
 				manageConnectionHandlers((ConnectionHandler) obj);
 			}
 		} else if (obs instanceof V2GCommunicationSessionSECC && obj instanceof TerminateSession) {
-			// Remove the V2GCommunicationSessionSECC instance from the hashmap
+			// Remove the V2GCommunicationSessionSECC instance from the hash map
 			String ipAddress = ((V2GCommunicationSessionSECC) obs).getConnectionHandler().getAddress();
 			getV2gCommunicationSessions().remove(ipAddress);
 			
-			stopConnectionHandler(((V2GCommunicationSessionSECC) obs).getConnectionHandler());
+			stopConnectionHandler(((V2GCommunicationSessionSECC) obs).getConnectionHandler(), false);
+		} else if (obs instanceof V2GCommunicationSessionSECC && obj instanceof PauseSession) {
+			// Stop the connection handler, but keep the V2GCommunicationSessionSECC instance in the hash map
+			stopConnectionHandler(((V2GCommunicationSessionSECC) obs).getConnectionHandler(), true);
 		} else {
 			getLogger().warn("Notification received, but sending entity or received object not identifiable");
 		}
@@ -184,7 +194,7 @@ public class V2GCommunicationSessionHandlerSECC implements Observer {
 	 * @param connectionHandler The ConnectionHandler whose socket is to be closed and whose thread
 	 * 							   is to be interrupted.
 	 */
-	public void stopConnectionHandler(ConnectionHandler connectionHandler) {
+	public void stopConnectionHandler(ConnectionHandler connectionHandler, boolean pausingSession) {
 		if (getConnectionHandlerMap().containsKey(connectionHandler)) {
 			// Close the socket
 			connectionHandler.stop();
@@ -196,7 +206,9 @@ public class V2GCommunicationSessionHandlerSECC implements Observer {
 			// Remove HashMap entry
 			getConnectionHandlerMap().remove(connectionHandler);
 			
-			getLogger().debug("Thread '" + connectionThread.getName() + "' has been interrupted and removed\n\n" );
+			
+			getLogger().debug("Thread '" + connectionThread.getName() + "' has been interrupted and removed" + 
+							  ((pausingSession) ? ". Charging session is paused." : "") + "\n\n");
 		} else {
 			String address = connectionHandler.getAddress();
 			int port = connectionHandler.getPort(); 

+ 48 - 27
RISE-V2G-SECC/src/main/java/com/v2gclarity/risev2g/secc/session/V2GCommunicationSessionSECC.java

@@ -57,20 +57,24 @@ import com.v2gclarity.risev2g.secc.transportLayer.ConnectionHandler;
 import com.v2gclarity.risev2g.shared.enumerations.GlobalValues;
 import com.v2gclarity.risev2g.shared.enumerations.V2GMessages;
 import com.v2gclarity.risev2g.shared.messageHandling.ChangeProcessingState;
+import com.v2gclarity.risev2g.shared.messageHandling.PauseSession;
 import com.v2gclarity.risev2g.shared.messageHandling.ReactionToIncomingMessage;
 import com.v2gclarity.risev2g.shared.messageHandling.SendMessage;
 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.v2gMessages.appProtocol.SupportedAppProtocolReq;
 import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ACEVSEStatusType;
 import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.CertificateChainType;
+import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ChargingSessionType;
 import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.EVSENotificationType;
 import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.EnergyTransferModeType;
 import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.MessageHeaderType;
 import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.MeterInfoType;
 import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.PMaxScheduleType;
+import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.PaymentOptionListType;
 import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.PaymentOptionType;
 import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ResponseCodeType;
 import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.SAScheduleListType;
@@ -81,8 +85,7 @@ public class V2GCommunicationSessionSECC extends V2GCommunicationSession impleme
 	
 	private short schemaID;
 	private ACEVSEStatusType acEVSEStatus;
-	private boolean stopV2GCommunicationSession;
-	private boolean pauseV2GCommunicationSession;
+	private ChargingSessionType chargingSession;
 	private PMaxScheduleType pMaxSchedule;
 	private short chosenSAScheduleTuple;
 	private IACEVSEController acEvseController;
@@ -142,8 +145,8 @@ public class V2GCommunicationSessionSECC extends V2GCommunicationSession impleme
 		getACEVSEStatus().setNotificationMaxDelay(0);
 		getACEVSEStatus().setRCD(false);
 		
-		setStopV2GCommunicationSession(false);
-		setPauseV2GCommunicationSession(false);
+		// Will be set only if a session is to be stopped or paused
+		setChargingSession(null);
 		
 		setOfferedServices(new ArrayList<ServiceType>());
 		
@@ -189,8 +192,11 @@ public class V2GCommunicationSessionSECC extends V2GCommunicationSession impleme
 		// Check the outcome of the processIncomingMessage() of the respective state
 		if (reactionToIncomingMessage instanceof SendMessage) {
 			send((SendMessage) reactionToIncomingMessage);
-			if (isStopV2GCommunicationSession()) {
+			if (getChargingSession() != null && getChargingSession() == ChargingSessionType.TERMINATE) 
 				terminateSession("EVCC indicated request to stop the session or a FAILED response code was sent", true);
+			
+			if (getChargingSession() != null && getChargingSession() == ChargingSessionType.PAUSE) {
+				pauseSession(new PauseSession());
 			}
 		} else if (reactionToIncomingMessage instanceof ChangeProcessingState) {
 			setCurrentState(((ChangeProcessingState) reactionToIncomingMessage).getNewState());
@@ -217,20 +223,22 @@ public class V2GCommunicationSessionSECC extends V2GCommunicationSession impleme
 	 */
 	public ResponseCodeType checkSessionID(MessageHeaderType header) {
 		if (getCurrentState().equals(getStates().get(V2GMessages.SESSION_SETUP_REQ)) && 
-				ByteUtils.toLongFromByteArray(header.getSessionID()) == 0L) {
+			ByteUtils.toHexString(header.getSessionID()).equals("00")) {
 			// EV wants to start a totally new charging session
 			setSessionID(generateSessionIDRandomly());
 			setOldSessionJoined(false);
 			return ResponseCodeType.OK_NEW_SESSION_ESTABLISHED;
 		} else if (getCurrentState().equals(getStates().get(V2GMessages.SESSION_SETUP_REQ)) && 
-				   header.getSessionID() == getSessionID()) {
+				   Arrays.equals(header.getSessionID(), getSessionID())) {
 			// A charging pause has taken place and the EV wants to resume the old charging session
 			setOldSessionJoined(true);
 			return ResponseCodeType.OK_OLD_SESSION_JOINED;
 		} else if (getCurrentState().equals(getStates().get(V2GMessages.SESSION_SETUP_REQ)) && 
-				ByteUtils.toLongFromByteArray(header.getSessionID()) != 0L &&
-				   header.getSessionID() != getSessionID()) {
+				  !ByteUtils.toHexString(header.getSessionID()).equals("00") &&
+				  !Arrays.equals(header.getSessionID(), getSessionID())) {
 			// Avoid a "FAILED_..." response code by generating a new SessionID in the response
+			getLogger().warn("Presented session ID '" + ByteUtils.toHexString(header.getSessionID()) + "' does not match stored session ID '" +
+							 ByteUtils.toHexString(getSessionID()) + "'. Will reassign a new session ID");
 			setSessionID(generateSessionIDRandomly());
 			setOldSessionJoined(false);
 			return ResponseCodeType.OK_NEW_SESSION_ESTABLISHED;
@@ -246,6 +254,27 @@ public class V2GCommunicationSessionSECC extends V2GCommunicationSession impleme
 	}
 	
 	
+	@SuppressWarnings("unchecked")
+	public PaymentOptionListType getPaymentOptions() {
+		ArrayList<PaymentOptionType> paymentOptions = new ArrayList<PaymentOptionType>();
+		
+		if (isOldSessionJoined()) {
+			paymentOptions.add(selectedPaymentOption);
+		} else { 
+			paymentOptions.addAll((ArrayList<PaymentOptionType>) (MiscUtils.getPropertyValue("authentication.modes.supported")));
+		}
+		
+		// Contract-based payment may only be offered if TLS is used
+		if (!isTlsConnection()) 
+			paymentOptions.remove(PaymentOptionType.CONTRACT);
+				
+		PaymentOptionListType paymentOptionList = new PaymentOptionListType();
+		paymentOptionList.getPaymentOption().addAll(paymentOptions);
+		
+		return paymentOptionList;
+	}
+	
+	
 	public void send(SendMessage sendMessage) {
 		// Only EXI encoded messages will be sent here. Decide whether V2GMessage or SupportedAppProtocolRes
 		byte[] payload = null;
@@ -284,24 +313,6 @@ public class V2GCommunicationSessionSECC extends V2GCommunicationSession impleme
 		return acEVSEStatus;
 	}
 
-	public boolean isStopV2GCommunicationSession() {
-		return stopV2GCommunicationSession;
-	}
-
-	public void setStopV2GCommunicationSession(boolean stopV2GCommunicationSession) {
-		this.stopV2GCommunicationSession = stopV2GCommunicationSession;
-	}
-
-	public boolean isPauseV2GCommunicationSession() {
-		return pauseV2GCommunicationSession;
-	}
-
-
-	public void setPauseV2GCommunicationSession(boolean pauseV2GCommunicationSession) {
-		this.pauseV2GCommunicationSession = pauseV2GCommunicationSession;
-	}
-
-
 	public PMaxScheduleType getPMaxSchedule() {
 		return pMaxSchedule;
 	}
@@ -475,4 +486,14 @@ public class V2GCommunicationSessionSECC extends V2GCommunicationSession impleme
 	public void setChargeProgressStarted(boolean chargeProgressStarted) {
 		this.chargeProgressStarted = chargeProgressStarted;
 	}
+
+
+	public ChargingSessionType getChargingSession() {
+		return chargingSession;
+	}
+
+
+	public void setChargingSession(ChargingSessionType chargingSession) {
+		this.chargingSession = chargingSession;
+	}
 }

+ 3 - 2
RISE-V2G-SECC/src/main/java/com/v2gclarity/risev2g/secc/states/ServerState.java

@@ -38,6 +38,7 @@ import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.CertificateChainType;
 import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.CertificateInstallationResType;
 import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.CertificateUpdateResType;
 import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ChargeParameterDiscoveryResType;
+import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ChargingSessionType;
 import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ChargingStatusResType;
 import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ContractSignatureEncryptedPrivateKeyType;
 import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.CurrentDemandResType;
@@ -167,7 +168,7 @@ public abstract class ServerState extends State {
 		
 		if (!responseCode.value().startsWith("OK")) {
 			getLogger().error("Response code '" + responseCode.value() + "' will be sent.");
-			getCommSessionContext().setStopV2GCommunicationSession(true);
+			getCommSessionContext().setChargingSession(ChargingSessionType.TERMINATE);
 		}
 		
 		return getSendMessage(message, nextExpectedMessage, "", timeout);
@@ -181,7 +182,7 @@ public abstract class ServerState extends State {
 		
 		if (!responseCode.value().substring(0, 2).toUpperCase().equals("OK")) {
 			getLogger().error("Response code '" + responseCode.value() + "' will be sent.");
-			getCommSessionContext().setStopV2GCommunicationSession(true);
+			getCommSessionContext().setChargingSession(ChargingSessionType.TERMINATE);
 		}
 		
 		getLogger().debug("Preparing to send " + messageName);

+ 17 - 6
RISE-V2G-SECC/src/main/java/com/v2gclarity/risev2g/secc/states/WaitForChargeParameterDiscoveryReq.java

@@ -40,6 +40,7 @@ import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ChargeParameterDiscovery
 import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.DCEVChargeParameterType;
 import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.EVSEProcessingType;
 import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.EnergyTransferModeType;
+import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.IsolationLevelType;
 import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ResponseCodeType;
 import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.SAScheduleListType;
 import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.V2GMessage;
@@ -80,12 +81,22 @@ public class WaitForChargeParameterDiscoveryReq extends ServerState {
 					
 					Long departureTime = chargeParameterDiscoveryReq.getEVChargeParameter().getValue().getDepartureTime();
 					
-					getCommSessionContext().setSaSchedules(
-							getCommSessionContext().getBackendInterface().getSAScheduleList(
-									maxEntriesSAScheduleTuple, 
-									(departureTime != null) ? departureTime.longValue() : 0,
-									getXMLSignatureRefElements())
-							);
+					if (getCommSessionContext().isOldSessionJoined()) {
+						getCommSessionContext().setSaSchedules(
+								getCommSessionContext().getBackendInterface().getSAScheduleList(
+										maxEntriesSAScheduleTuple, 
+										(departureTime != null) ? departureTime.longValue() : 0,
+										getXMLSignatureRefElements(),
+										getCommSessionContext().getChosenSAScheduleTuple())
+								);
+					} else {
+						getCommSessionContext().setSaSchedules(
+								getCommSessionContext().getBackendInterface().getSAScheduleList(
+										maxEntriesSAScheduleTuple, 
+										(departureTime != null) ? departureTime.longValue() : 0,
+										getXMLSignatureRefElements())
+								);
+					}
 				}
 				
 				// TODO An integration to a backend system which provides the SalesTariff would be needed here

+ 3 - 6
RISE-V2G-SECC/src/main/java/com/v2gclarity/risev2g/secc/states/WaitForPowerDeliveryReq.java

@@ -65,10 +65,6 @@ public class WaitForPowerDeliveryReq extends ServerState {
 			if (isResponseCodeOK(powerDeliveryReq)) {
 				getCommSessionContext().setChosenSAScheduleTuple(powerDeliveryReq.getSAScheduleTupleID());
 				
-				// For debugging purposes, log the ChargeProgress value
-				getLogger().debug("ChargeProgress of PowerDeliveryReq set to '" + 
-								  powerDeliveryReq.getChargeProgress().toString() + "'");
-				
 				// TODO regard [V2G2-866]
 				
 				setEVSEStatus(powerDeliveryRes);
@@ -114,8 +110,9 @@ public class WaitForPowerDeliveryReq extends ServerState {
 	public boolean isResponseCodeOK(PowerDeliveryReqType powerDeliveryReq) {
 		SAScheduleTupleType chosenSASchedule = getChosenSASCheduleTuple(powerDeliveryReq.getSAScheduleTupleID());
 		
-		// This debug message is helpful to determine why the EV might not send a ChargingProfile (parameter is optional and should only be left out if ChargeProgress is set to Stop)
-		getLogger().debug("ChargeProgress is set to " + powerDeliveryReq.getChargeProgress());
+		// This debug message is helpful to determine why the EV might not send a ChargingProfile 
+		// (parameter is optional and should only be left out if ChargeProgress is set to Stop)
+		getLogger().debug("ChargeProgress of PowerDeliveryReq set to '" + powerDeliveryReq.getChargeProgress().toString() + "'");
 		
 		if (powerDeliveryReq.getChargeProgress().equals(ChargeProgressType.RENEGOTIATE) && 
 				!getCommSessionContext().isChargeProgressStarted()) {

+ 12 - 3
RISE-V2G-SECC/src/main/java/com/v2gclarity/risev2g/secc/states/WaitForSessionStopReq.java

@@ -27,6 +27,7 @@ import com.v2gclarity.risev2g.secc.session.V2GCommunicationSessionSECC;
 import com.v2gclarity.risev2g.shared.enumerations.V2GMessages;
 import com.v2gclarity.risev2g.shared.messageHandling.ReactionToIncomingMessage;
 import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.BodyBaseType;
+import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ChargingSessionType;
 import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.PaymentServiceSelectionReqType;
 import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ResponseCodeType;
 import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.SessionStopReqType;
@@ -51,18 +52,26 @@ public class WaitForSessionStopReq extends ServerState {
 			
 			getLogger().info("EV indicated to " + sessionStopReq.getChargingSession() + " the charging session");
 			
-			getCommSessionContext().setStopV2GCommunicationSession(true);
+			if (sessionStopReq.getChargingSession() == ChargingSessionType.TERMINATE) {
+				getCommSessionContext().setChargingSession(ChargingSessionType.TERMINATE);
+				return getSendMessage(sessionStopRes, V2GMessages.NONE, sessionStopRes.getResponseCode());
+			} else {
+				// EV indicated to pause the charging session. Next expected request message is SupportedAppProtocolReq
+				getCommSessionContext().setChargingSession(ChargingSessionType.PAUSE);
+				return getSendMessage(sessionStopRes, V2GMessages.SUPPORTED_APP_PROTOCOL_REQ, sessionStopRes.getResponseCode());
+			}
 		} else {
+			getCommSessionContext().setChargingSession(ChargingSessionType.TERMINATE);
+			
 			if (sessionStopRes.getResponseCode().equals(ResponseCodeType.FAILED_SEQUENCE_ERROR)) {
 				BodyBaseType responseMessage = getSequenceErrorResMessage(new SessionStopResType(), message);
 				
 				return getSendMessage(responseMessage, V2GMessages.NONE, sessionStopRes.getResponseCode());
 			} else {
 				setMandatoryFieldsForFailedRes(sessionStopRes, sessionStopRes.getResponseCode());
+				return getSendMessage(sessionStopRes, V2GMessages.NONE, sessionStopRes.getResponseCode());
 			}
 		}
-			
-		return getSendMessage(sessionStopRes, V2GMessages.NONE, sessionStopRes.getResponseCode());
 	}
 
 

+ 3 - 33
RISE-V2G-Shared/src/main/java/com/v2gclarity/risev2g/shared/misc/V2GCommunicationSession.java

@@ -60,16 +60,7 @@ public abstract class V2GCommunicationSession extends Observable {
 		setSessionID(null);
 		setV2gTpMessage(null);
 	}
-	
-	
-	/**
-	 * Generates a session ID (with length of 8 bytes) from a given long value.
-	 * @param The long value representing a session ID (either 0 or a previously stored session ID)
-	 * @return The byte array representation of the provided session ID
-	 */
-	public byte[] generateSessionIDFromValue(long fromValue) {
-		return ByteUtils.toByteArrayFromLong(fromValue);
-	}
+
 	
 	/**
 	 * Generates randomly a new session ID (with length of 8 bytes) and takes care that the newly generated 
@@ -87,8 +78,7 @@ public abstract class V2GCommunicationSession extends Observable {
 	}
 	
 	protected void pauseSession(PauseSession pauseObject) {
-		getLogger().info("Pausing"
-				+ " V2G communication session");
+		getLogger().info("Pausing V2G communication session");
 		setChanged();
 		notifyObservers(pauseObject);
 	}
@@ -126,25 +116,6 @@ public abstract class V2GCommunicationSession extends Observable {
 	}
 
 	
-	public PaymentOptionListType getPaymentOptions() {
-		@SuppressWarnings("unchecked")
-		ArrayList<PaymentOptionType> paymentOptions = (ArrayList<PaymentOptionType>) (MiscUtils.getPropertyValue("authentication.modes.supported"));
-		
-		if (paymentOptions == null) {
-			paymentOptions = new ArrayList<PaymentOptionType>();
-		}
-		
-		// Contract-based payment may only be offered if TLS is used
-		if (!isTlsConnection()) 
-			paymentOptions.remove(PaymentOptionType.CONTRACT);
-				
-		PaymentOptionListType paymentOptionList = new PaymentOptionListType();
-		paymentOptionList.getPaymentOption().addAll(paymentOptions);
-		
-		return paymentOptionList;
-	}
-	
-	
 	public ArrayList<EnergyTransferModeType> getSupportedEnergyTransferModes() {
 		@SuppressWarnings("unchecked")
 		ArrayList<EnergyTransferModeType> energyTransferModes = 
@@ -199,10 +170,9 @@ public abstract class V2GCommunicationSession extends Observable {
 
 	public void setSessionID(byte[] sessionID) {
 		if (sessionID == null) {
-			sessionID = generateSessionIDFromValue(0L);
+			sessionID = ByteUtils.toByteArrayFromHexString("00");
 		} 
 		this.sessionID = sessionID;
-		MiscUtils.getV2gEntityConfig().setProperty("session.id", String.valueOf(ByteUtils.toLongFromByteArray(sessionID)));
 	}
 
 	public V2GTPMessage getV2gTpMessage() {

+ 1 - 1
RISE-V2G-Shared/src/main/java/com/v2gclarity/risev2g/shared/misc/V2GImplementationFactory.java

@@ -43,7 +43,7 @@ public abstract class V2GImplementationFactory {
 	 */
 	protected static <T> T buildFromProperties(String propertyName, Class<T> cls) {
 		try {
-			String className = MiscUtils.getV2gEntityConfig().getProperty(propertyName);
+			String className = MiscUtils.getProperties().getProperty(propertyName);
 			if (className == null) {
 				return null;
 			}

+ 4 - 2
RISE-V2G-Shared/src/main/java/com/v2gclarity/risev2g/shared/utils/ByteUtils.java

@@ -67,9 +67,11 @@ public final class ByteUtils {
 	 * 					 representing the octet code. For example, '0FB7' is a hex encoding for the 
 	 * 					 16-bit integer 4023 (whose binary representation is 111110110111)."
 	 * @return A byte array representing the hexadecimal string
+	 * @throws IllegalArgumentException Passes on the IllegalArgumentException from the method DatatypeConverter.parseHexBinary()
+	 * 								   so that the caller can appropriately handle the execption
 	 */
-	public static byte[] toByteArrayFromHexString(String s) {
-	    return DatatypeConverter.parseHexBinary(s);
+	public static byte[] toByteArrayFromHexString(String s) throws IllegalArgumentException {
+		return DatatypeConverter.parseHexBinary(s);
 	}
 	
 	/**

+ 46 - 34
RISE-V2G-Shared/src/main/java/com/v2gclarity/risev2g/shared/utils/MiscUtils.java

@@ -25,6 +25,7 @@ package com.v2gclarity.risev2g.shared.utils;
 
 			import java.io.FileInputStream;
 import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.net.Inet6Address;
 import java.net.InetAddress;
@@ -47,7 +48,7 @@ public final class MiscUtils {
 
 	static Logger logger = LogManager.getLogger(MiscUtils.class.getSimpleName());
 	static V2GMessages[] messageTypes = V2GMessages.values();
-	static Properties v2gEntityConfig;
+	static Properties properties;
 	
 	public static Logger getLogger() {
 		return logger;
@@ -131,34 +132,27 @@ public final class MiscUtils {
 	 * in this method. The return value differs depending on the key. Therefore, the return value
 	 * is given as an Object, which again must be casted to the matching type when using this method.
 	 * 
-	 * @param propertyName The key string written in the respective properties file of each V2G entity (EV or EVSE)
+	 * @param propertyKey The key string written in the respective properties file of each V2G entity (EV or EVSE)
 	 * @return An Object holding the data structure fitting for the key (e.g. an Enum value, a Boolean, 
 	 * 			a collection, ...)
 	 */
-	public static Object getPropertyValue(String propertyName) {
+	public static Object getPropertyValue(String propertyKey) {
 		Object returnValue = null;
 		String propertyValue = "";
 		
 		try {
-			propertyValue = getV2gEntityConfig().getProperty(propertyName).replaceAll("\\s", "");
+			propertyValue = getProperties().getProperty(propertyKey).replaceAll("\\s", "");
 		} catch (NullPointerException e) {
-			getLogger().warn("No entry found in the properties file for property '" + propertyName + "'", e);
+			getLogger().warn("No entry found in the properties file for property '" + propertyKey + "'", e);
 			return null;
 		}
 		
-		switch (propertyName) {
+		switch (propertyKey) {
 		case "network.interface": // EV + EVSE property
 			returnValue = propertyValue;
 			break;
 		case "session.id": // EV property
-			try {
-				returnValue = Long.parseLong(propertyValue);
-			} catch (NumberFormatException e) {
-				getLogger().warn("SessionID '" + propertyValue + "' not supported. " +
-							     "Setting default value to 0.", e);
-				getV2gEntityConfig().setProperty("session.id", "0");
-				returnValue = 0L;
-			}
+			returnValue = propertyValue;  // a hexadecimal string representing a byte array
 			break;
 		case "energy.transfermodes.supported": // EVSE property
 			String energyTransferMode = "";
@@ -170,7 +164,7 @@ public final class MiscUtils {
 					try {
 						supportedEnergyTransferModeType.getEnergyTransferMode().add(EnergyTransferModeType.fromValue(energyTransferMode));
 					} catch (IllegalArgumentException e){
-						getLogger().warn("EnergyTransferModeType '" + energyTransferMode + "' not supported");
+						getLogger().warn("EnergyTransferModeType '" + energyTransferMode + "' listed in properties file is not supported");
 					}
 				}
 			}
@@ -178,11 +172,10 @@ public final class MiscUtils {
 			break;
 		case "energy.transfermode.requested": // EV property
 			try {
-				if (!propertyValue.equals("")) returnValue = EnergyTransferModeType.fromValue(propertyValue);
-				else return null;
+				if (!propertyValue.equals("")) 
+					returnValue = EnergyTransferModeType.fromValue(propertyValue);
 			} catch (IllegalArgumentException e) {
-				getLogger().warn("EnergyTransferModeType '" + propertyValue + "' not supported");
-				return null;
+				getLogger().warn("EnergyTransferModeType '" + propertyValue + "' listed in properties file is not supported");
 			}
 			break;
 		case "tls": // EV property (with this code, TLS is always supported on EVSE side)
@@ -193,19 +186,18 @@ public final class MiscUtils {
 			try {
 				returnValue = Integer.parseInt(propertyValue);
 			} catch (NumberFormatException e) {
-				getLogger().warn("ContractCertificateUpdateTimespan '" + propertyValue + "' not supported. " +
+				getLogger().warn("ContractCertificateUpdateTimespan '" + propertyValue + "' listed in properties file is not supported. " +
 							     "Setting default value to 14.", e);
-				getV2gEntityConfig().setProperty("contract.certificate.update.timespan", "14");
+				getProperties().setProperty("contract.certificate.update.timespan", "14");
 				returnValue = 14;
 			}
 			break;
 		case "authentication.mode": // EV property
 			try {
-				if (!propertyValue.equals("")) returnValue = PaymentOptionType.fromValue(propertyValue);
-				else return null;
+				if (!propertyValue.equals("")) 
+					returnValue = PaymentOptionType.fromValue(propertyValue);
 			} catch (IllegalArgumentException e) {
-				getLogger().warn("PaymentOptionType '" + propertyValue + "' not supported");
-				return null;
+				getLogger().warn("PaymentOptionType '" + propertyValue + "' listed in properties file is not supported");
 			}
 			break;
 		case "authentication.modes.supported": // EVSE property
@@ -219,7 +211,7 @@ public final class MiscUtils {
 					try {
 						paymentOptionsList.add(PaymentOptionType.fromValue(option));
 					} catch (IllegalArgumentException e) {
-						getLogger().warn("PaymentOptionType '" + option + "' not supported");
+						getLogger().warn("PaymentOptionType '" + option + "' listed in properties file is not supported");
 					}
 				}
 			}
@@ -251,14 +243,14 @@ public final class MiscUtils {
 			try {
 				returnValue = Integer.parseInt(propertyValue);
 			} catch (NumberFormatException e) {
-				getLogger().warn("Voltage accuracy '" + propertyValue + "' not supported. " +
+				getLogger().warn("Voltage accuracy '" + propertyValue + "' listed in properties file is not supported. " +
 							     "Setting default value to 5.", e);
-				getV2gEntityConfig().setProperty("voltage.accuracy", "5");
+				getProperties().setProperty("voltage.accuracy", "5");
 				returnValue = 5;
 			}
 			break;
 		default:
-			getLogger().error("No property with name '" + propertyName + "' found");
+			getLogger().error("No property with name '" + propertyKey + "' found");
 		}
 		
 		return returnValue;
@@ -273,8 +265,8 @@ public final class MiscUtils {
 	 * @return The Properties object containing the (key, value)-pairs of the respective properties
 	 * 			file for the respective V2G entity (EVCC or SECC)
 	 */
-	public static Properties getV2gEntityConfig() {
-		return v2gEntityConfig;
+	public static Properties getProperties() {
+		return properties;
 	}
 
 
@@ -287,13 +279,12 @@ public final class MiscUtils {
 	 * @param propertiesFileLocation The location of the properties file
 	 * @return True, if the properties file could be loaded successfully.
 	 */
-	public static boolean setV2gEntityConfig(String propertiesFileLocation) {
-		Properties properties = new Properties();
+	public static boolean loadProperties(String propertiesFileLocation) {
+		properties = new Properties();
 		
 		try {
 			FileInputStream config = new FileInputStream(propertiesFileLocation);
 			properties.load(config);
-			v2gEntityConfig = properties;
 			config.close();
 			return true;
 		} catch (FileNotFoundException e) {
@@ -306,4 +297,25 @@ public final class MiscUtils {
 			return false;
 		}
 	}
+	
+	
+	/**
+	 * Stores the current properties into the properties file
+	 * 
+	 */
+	public static void storeProperties(String propertiesFileLocation) {
+		try {
+			FileOutputStream configFile = new FileOutputStream(propertiesFileLocation);
+			
+			getProperties().store(configFile, "");
+		} catch (FileNotFoundException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		} catch (IOException e) {
+			// TODO Auto-generated catch block
+						e.printStackTrace();
+		}
+		
+//		getV2gEntityConfig().store(out, "");
+	}
 }