ClientState.java 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. /*******************************************************************************
  2. * The MIT License (MIT)
  3. *
  4. * Copyright (c) 2015 - 2019 Dr. Marc Mültin (V2G Clarity)
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. *******************************************************************************/
  24. package com.v2gclarity.risev2g.evcc.states;
  25. import java.security.KeyStore;
  26. import java.util.Arrays;
  27. import java.util.ListIterator;
  28. import javax.xml.bind.JAXBElement;
  29. import javax.xml.namespace.QName;
  30. import com.v2gclarity.risev2g.evcc.evController.IACEVController;
  31. import com.v2gclarity.risev2g.evcc.evController.IDCEVController;
  32. import com.v2gclarity.risev2g.evcc.session.V2GCommunicationSessionEVCC;
  33. import com.v2gclarity.risev2g.shared.enumerations.CPStates;
  34. import com.v2gclarity.risev2g.shared.enumerations.GlobalValues;
  35. import com.v2gclarity.risev2g.shared.enumerations.V2GMessages;
  36. import com.v2gclarity.risev2g.shared.misc.State;
  37. import com.v2gclarity.risev2g.shared.utils.ByteUtils;
  38. import com.v2gclarity.risev2g.shared.utils.MiscUtils;
  39. import com.v2gclarity.risev2g.shared.utils.SecurityUtils;
  40. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.AuthorizationReqType;
  41. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.AuthorizationResType;
  42. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.BodyBaseType;
  43. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.CableCheckReqType;
  44. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.CableCheckResType;
  45. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.CertificateInstallationResType;
  46. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.CertificateUpdateResType;
  47. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ChargeParameterDiscoveryReqType;
  48. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ChargeParameterDiscoveryResType;
  49. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ChargeProgressType;
  50. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ChargingProfileType;
  51. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ChargingSessionType;
  52. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ChargingStatusResType;
  53. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.CurrentDemandReqType;
  54. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.CurrentDemandResType;
  55. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.DCEVPowerDeliveryParameterType;
  56. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.EMAIDType;
  57. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.EnergyTransferModeType;
  58. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.MessageHeaderType;
  59. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.MeteringReceiptResType;
  60. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.PaymentDetailsReqType;
  61. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.PaymentDetailsResType;
  62. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.PaymentOptionType;
  63. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.PaymentServiceSelectionReqType;
  64. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.PaymentServiceSelectionResType;
  65. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.PowerDeliveryReqType;
  66. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.PowerDeliveryResType;
  67. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.PreChargeResType;
  68. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ResponseCodeType;
  69. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ServiceDetailReqType;
  70. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ServiceDetailResType;
  71. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.ServiceDiscoveryResType;
  72. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.SessionSetupResType;
  73. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.SessionStopReqType;
  74. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.SessionStopResType;
  75. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.V2GMessage;
  76. import com.v2gclarity.risev2g.shared.v2gMessages.msgDef.WeldingDetectionResType;
  77. /**
  78. * Some request messages are to be sent from different states which makes it more convenient (having
  79. * less code and being less error-prone) to keep the creation of those messages in one single class.
  80. */
  81. public abstract class ClientState extends State {
  82. public ClientState(V2GCommunicationSessionEVCC commSessionContext) {
  83. super(commSessionContext);
  84. }
  85. public V2GCommunicationSessionEVCC getCommSessionContext() {
  86. return (V2GCommunicationSessionEVCC) super.getCommSessionContext();
  87. }
  88. protected boolean isIncomingMessageValid(Object incomingMessage, Class<? extends BodyBaseType> expectedMessage) {
  89. V2GMessage v2gMessage = null;
  90. if (incomingMessage instanceof V2GMessage) {
  91. v2gMessage = (V2GMessage) incomingMessage;
  92. if (!expectedMessage.isAssignableFrom(v2gMessage.getBody().getBodyElement().getValue().getClass())) {
  93. getLogger().fatal("Invalid message (" + v2gMessage.getBody().getBodyElement().getValue().getClass().getSimpleName() +
  94. ") at this state (" + this.getClass().getSimpleName() + ")");
  95. return false;
  96. } else {
  97. getLogger().debug(v2gMessage.getBody().getBodyElement().getValue().getClass().getSimpleName().replace("Type", "") + " received");
  98. if (!isHeaderOK(v2gMessage.getHeader())) return false;
  99. if (!isResponseCodeOK(v2gMessage)) return false;
  100. return true;
  101. }
  102. } else {
  103. getLogger().fatal("Incoming message is not a V2GMessage");
  104. return false;
  105. }
  106. }
  107. /**
  108. * Performs the following checks:
  109. * - is the returned session ID the same as the one saved by the EVCC?
  110. * - does the EVCC need to react to a possibly set notification?
  111. * - does the EVCC need to check the signature?
  112. *
  113. * @param header The header of the V2GMessage
  114. */
  115. private boolean isHeaderOK(MessageHeaderType header) {
  116. // Check sessionID (only if not at state WaitForSessionSetupRes)
  117. if (!this.equals(getCommSessionContext().getStates().get(V2GMessages.SESSION_SETUP_RES)) &&
  118. !Arrays.equals(header.getSessionID(), getCommSessionContext().getSessionID())) {
  119. getLogger().error("Session ID is invalid: " +
  120. "expected " + ByteUtils.toLongFromByteArray(getCommSessionContext().getSessionID()) +
  121. ", received " + ByteUtils.toLongFromByteArray(header.getSessionID()));
  122. return false;
  123. }
  124. if (header.getNotification() != null) {
  125. // TODO react on the several notifications
  126. }
  127. /*
  128. * If a signature is present, it is placed in the header. However, not all messages have a
  129. * signature. Therefore, the signature validation is to be done in the respective state itself.
  130. */
  131. return true;
  132. }
  133. private boolean isResponseCodeOK(V2GMessage responseMessage) {
  134. BodyBaseType bbt = ((V2GMessage) responseMessage).getBody().getBodyElement().getValue();
  135. ResponseCodeType v2gMessageRCT = null;
  136. switch (bbt.getClass().getSimpleName()) {
  137. case "SessionSetupResType":
  138. v2gMessageRCT = ((SessionSetupResType) bbt).getResponseCode();
  139. break;
  140. case "ServiceDiscoveryResType":
  141. v2gMessageRCT = ((ServiceDiscoveryResType) bbt).getResponseCode();
  142. break;
  143. case "ServiceDetailResType":
  144. v2gMessageRCT = ((ServiceDetailResType) bbt).getResponseCode();
  145. break;
  146. case "PaymentServiceSelectionResType":
  147. v2gMessageRCT = ((PaymentServiceSelectionResType) bbt).getResponseCode();
  148. break;
  149. case "PaymentDetailsResType":
  150. v2gMessageRCT = ((PaymentDetailsResType) bbt).getResponseCode();
  151. break;
  152. case "CertificateInstallationResType":
  153. v2gMessageRCT = ((CertificateInstallationResType) bbt).getResponseCode();
  154. break;
  155. case "CertificateUpdateResType":
  156. v2gMessageRCT = ((CertificateUpdateResType) bbt).getResponseCode();
  157. break;
  158. case "AuthorizationResType":
  159. v2gMessageRCT = ((AuthorizationResType) bbt).getResponseCode();
  160. break;
  161. case "ChargeParameterDiscoveryResType":
  162. v2gMessageRCT = ((ChargeParameterDiscoveryResType) bbt).getResponseCode();
  163. break;
  164. case "CableCheckResType":
  165. v2gMessageRCT = ((CableCheckResType) bbt).getResponseCode();
  166. break;
  167. case "PreChargeResType":
  168. v2gMessageRCT = ((PreChargeResType) bbt).getResponseCode();
  169. break;
  170. case "PowerDeliveryResType":
  171. v2gMessageRCT = ((PowerDeliveryResType) bbt).getResponseCode();
  172. break;
  173. case "ChargingStatusResType":
  174. v2gMessageRCT = ((ChargingStatusResType) bbt).getResponseCode();
  175. break;
  176. case "CurrentDemandResType":
  177. v2gMessageRCT = ((CurrentDemandResType) bbt).getResponseCode();
  178. break;
  179. case "MeteringReceiptResType":
  180. v2gMessageRCT = ((MeteringReceiptResType) bbt).getResponseCode();
  181. break;
  182. case "WeldingDetectionResType":
  183. v2gMessageRCT = ((WeldingDetectionResType) bbt).getResponseCode();
  184. break;
  185. case "SessionStopResType":
  186. v2gMessageRCT = ((SessionStopResType) bbt).getResponseCode();
  187. break;
  188. default:
  189. getLogger().error("Response message could not be identified");
  190. return false;
  191. }
  192. if (v2gMessageRCT.toString().startsWith("OK")) return true;
  193. else {
  194. getLogger().error("Negative response code " + v2gMessageRCT.toString());
  195. return false;
  196. }
  197. }
  198. /**
  199. * A ServiceDetailReq needs to be generated from several states:
  200. * - WaitForServiceDiscoveryRes
  201. * - WaitForServiceDetailRes
  202. *
  203. * Checks if the list of value added services (VAS) which are to be used contains service IDs. Those
  204. * service IDs can be used in a ServiceDetailReq to request more details about the service.
  205. * Each time a ServiceDetailReq is created, the respective service ID is deleted from the list.
  206. *
  207. * @return A ServiceDetailReq with a service ID whose details are requested, if the list of service IDs
  208. * is not empty. Null otherwise.
  209. */
  210. protected ServiceDetailReqType getServiceDetailReq() {
  211. if (getCommSessionContext().getServiceDetailsToBeRequested().size() > 0) {
  212. ListIterator<Short> listIterator = getCommSessionContext().getServiceDetailsToBeRequested().listIterator();
  213. ServiceDetailReqType serviceDetailReq = new ServiceDetailReqType();
  214. serviceDetailReq.setServiceID((short) listIterator.next());
  215. listIterator.remove();
  216. return serviceDetailReq;
  217. }
  218. return null;
  219. }
  220. /**
  221. * A ServiceDetailReq needs to be generated from several states:
  222. * - WaitForServiceDiscoveryRes
  223. * - WaitForServiceDetailRes
  224. */
  225. protected PaymentServiceSelectionReqType paymentServiceSelectionReq() {
  226. PaymentServiceSelectionReqType paymentServiceSelectionReq = new PaymentServiceSelectionReqType();
  227. paymentServiceSelectionReq.setSelectedPaymentOption(getCommSessionContext().getSelectedPaymentOption());
  228. return paymentServiceSelectionReq;
  229. }
  230. /**
  231. * An AuthorizationReq needs to be generated from several states:
  232. * - WaitForPaymentServiceSelectionRes (no genChallege)
  233. * - WaitForPaymentDetailsRes (genChallenge)
  234. * - WaitForAuthorizationRes (no genChallenge, EVSE is still processing)
  235. *
  236. * @return An AuthorizationReq, either empty or with a set genChallenge and ID depending on input parameter
  237. */
  238. protected AuthorizationReqType getAuthorizationReq(byte[] genChallenge) {
  239. AuthorizationReqType authorizationReq = new AuthorizationReqType();
  240. if (genChallenge != null) {
  241. authorizationReq.setGenChallenge(genChallenge);
  242. /*
  243. * Experience from the test symposium in San Diego (April 2016):
  244. * The Id element of the signature is not restricted in size by the standard itself. But on embedded
  245. * systems, the memory is very limited which is why we should not use long IDs for the signature reference
  246. * element. A good size would be 3 characters max (like the example in the ISO 15118-2 annex J)
  247. */
  248. authorizationReq.setId("ID1");
  249. }
  250. return authorizationReq;
  251. }
  252. /**
  253. * A CableCheckReq needs to be generated from several states:
  254. * - WaitForChargeParameterDiscoveryRes
  255. * - WaitForCableCheckRes (EVSEProcessing = ONGOING)
  256. *
  257. * @return A CableCheckReq
  258. */
  259. protected CableCheckReqType getCableCheckReq() {
  260. CableCheckReqType cableCheckReq = new CableCheckReqType();
  261. cableCheckReq.setDCEVStatus(((IDCEVController) getCommSessionContext().getEvController()).getDCEVStatus());
  262. return cableCheckReq;
  263. }
  264. /**
  265. * A CurrentDemandReq needs to be generated from several states:
  266. * - WaitForCurrentDemandRes (the initial CurrentDemandReq message)
  267. * - WaitForMeteringReceiptRes
  268. *
  269. * @return A CurrentDemandReq message
  270. */
  271. protected CurrentDemandReqType getCurrentDemandReq() {
  272. IDCEVController evController = (IDCEVController) getCommSessionContext().getEvController();
  273. CurrentDemandReqType currentDemandReq = new CurrentDemandReqType();
  274. currentDemandReq.setBulkChargingComplete(evController.isBulkChargingComplete());
  275. currentDemandReq.setChargingComplete(evController.isChargingComplete());
  276. currentDemandReq.setDCEVStatus(evController.getDCEVStatus());
  277. currentDemandReq.setEVMaximumCurrentLimit(evController.getMaximumCurrentLimit());
  278. currentDemandReq.setEVMaximumPowerLimit(evController.getMaximumPowerLimit());
  279. currentDemandReq.setEVMaximumVoltageLimit(evController.getMaximumVoltageLimit());
  280. currentDemandReq.setEVTargetCurrent(evController.getTargetCurrent());
  281. currentDemandReq.setEVTargetVoltage(evController.getTargetVoltage());
  282. currentDemandReq.setRemainingTimeToBulkSoC(evController.getRemainingTimeToBulkSOC());
  283. currentDemandReq.setRemainingTimeToFullSoC(evController.getRemainingTimeToFullSOC());
  284. return currentDemandReq;
  285. }
  286. /**
  287. * A ChargeParameterDiscoveryReq needs to be generated from several states:
  288. * - WaitForAuthorizationRes (the initial ChargeParameterDiscoveryReq)
  289. * - WaitForPowerDeliveryRes (in case AC_EVSEStatus requests a renegotiation)
  290. * - WaitForChargingStatusRes (in case AC_EVSEStatus requests a renegotiation)
  291. *
  292. * @return A ChargeParameterDiscoveryReq which itself consists of several complex datatypes.
  293. */
  294. protected ChargeParameterDiscoveryReqType getChargeParameterDiscoveryReq() {
  295. ChargeParameterDiscoveryReqType chargeParameterDiscoveryReq = new ChargeParameterDiscoveryReqType();
  296. // Optionally limit the number of entries in the SAScheduleTuple by setting MaxEntriesSAScheduleTuple
  297. chargeParameterDiscoveryReq.setRequestedEnergyTransferMode(getRequestedEnergyTransferMode());
  298. if (getCommSessionContext().getRequestedEnergyTransferMode().toString().startsWith("AC"))
  299. chargeParameterDiscoveryReq.setEVChargeParameter(((IACEVController) getCommSessionContext().getEvController()).getACEVChargeParamter());
  300. else
  301. chargeParameterDiscoveryReq.setEVChargeParameter(((IDCEVController) getCommSessionContext().getEvController()).getDCEVChargeParamter());
  302. return chargeParameterDiscoveryReq;
  303. }
  304. /**
  305. * A PaymentServiceSelectionReq needs to be generated from several states:
  306. * - WaitForServiceDiscoveryRes
  307. * - WaitForServiceDetailRes
  308. *
  309. * @return A PaymentServiceSelectionReq
  310. */
  311. protected PaymentServiceSelectionReqType getPaymentServiceSelectionReq() {
  312. PaymentServiceSelectionReqType paymentServiceSelectionReq = new PaymentServiceSelectionReqType();
  313. paymentServiceSelectionReq.setSelectedPaymentOption(getCommSessionContext().getSelectedPaymentOption());
  314. paymentServiceSelectionReq.setSelectedServiceList(getCommSessionContext().getSelectedServices());
  315. return paymentServiceSelectionReq;
  316. }
  317. /**
  318. * A PaymentDetailsReq needs to be generated from several states:
  319. * - WaitForPaymentServiceSelectionRes
  320. * - WaitForCertificateInstallationRes
  321. * - WaitForCertificateUpdateRes
  322. *
  323. * @return A PaymentDetailsReq
  324. */
  325. protected PaymentDetailsReqType getPaymentDetailsReq() {
  326. KeyStore evccKeyStore = SecurityUtils.getKeyStore(
  327. GlobalValues.EVCC_KEYSTORE_FILEPATH.toString(),
  328. GlobalValues.PASSPHRASE_FOR_CERTIFICATES_AND_KEYS.toString());
  329. PaymentDetailsReqType paymentDetailsReq = new PaymentDetailsReqType();
  330. EMAIDType emaid = SecurityUtils.getEMAID(GlobalValues.PASSPHRASE_FOR_CERTIFICATES_AND_KEYS.toString());
  331. if (emaid != null) {
  332. paymentDetailsReq.setEMAID(SecurityUtils.getEMAID(GlobalValues.PASSPHRASE_FOR_CERTIFICATES_AND_KEYS.toString()).getValue());
  333. paymentDetailsReq.setContractSignatureCertChain(SecurityUtils.getCertificateChain(
  334. evccKeyStore, GlobalValues.ALIAS_CONTRACT_CERTIFICATE.toString()));
  335. }
  336. return paymentDetailsReq;
  337. }
  338. /**
  339. * A PowerDeliveryReq needs to be generated from several states:
  340. * - WaitForChargeParameterDiscoveryRes
  341. * - WaitForChargingStatusRes
  342. * - WaitForMeteringReceiptRes
  343. *
  344. * @param chargeProgress Indicates whether to START a charging session, RENEGOTIATE charing parameters
  345. * or STOP the charging session
  346. * @return A ChargeParameterDiscoveryReq which itself consists of several complex datatypes.
  347. */
  348. protected PowerDeliveryReqType getPowerDeliveryReq(ChargeProgressType chargeProgress) {
  349. PowerDeliveryReqType powerDeliveryReq = new PowerDeliveryReqType();
  350. if (chargeProgress.equals(ChargeProgressType.START)) {
  351. // Signal needed state change after sending PowerDeliveryReq in AC charging mode
  352. if (getCommSessionContext().getRequestedEnergyTransferMode().toString().startsWith("AC"))
  353. getCommSessionContext().setChangeToState(CPStates.STATE_C);
  354. ChargingProfileType chargingProfile = getCommSessionContext().getEvController().getChargingProfile();
  355. powerDeliveryReq.setChargingProfile(chargingProfile);
  356. getCommSessionContext().setChargingProfile(chargingProfile);
  357. } else if (chargeProgress.equals(ChargeProgressType.STOP)) {
  358. // Signal needed state change after sending PowerDeliveryReq in AC charging mode
  359. if (getCommSessionContext().getRequestedEnergyTransferMode().toString().startsWith("AC"))
  360. getCommSessionContext().setChangeToState(CPStates.STATE_B);
  361. }
  362. powerDeliveryReq.setChargeProgress(chargeProgress);
  363. powerDeliveryReq.setSAScheduleTupleID(getCommSessionContext().getEvController().getChosenSAScheduleTupleID());
  364. // Set DC_EVPowerDeliveryParameter if in DC charging mode
  365. if (getCommSessionContext().getRequestedEnergyTransferMode().toString().startsWith("DC")) {
  366. /*
  367. * The MessageHandler method getJAXBElement() cannot be used here because of the difference in the
  368. * class name (DCEVPowerDeliveryParameter) and the name in the XSD (DC_EVPowerDeliveryParameter)
  369. */
  370. JAXBElement<DCEVPowerDeliveryParameterType> jaxbDcEvPowerDeliveryParameter = new JAXBElement<>(new QName("urn:iso:15118:2:2013:MsgDataTypes", "DC_EVPowerDeliveryParameter"),
  371. DCEVPowerDeliveryParameterType.class,
  372. ((IDCEVController) getCommSessionContext().getEvController()).getEVPowerDeliveryParameter());
  373. powerDeliveryReq.setEVPowerDeliveryParameter(jaxbDcEvPowerDeliveryParameter);
  374. }
  375. return powerDeliveryReq;
  376. }
  377. /**
  378. * A SessionStopReq needs to be generated from several states:
  379. * - WaitForPowerDeliveryRes
  380. * - WaitForWeldingDetectionRes
  381. *
  382. * @return A SessionStopReq message
  383. */
  384. protected SessionStopReqType getSessionStopReq(ChargingSessionType chargingSessionType) {
  385. SessionStopReqType sessionStopReq = new SessionStopReqType();
  386. sessionStopReq.setChargingSession(chargingSessionType);
  387. return sessionStopReq;
  388. }
  389. protected EnergyTransferModeType getRequestedEnergyTransferMode() {
  390. EnergyTransferModeType requestedEnergyTransferMode = null;
  391. // Check if an EnergyTransferModeType has been requested in a previously paused session
  392. if (getCommSessionContext().isOldSessionJoined())
  393. requestedEnergyTransferMode = (EnergyTransferModeType) MiscUtils.getPropertyValue("energy.transfermode.requested");
  394. if (requestedEnergyTransferMode == null)
  395. requestedEnergyTransferMode = getCommSessionContext().getEvController().getRequestedEnergyTransferMode();
  396. // We need to save the requested energy transfer mode in the session variable to be able to store in the properties file during pausing
  397. getCommSessionContext().setRequestedEnergyTransferMode(requestedEnergyTransferMode);
  398. return requestedEnergyTransferMode;
  399. }
  400. }