ClientState.java 21 KB

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