1
0

pev_service.c 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397
  1. /*
  2. * Copyright (C) 2007-2012 Siemens AG
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU Lesser General Public License as published
  6. * by the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. /*******************************************************************
  18. *
  19. * @author Sebastian.Kaebisch.EXT@siemens.com
  20. * @version 0.6
  21. * @contact Joerg.Heuer@siemens.com
  22. *
  23. ********************************************************************/
  24. /* includes of the 15118 messaging */
  25. #include "v2g_service.h"
  26. #include "v2g_serviceDataTypes.h"
  27. #include "v2g_serviceClientStubs.h"
  28. #include "EXITypes.h"
  29. /* includes for the application handshake protocol */
  30. #include "appHand_service.h"
  31. #include "appHand_dataTypes.h"
  32. /* includes V2GTP */
  33. #include "v2gtp.h"
  34. /* includes for example data transmitter */
  35. #include "serviceClientDataTransmitter.h"
  36. #include <stdio.h>
  37. #define MAX_BYTE_SIZE 128
  38. #define MAX_STRING_SIZE 256
  39. #define MAX_STREAM_SIZE 100
  40. static void printErrorMessage(struct EXIService* service);
  41. static void printDCEVSEStatus(struct DC_EVSEStatusType* status);
  42. static void printACEVSEStatus(struct AC_EVSEStatusType* status);
  43. static void printASCIIString(uint32_t* string, uint32_t len);
  44. static void printBinaryArray(uint8_t* byte, uint32_t len);
  45. static int writeStringToEXIString(char* string, uint32_t* exiString);
  46. /** Example implementation of the handshake protocol (EV side) */
  47. static int appHandshake()
  48. {
  49. static uint8_t byte_array[MAX_BYTE_SIZE]; /* define MAX_BYTE_SIZE before*/
  50. static uint32_t string_array[MAX_STRING_SIZE]; /* define MAX_STRING_SIZE before*/
  51. /* define in and out byte stream */
  52. uint8_t inStream[MAX_STREAM_SIZE]; /* define MAX_STREAM_SIZE before */
  53. uint8_t outStream[MAX_STREAM_SIZE]; /* define MAX_STREAM_SIZE before */
  54. /* BINARY memory setup */
  55. bytes_t bytes = { MAX_BYTE_SIZE, byte_array, 0 };
  56. /* STRING memory setup */
  57. string_ucs_t string = { MAX_STRING_SIZE, string_array, 0 };
  58. struct EXIDatabinder appHandService;
  59. struct EXIDocumentType_appHand exiDoc;
  60. struct AnonType_supportedAppProtocolReq handshake;
  61. struct AnonType_supportedAppProtocolRes resultHandshake;
  62. uint16_t length, payloadLength;
  63. /* init the app handshake serializer.
  64. * Important: also provide the offset of the V2GTP header */
  65. init_appHandSerializer(&appHandService,bytes,string,MAX_STREAM_SIZE, V2GTP_HEADER_LENGTH);
  66. init_EXIDocumentType_appHand(&exiDoc);
  67. printf("EV side: setup data for the supported application handshake request message\n");
  68. /* set up ISO/IEC 15118 Version 1.0 information */
  69. length = writeStringToEXIString("urn:iso:15118:2:2010:MsgDef", handshake.AppProtocol[0].ProtocolNamespace.data);
  70. handshake.AppProtocol[0].ProtocolNamespace.arraylen.data = length; /* length of the string */
  71. handshake.AppProtocol[0].SchemaID=1;
  72. handshake.AppProtocol[0].VersionNumberMajor=1;
  73. handshake.AppProtocol[0].VersionNumberMinor=0;
  74. handshake.AppProtocol[0].Priority=1;
  75. handshake.arraylen.AppProtocol=1; /* we have only one protocol implemented */
  76. /* assign handshake request structure to the exiDoc and signal it */
  77. exiDoc.supportedAppProtocolReq = &handshake;
  78. exiDoc.isused.supportedAppProtocolReq=1;
  79. payloadLength=0;
  80. if(serialize_appHand(&appHandService, outStream,&payloadLength, &exiDoc))
  81. {
  82. /* an error occurred */
  83. return -1;
  84. }
  85. printf("EV side: send message to the EVSE \n");
  86. /* Use here your sending / receiving mechanism to / from the EVSE. The following serviceDataTransmitter method
  87. * is only an exemplary implementation which also shows how to add the V2GTP header information to
  88. * the output stream.
  89. * */
  90. serviceDataTransmitter(outStream, payloadLength, inStream);
  91. /* Init deserializer
  92. * Provide here also the offset of the transport protocol */
  93. init_appHandDeserializer(&appHandService,bytes,string,V2GTP_HEADER_LENGTH);
  94. init_EXIDocumentType_appHand(&exiDoc);
  95. exiDoc.supportedAppProtocolRes=&resultHandshake;
  96. exiDoc.isused.supportedAppProtocolRes=1;
  97. if(deserialize_appHand(&appHandService,inStream,100,&exiDoc))
  98. {
  99. /* an error occurred */
  100. return -1;
  101. }
  102. printf("EV side: Response of the EVSE \n");
  103. if(resultHandshake.ResponseCode==OK_SuccessfulNegotiation_responseCodeType)
  104. {
  105. printf("\t\tResponseCode=OK_SuccessfulNegotiation\n");
  106. printf("\t\tSchemaID=%d\n",resultHandshake.SchemaID );
  107. }
  108. return 0;
  109. }
  110. static int ac_charging()
  111. {
  112. static uint8_t byte_array[MAX_BYTE_SIZE]; /* define MAX_BYTE_SIZE before*/
  113. static uint32_t string_array[MAX_STRING_SIZE]; /* define MAX_STRING_SIZE before*/
  114. /* define in and out byte stream */
  115. uint8_t inStream[MAX_STREAM_SIZE]; /* define MAX_STREAM_SIZE before */
  116. uint8_t outStream[MAX_STREAM_SIZE]; /* define MAX_STREAM_SIZE before */
  117. /* define offset variable for transport header data */
  118. uint16_t transportHeaderOffset;
  119. /* service data structure for AC*/
  120. struct EXIService service;
  121. struct MessageHeaderType v2gHeader;
  122. struct SessionSetupReqType sessionSetup;
  123. struct SessionSetupResType resultSessionSetup;
  124. struct ServiceDiscoveryReqType serviceDiscovery;
  125. struct ServiceDiscoveryResType resultServiceDiscovery;
  126. struct ServicePaymentSelectionReqType servicePayment;
  127. struct ServicePaymentSelectionResType resultServicePayment;
  128. struct ChargeParameterDiscoveryReqType powerDiscovery;
  129. struct ChargeParameterDiscoveryResType resultPowerDiscovery;
  130. struct PowerDeliveryReqType powerDelivery;
  131. struct PowerDeliveryResType resultPowerDelivery;
  132. struct ChargingStatusResType resultChargingStatus;
  133. struct SessionStopResType resultSessionStop;
  134. struct AC_EVSEStatusType evseStatus;
  135. struct AC_EVChargeParameterType EVChargeParameter;
  136. struct AC_EVSEChargeParameterType evseChargeParameter;
  137. struct SAScheduleListType scheduleInfo;
  138. struct SalesTariffType sales;
  139. struct PhysicalValueType float_type;
  140. enum responseMessages resMsg;
  141. uint32_t outPayloadLength;
  142. /* BINARY memory setup */
  143. bytes_t bytes = { MAX_BYTE_SIZE, byte_array, 0 };
  144. /* STRING memory setup */
  145. string_ucs_t string = { MAX_STRING_SIZE, string_array, 0 };
  146. /* setup offset for DoIP header (otherwise set
  147. * transportHeaderOffset=0 if no transfer protocol is used)*/
  148. transportHeaderOffset = V2GTP_HEADER_LENGTH;
  149. /*******************
  150. * Init V2G Client *
  151. *******************/
  152. init_v2gServiceClient(&service,bytes,string,inStream,MAX_STREAM_SIZE, outStream, MAX_STREAM_SIZE, &outPayloadLength, transportHeaderOffset);
  153. /*******************************
  154. * Setup data for sessionSetup *
  155. *******************************/
  156. /* setup header information */
  157. v2gHeader.SessionID.data[0] = 0; /* sessionID is always '0' at the beginning (the response contains the valid sessionID)*/
  158. v2gHeader.SessionID.data[1] = 0;
  159. v2gHeader.SessionID.data[2] = 0;
  160. v2gHeader.SessionID.data[3] = 0;
  161. v2gHeader.SessionID.data[4] = 0;
  162. v2gHeader.SessionID.data[5] = 0;
  163. v2gHeader.SessionID.data[6] = 0;
  164. v2gHeader.SessionID.data[7] = 0;
  165. v2gHeader.SessionID.arraylen.data = 8; /* length of the byte session array is always 8*/
  166. v2gHeader.isused.Notification=0; /* no notification */
  167. v2gHeader.isused.Signature=0; /* no security */
  168. /* setup sessionSetup parameter */
  169. sessionSetup.EVCCID.data[0]=1;
  170. sessionSetup.EVCCID.arraylen.data=1;
  171. /************************
  172. * Prepare sessionSetup *
  173. ************************/
  174. prepare_sessionSetup(&service,&v2gHeader, &sessionSetup,&resultSessionSetup);
  175. printf("EV side: call EVSE sessionSetup\n");
  176. /* Use here your sending / receiving mechanism to / from the EVSE. The following serviceDataTransmitter method
  177. * is only an exemplary implementation which also shows how to add the V2GTP header information to
  178. * the output stream.
  179. * */
  180. serviceDataTransmitter(outStream, outPayloadLength, inStream);
  181. /* this method deserializes the response EXI stream */
  182. if( determineResponseMesssage(&service, &resMsg))
  183. {
  184. printErrorMessage(&service);
  185. }
  186. /* check, if this is the sessionSetup response message */
  187. if(resMsg==SESSIONSETUPRES)
  188. {
  189. /* show result of the answer message of EVSE sessionSetup */
  190. printf("EV side: received response message from EVSE\n");
  191. printf("\tHeader SessionID=");
  192. printBinaryArray(v2gHeader.SessionID.data,v2gHeader.SessionID.arraylen.data );
  193. printf("\tResponseCode=%d\n",resultSessionSetup.ResponseCode);
  194. printf("\tEVSEID=%d\n", resultSessionSetup.EVSEID.data[0]);
  195. printf("\tDateTimeNow=%d\n",resultSessionSetup.DateTimeNow);
  196. }
  197. /*******************************************
  198. * Setup data for serviceDiscovery *
  199. *******************************************/
  200. serviceDiscovery.isused.ServiceCategory=1;
  201. serviceDiscovery.ServiceCategory = EVCharging_serviceCategoryType;
  202. serviceDiscovery.isused.ServiceScope=0;
  203. /****************************
  204. * Prepare serviceDiscovery *
  205. ****************************/
  206. prepare_serviceDiscovery(&service,&v2gHeader, &serviceDiscovery,&resultServiceDiscovery);
  207. printf("EV side: call EVSE serviceDiscovery \n");
  208. /* Use here your sending / receiving mechanism to / from the EVSE. The following serviceDataTransmitter method
  209. * is only an exemplary implementation which also shows how to add the V2GTP header information to
  210. * the output stream.
  211. * */
  212. serviceDataTransmitter(outStream, outPayloadLength, inStream);
  213. /* this methods deserialize the response EXI stream and determines the kind of
  214. * the response message */
  215. if(determineResponseMesssage(&service, &resMsg))
  216. {
  217. printErrorMessage(&service);
  218. }
  219. /* check, if this is the serviceDiscovery response message */
  220. if(resMsg==SERVICEDISCOVERYRES)
  221. {
  222. /* show result of the answer message of EVSE serviceDiscovery */
  223. printf("EV side: received response message from EVSE\n");
  224. printf("\tHeader SessionID=");
  225. printBinaryArray(v2gHeader.SessionID.data,v2gHeader.SessionID.arraylen.data );
  226. printf("\t ResponseCode=%d\n",resultServiceDiscovery.ResponseCode);
  227. printf("\t ServiceID=%d\n", resultServiceDiscovery.ChargeService.ServiceTag.ServiceID);
  228. printf("\t ServiceName=");
  229. printASCIIString(resultServiceDiscovery.ChargeService.ServiceTag.ServiceName.data,(uint32_t)resultServiceDiscovery.ChargeService.ServiceTag.ServiceName.arraylen.data );
  230. printf("\t PaymentOption=%d\n", resultServiceDiscovery.PaymentOptions.PaymentOption[0]);
  231. printf("\t EnergyTransferType=%d\n", resultServiceDiscovery.ChargeService.EnergyTransferType);
  232. }
  233. /*******************************************
  234. * Setup data for ServicePaymentSelection *
  235. *******************************************/
  236. servicePayment.SelectedPaymentOption = ExternalPayment_paymentOptionType;
  237. servicePayment.SelectedServiceList.SelectedService[0].ServiceID=1; /* charge server ID */
  238. servicePayment.SelectedServiceList.SelectedService[0].isused.ParameterSetID=0; /* is not used */
  239. servicePayment.SelectedServiceList.arraylen.SelectedService=1; /* only one service was selected */
  240. /***********************************
  241. * Prepare ServicePaymentSelection *
  242. ***********************************/
  243. if(prepare_servicePaymentSelection(&service,&v2gHeader, &servicePayment,&resultServicePayment))
  244. {
  245. printErrorMessage(&service);
  246. return 0;
  247. }
  248. printf("EV side: call EVSE ServicePaymentSelection \n");
  249. /* Use here your sending / receiving mechanism to / from the EVSE. The following serviceDataTransmitter method
  250. * is only an exemplary implementation which also shows how to add the V2GTP header information to
  251. * the output stream.
  252. * */
  253. serviceDataTransmitter(outStream, outPayloadLength, inStream);
  254. /* this methods deserialize the response EXI stream and determines the kind of
  255. * the response message */
  256. if(determineResponseMesssage(&service, &resMsg))
  257. {
  258. printErrorMessage(&service);
  259. }
  260. /* check, if this is the servicePaymentSelection response message */
  261. if(resMsg==SERVICEPAYMENTSELECTIONRES)
  262. {
  263. /* show result of the answer message of EVSE servicePaymentSelection */
  264. printf("EV side: received response message from EVSE\n");
  265. printf("\tHeader SessionID=");
  266. printBinaryArray(v2gHeader.SessionID.data,v2gHeader.SessionID.arraylen.data );
  267. printf("\t ResponseCode=%d\n",resultServicePayment.ResponseCode);
  268. }
  269. /*******************************************
  270. * Setup data for chargeParameterDiscovery *
  271. *******************************************/
  272. printf("\n\nEV side: prepare EVSE chargeParameterDiscovery\n");
  273. powerDiscovery.EVRequestedEnergyTransferType = AC_three_phase_core_EVRequestedEnergyTransferType;
  274. EVChargeParameter.DepartureTime = 12345;
  275. float_type.Multiplier = 0;
  276. float_type.Unit = W_unitSymbolType;
  277. float_type.isused.Unit=1;
  278. float_type.Value = 100;
  279. EVChargeParameter.EAmount = float_type;
  280. float_type.Unit = A_unitSymbolType;
  281. float_type.Value = 200;
  282. EVChargeParameter.EVMaxCurrent= float_type;
  283. float_type.Unit = V_unitSymbolType;
  284. float_type.Value = 400;
  285. EVChargeParameter.EVMaxVoltage=float_type;
  286. float_type.Unit = A_unitSymbolType;
  287. float_type.Value = 500;
  288. EVChargeParameter.EVMinCurrent=float_type;
  289. powerDiscovery.AC_EVChargeParameter = &EVChargeParameter;
  290. powerDiscovery.isused.AC_EVChargeParameter = 1; /* we use here DC based charging parameters */
  291. powerDiscovery.isused.DC_EVChargeParameter = 0;
  292. resultPowerDiscovery.AC_EVSEChargeParameter = &evseChargeParameter; /* we expect AC-based parameters from the evse*/
  293. resultPowerDiscovery.SAScheduleList = &scheduleInfo; /* EVSE may send a schedule for us; should be always assigned here! */
  294. resultPowerDiscovery.SAScheduleList->SAScheduleTuple[0].SalesTariff = &sales;
  295. prepare_chargeParameterDiscovery(&service,&v2gHeader,&powerDiscovery,&resultPowerDiscovery);
  296. printf("EV side: call EVSE chargeParameterDiscovery \n");
  297. /* Use here your sending / receiving mechanism to / from the EVSE. The following serviceDataTransmitter method
  298. * is only an exemplary implementation which also shows how to add the V2GTP header information to
  299. * the output stream.
  300. * */
  301. serviceDataTransmitter(outStream, outPayloadLength, inStream);
  302. /* this methods deserialize the response EXI stream and determines the kind of
  303. * the response message */
  304. if(determineResponseMesssage(&service, &resMsg))
  305. {
  306. printErrorMessage(&service);
  307. }
  308. /* check, if this is the chargeParameterDiscovery response message */
  309. if(resMsg==CHARGEPARAMETERDISCOVERYRES)
  310. {
  311. /* show result of the answer message of EVSE sessionSetup*/
  312. printf("EV side: received response message from EVSE\n");
  313. printf("\tHeader SessionID=");
  314. printBinaryArray(v2gHeader.SessionID.data,v2gHeader.SessionID.arraylen.data );
  315. printf("\tResponseCode=%d\n",resultPowerDiscovery.ResponseCode);
  316. printACEVSEStatus(&(resultPowerDiscovery.AC_EVSEChargeParameter->AC_EVSEStatus));
  317. printf("\t EVSEMaxCurrent=%d\n",resultPowerDiscovery.AC_EVSEChargeParameter->EVSEMaxCurrent.Value);
  318. printf("\t EVSEMaxVoltage=%d\n",resultPowerDiscovery.AC_EVSEChargeParameter->EVSEMaxVoltage.Value);
  319. printf("\t EVSEMinimumCurrentLimit=%d\n",resultPowerDiscovery.AC_EVSEChargeParameter->EVSEMinCurrent.Value);
  320. }
  321. /*********************************
  322. * Setup data for powerDelivery *
  323. *********************************/
  324. powerDelivery.ReadyToChargeState = 1;
  325. powerDelivery.isused.ChargingProfile= 0;
  326. powerDelivery.isused.DC_EVPowerDeliveryParameter=0; /* only used for DC charging */
  327. resultPowerDelivery.AC_EVSEStatus = &evseStatus; /* we expect an evse status */
  328. prepare_powerDelivery(&service,&v2gHeader,&powerDelivery,&resultPowerDelivery);
  329. printf("EV side: call EVSE powerDelivery \n");
  330. /* Use here your sending / receiving mechanism to / from the EVSE. The following serviceDataTransmitter method
  331. * is only an exemplary implementation which also shows how to add the V2GTP header information to
  332. * the output stream.
  333. * */
  334. serviceDataTransmitter(outStream, outPayloadLength, inStream);
  335. /* this methods deserialize the response EXI stream and determines the kind of
  336. * the response message */
  337. if(determineResponseMesssage(&service, &resMsg))
  338. {
  339. printErrorMessage(&service);
  340. }
  341. /* check, if this is the powerDelivery response message */
  342. if(resMsg==POWERDELIVERYRES)
  343. {
  344. /* show result of the answer message of EVSE sessionSetup*/
  345. printf("EV side: received response message from EVSE\n");
  346. printf("\tResponseCode=%d\n",resultPowerDelivery.ResponseCode);
  347. printACEVSEStatus(&evseStatus);
  348. }
  349. /*********************************
  350. * Setup data for chargingStatus *
  351. *********************************/
  352. /***************************
  353. * Prepare chargingStatus *
  354. ***************************/
  355. if(prepare_chargingStatus(&service,&v2gHeader,&resultChargingStatus))
  356. {
  357. printErrorMessage(&service);
  358. return 0; /* stop here */
  359. }
  360. printf("EV side: call EVSE chargingStatus \n");
  361. /* Use here your sending / receiving mechanism to / from the EVSE. The following serviceDataTransmitter method
  362. * is only an exemplary implementation which also shows how to add the V2GTP header information to
  363. * the output stream.
  364. * */
  365. serviceDataTransmitter(outStream, outPayloadLength, inStream);
  366. /* this methods deserialize the response EXI stream and determines the kind of
  367. * the response message */
  368. if(determineResponseMesssage(&service, &resMsg))
  369. {
  370. printErrorMessage(&service);
  371. }
  372. /* check, if this is the chargingStatus response message */
  373. if(resMsg==CHARGINGSTATUSRES)
  374. {
  375. /* show result of the answer message of EVSE sessionSetup*/
  376. printf("EV side: received response message from EVSE\n");
  377. /* show result of the answer message of EVSE powerDiscovery*/
  378. printf("\tResponseCode=%d\n",resultChargingStatus.ResponseCode);
  379. printACEVSEStatus(&evseStatus);
  380. printf("\tReceiptRequired=%d\n",resultChargingStatus.ReceiptRequired);
  381. printf("\tEVSEID=%d\n",resultChargingStatus.EVSEID.data[0]);
  382. printf("\tEVSEMaxCurrent=%d\n",resultChargingStatus.EVSEMaxCurrent.Value);
  383. printf("\tisused.MeterInfo=%d\n", resultChargingStatus.isused.MeterInfo);
  384. printf("\t\tMeterInfo.MeterID=%d\n", resultChargingStatus.MeterInfo.MeterID.data[0]);
  385. printf("\t\tMeterInfo.MeterReading.Value=%d\n", resultChargingStatus.MeterInfo.MeterReading.Value);
  386. printf("\t\tMeterInfo.MeterStatus=%d\n", resultChargingStatus.MeterInfo.MeterStatus);
  387. printf("\t\tMeterInfo.TMeter=%d\n", resultChargingStatus.MeterInfo.TMeter);
  388. }
  389. /***********************************
  390. * Setup data for stopSession *
  391. ***********************************/
  392. /************************
  393. * Prepare stopSession *
  394. ************************/
  395. if(prepare_sessionStop(&service,&v2gHeader,&resultSessionStop))
  396. {
  397. printErrorMessage(&service);
  398. return 0; /* stop here */
  399. }
  400. printf("EV side: call EVSE stopSession \n");
  401. /* Use here your sending / receiving mechanism to / from the EVSE. The following serviceDataTransmitter method
  402. * is only an exemplary implementation which also shows how to add the V2GTP header information to
  403. * the output stream.
  404. * */
  405. serviceDataTransmitter(outStream, outPayloadLength, inStream);
  406. /* this methods deserialize the response EXI stream and determines the kind of
  407. * the response message */
  408. if(determineResponseMesssage(&service, &resMsg))
  409. {
  410. printErrorMessage(&service);
  411. }
  412. /* check, if this is the stopSession response message */
  413. if(resMsg==SESSIONSTOPRES)
  414. {
  415. /* show result of the answer message of EVSE sessionSetup*/
  416. printf("EV side: received response message from EVSE\n");
  417. /* show result of the answer message of EVSE powerDiscovery*/
  418. printf("\tResponseCode=%d\n",resultSessionStop.ResponseCode);
  419. }
  420. return 0;
  421. }
  422. static int dc_charging()
  423. {
  424. static uint8_t byte_array[MAX_BYTE_SIZE]; /* define MAX_BYTE_SIZE before*/
  425. static uint32_t string_array[MAX_STRING_SIZE]; /* define MAX_STRING_SIZE before*/
  426. /* define in and out byte stream */
  427. uint8_t inStream[MAX_STREAM_SIZE]; /* define MAX_STREAM_SIZE before */
  428. uint8_t outStream[MAX_STREAM_SIZE]; /* define MAX_STREAM_SIZE before */
  429. /* define offset variable for transport header data */
  430. uint16_t transportHeaderOffset;
  431. /* service data structure for DC*/
  432. struct EXIService service;
  433. struct MessageHeaderType v2gHeader;
  434. struct SessionSetupReqType sessionSetup;
  435. struct SessionSetupResType resultSessionSetup;
  436. struct ServiceDiscoveryReqType serviceDiscovery;
  437. struct ServiceDiscoveryResType resultServiceDiscovery;
  438. struct ServicePaymentSelectionReqType servicePayment;
  439. struct ServicePaymentSelectionResType resultServicePayment;
  440. struct ChargeParameterDiscoveryReqType powerDiscovery;
  441. struct ChargeParameterDiscoveryResType resultPowerDiscovery;
  442. struct CableCheckReqType cableCheck;
  443. struct CableCheckResType resultCableCheck;
  444. struct PowerDeliveryReqType powerDelivery;
  445. struct PowerDeliveryResType resultPowerDelivery;
  446. struct PreChargeReqType preCharge;
  447. struct PreChargeResType resultPreCharge;
  448. struct CurrentDemandReqType currentDemand;
  449. struct CurrentDemandResType resultCurrentDemand;
  450. struct WeldingDetectionReqType weldingDetection;
  451. struct WeldingDetectionResType resultWeldingDetection;
  452. struct SessionStopResType resultSessionStop;
  453. struct DC_EVStatusType EVStatus;
  454. struct DC_EVSEStatusType evseStatus;
  455. struct DC_EVChargeParameterType EVChargeParameter;
  456. struct DC_EVSEChargeParameterType evseChargeParameter;
  457. struct DC_EVPowerDeliveryParameterType EVPowerDelivery;
  458. struct SAScheduleListType pmaxScheduleList;
  459. enum responseMessages resMsg;
  460. struct PhysicalValueType float_type;
  461. uint32_t outPayloadLength;
  462. size_t i, j;
  463. /* BINARY memory setup */
  464. bytes_t bytes = { MAX_BYTE_SIZE, byte_array, 0 };
  465. /* STRING memory setup */
  466. string_ucs_t string = { MAX_STRING_SIZE, string_array, 0 };
  467. /* setup offset for DoIP header (otherwise set
  468. * transportHeaderOffset=0 if no transfer protocol is used)*/
  469. transportHeaderOffset = V2GTP_HEADER_LENGTH;
  470. /*******************
  471. * Init V2G Client *
  472. *******************/
  473. init_v2gServiceClient(&service,bytes,string,inStream,MAX_STREAM_SIZE, outStream, MAX_STREAM_SIZE, &outPayloadLength, transportHeaderOffset);
  474. /*******************************
  475. * Setup data for sessionSetup *
  476. *******************************/
  477. /* setup header information */
  478. v2gHeader.SessionID.data[0] = 0; /* sessionID is always '0' at the beginning (the response message contains the valid sessionID)*/
  479. v2gHeader.SessionID.data[1] = 0;
  480. v2gHeader.SessionID.data[2] = 0;
  481. v2gHeader.SessionID.data[3] = 0;
  482. v2gHeader.SessionID.data[4] = 0;
  483. v2gHeader.SessionID.data[5] = 0;
  484. v2gHeader.SessionID.data[6] = 0;
  485. v2gHeader.SessionID.data[7] = 0;
  486. v2gHeader.SessionID.arraylen.data = 8; /* length of the byte session array is always 8*/
  487. v2gHeader.isused.Notification=0; /* no notification */
  488. v2gHeader.isused.Signature=0; /* no security */
  489. /* setup sessionSetup parameter */
  490. sessionSetup.EVCCID.data[0]=10;
  491. sessionSetup.EVCCID.arraylen.data=1;
  492. printf("EV side: prepare EVSE sessionSetup\n");
  493. /************************
  494. * Prepare sessionSetup *
  495. ************************/
  496. prepare_sessionSetup(&service,&v2gHeader, &sessionSetup,&resultSessionSetup);
  497. printf("EV side: call EVSE sessionSetup\n");
  498. /* Use here your sending / receiving mechanism to / from the EVSE. The following serviceDataTransmitter method
  499. * is only an exemplary implementation which also shows how to add the V2GTP header information to
  500. * the output stream.
  501. * */
  502. serviceDataTransmitter(outStream, outPayloadLength, inStream);
  503. /* this methods deserialize the response EXI stream */
  504. if(determineResponseMesssage(&service, &resMsg))
  505. {
  506. printErrorMessage(&service);
  507. }
  508. /* check, if this is the sessionSetup response message */
  509. if(resMsg==SESSIONSETUPRES)
  510. {
  511. /* show result of the answer message of EVSE sessionSetup */
  512. printf("EV: received response message from EVSE\n");
  513. printf("\tHeader SessionID=");
  514. printBinaryArray(v2gHeader.SessionID.data,v2gHeader.SessionID.arraylen.data );
  515. printf("\tResponseCode=%d\n",resultSessionSetup.ResponseCode);
  516. printf("\tEVSEID=%d\n", resultSessionSetup.EVSEID.data[0]);
  517. printf("\tDateTimeNow=%d\n",resultSessionSetup.DateTimeNow);
  518. }
  519. /*******************************************
  520. * Setup data for serviceDiscovery *
  521. *******************************************/
  522. serviceDiscovery.isused.ServiceCategory=1;
  523. /* we are only interested in charging */
  524. serviceDiscovery.ServiceCategory = EVCharging_serviceCategoryType;
  525. serviceDiscovery.isused.ServiceScope=0;
  526. printf("\n\nEV side: prepare EVSE serviceDiscovery\n");
  527. /****************************
  528. * Prepare serviceDiscovery *
  529. ****************************/
  530. prepare_serviceDiscovery(&service,&v2gHeader, &serviceDiscovery,&resultServiceDiscovery);
  531. printf("EV side: call EVSE serviceDiscovery \n");
  532. /* Use here your sending / receiving mechanism to / from the EVSE. The following serviceDataTransmitter method
  533. * is only an exemplary implementation which also shows how to add the V2GTP header information to
  534. * the output stream.
  535. * */
  536. serviceDataTransmitter(outStream, outPayloadLength, inStream);
  537. /* this methods deserialize the response EXI stream and determines the kind of
  538. * the response message */
  539. if(determineResponseMesssage(&service, &resMsg))
  540. {
  541. printErrorMessage(&service);
  542. }
  543. /* check, if this is the serviceDiscovery response message */
  544. if(resMsg==SERVICEDISCOVERYRES)
  545. {
  546. /* show result of the answer message of EVSE sessionSetup */
  547. printf("\nEV side: received response message from EVSE\n");
  548. printf("\tHeader SessionID=");
  549. printBinaryArray(v2gHeader.SessionID.data,v2gHeader.SessionID.arraylen.data );
  550. printf("\t ResponseCode=%d\n",resultServiceDiscovery.ResponseCode);
  551. printf("\t ServiceID=%d\n", resultServiceDiscovery.ChargeService.ServiceTag.ServiceID);
  552. printf("\t ServiceName=");
  553. printASCIIString(resultServiceDiscovery.ChargeService.ServiceTag.ServiceName.data,(uint32_t)resultServiceDiscovery.ChargeService.ServiceTag.ServiceName.arraylen.data );
  554. printf("\t PaymentOption=%d\n", resultServiceDiscovery.PaymentOptions.PaymentOption[0]);
  555. printf("\t EnergyTransferType=%d\n", resultServiceDiscovery.ChargeService.EnergyTransferType);
  556. }
  557. /*******************************************
  558. * Setup data for ServicePaymentSelection *
  559. *******************************************/
  560. servicePayment.SelectedPaymentOption = ExternalPayment_paymentOptionType;
  561. servicePayment.SelectedServiceList.SelectedService[0].ServiceID=1; /* charge server ID */
  562. servicePayment.SelectedServiceList.SelectedService[0].isused.ParameterSetID=0; /* is not used */
  563. servicePayment.SelectedServiceList.arraylen.SelectedService=1; /* only one service was selected */
  564. printf("\n\nEV side: prepare EVSE servicePaymentSelection\n");
  565. /**************************************
  566. * Prepare ServicePaymentSelection *
  567. **************************************/
  568. if(prepare_servicePaymentSelection(&service,&v2gHeader, &servicePayment,&resultServicePayment))
  569. {
  570. printErrorMessage(&service);
  571. return 0;
  572. }
  573. printf("EV side: call EVSE ServicePaymentSelection \n");
  574. /* Use here your sending / receiving mechanism to / from the EVSE. The following serviceDataTransmitter method
  575. * is only an exemplary implementation which also shows how to add the V2GTP header information to
  576. * the output stream.
  577. * */
  578. serviceDataTransmitter(outStream, outPayloadLength, inStream);
  579. /* this methods deserialize the response EXI stream and determines the kind of
  580. * the response message */
  581. if(determineResponseMesssage(&service, &resMsg))
  582. {
  583. printErrorMessage(&service);
  584. }
  585. /* check, if this is the servicePaymentSelection response message */
  586. if(resMsg==SERVICEPAYMENTSELECTIONRES)
  587. {
  588. /* show result of the answer message of EVSE sessionSetup */
  589. printf("EV: received response message from EVSE\n");
  590. printf("\tHeader SessionID=");
  591. printBinaryArray(v2gHeader.SessionID.data,v2gHeader.SessionID.arraylen.data );
  592. printf("\t ResponseCode=%d\n",resultServicePayment.ResponseCode);
  593. }
  594. /*******************************************
  595. * Setup data for chargeParameterDiscovery *
  596. *******************************************/
  597. /* setup EVStatus */
  598. EVStatus.EVRESSSOC = 30;
  599. EVStatus.EVReady = 1;
  600. EVStatus.EVCabinConditioning = 1;
  601. EVStatus.EVRESSConditioning = 1;
  602. EVStatus.isused.EVCabinConditioning=1;
  603. EVStatus.isused.EVRESSConditioning=1;
  604. EVStatus.EVErrorCode = NO_ERROR_DC_EVErrorCodeType;
  605. EVChargeParameter.DC_EVStatus = EVStatus;
  606. float_type.Multiplier = 0;
  607. float_type.Unit = A_unitSymbolType;
  608. float_type.isused.Unit=1;
  609. float_type.Value = 60;
  610. EVChargeParameter.EVMaximumCurrentLimit = float_type;
  611. float_type.Unit = W_unitSymbolType;
  612. float_type.Value = 20000;
  613. EVChargeParameter.EVMaximumPowerLimit = float_type;
  614. EVChargeParameter.isused.EVMaximumPowerLimit = 1;
  615. float_type.Unit = V_unitSymbolType;
  616. float_type.Value = 420;
  617. EVChargeParameter.EVMaximumVoltageLimit= float_type;
  618. float_type.Unit = W_s_unitSymbolType;
  619. float_type.Value = 15000;
  620. EVChargeParameter.EVEnergyCapacity= float_type;
  621. EVChargeParameter.isused.EVEnergyCapacity = 1;
  622. float_type.Unit = W_s_unitSymbolType;
  623. float_type.Value = 5000;
  624. EVChargeParameter.EVEnergyRequest= float_type;
  625. EVChargeParameter.isused.EVEnergyRequest = 1;
  626. EVChargeParameter.FullSOC=99;
  627. EVChargeParameter.isused.FullSOC = 1;
  628. EVChargeParameter.BulkSOC=80;
  629. EVChargeParameter.isused.BulkSOC = 1;
  630. powerDiscovery.EVRequestedEnergyTransferType = DC_combo_core_EVRequestedEnergyTransferType;
  631. powerDiscovery.DC_EVChargeParameter = &EVChargeParameter;
  632. powerDiscovery.isused.DC_EVChargeParameter = 1; /* we use here DC based charging parameters */
  633. powerDiscovery.isused.AC_EVChargeParameter = 0;
  634. resultPowerDiscovery.DC_EVSEChargeParameter = &evseChargeParameter; /* we expect DC-based parameters from the evse*/
  635. resultPowerDiscovery.SAScheduleList = &pmaxScheduleList; /* the EVSE can provide some PMax information; should be always assign here! */
  636. printf("\n\nEV side: prepare EVSE chargeParameterDiscovery\n");
  637. /************************************
  638. * Prepare chargeParameterDiscovery *
  639. ************************************/
  640. if(prepare_chargeParameterDiscovery(&service,&v2gHeader, &powerDiscovery,&resultPowerDiscovery))
  641. {
  642. printErrorMessage(&service);
  643. return 0;
  644. }
  645. printf("EV side: call EVSE chargeParameterDiscovery \n");
  646. /* Use here your sending / receiving mechanism to / from the EVSE. The following serviceDataTransmitter method
  647. * is only an exemplary implementation which also shows how to add the V2GTP header information to
  648. * the output stream.
  649. * */
  650. serviceDataTransmitter(outStream, outPayloadLength, inStream);
  651. /* this methods deserialize the response EXI stream and determines the kind of
  652. * the response message */
  653. if(determineResponseMesssage(&service, &resMsg))
  654. {
  655. printErrorMessage(&service);
  656. }
  657. /* check, if this is the chargeParameterDiscovery response message */
  658. if(resMsg==CHARGEPARAMETERDISCOVERYRES)
  659. {
  660. /* show result of the answer message of EVSE sessionSetup*/
  661. printf("\nEV side: received response message from EVSE\n");
  662. printf("\t\t Header SessionID=%d\n",v2gHeader.SessionID.data[0]);
  663. printf("\tResponseCode=%d\n",resultPowerDiscovery.ResponseCode);
  664. printDCEVSEStatus(&(resultPowerDiscovery.DC_EVSEChargeParameter->DC_EVSEStatus));
  665. printf("\tEVSEMaximumCurrentLimit=%d\n",resultPowerDiscovery.DC_EVSEChargeParameter->EVSEMaximumCurrentLimit.Value);
  666. printf("\tEVSEMaximumPowerLimit=%d\n",resultPowerDiscovery.DC_EVSEChargeParameter->EVSEMaximumPowerLimit.Value);
  667. printf("\tEVSEMaximumVoltageLimit=%d\n",resultPowerDiscovery.DC_EVSEChargeParameter->EVSEMaximumVoltageLimit.Value);
  668. printf("\tEVSEMinimumCurrentLimit=%d\n",resultPowerDiscovery.DC_EVSEChargeParameter->EVSEMinimumCurrentLimit.Value);
  669. printf("\tEVSEMinimumVoltageLimit=%d\n",resultPowerDiscovery.DC_EVSEChargeParameter->EVSEMinimumVoltageLimit.Value);
  670. printf("\tEVSECurrentRegulationTolerance=%d\n",resultPowerDiscovery.DC_EVSEChargeParameter->EVSECurrentRegulationTolerance.Value);
  671. printf("\tEVSEPeakCurrentRipple=%d\n",resultPowerDiscovery.DC_EVSEChargeParameter->EVSEPeakCurrentRipple.Value);
  672. printf("\tEVSEEnergyToBeDelivered=%d\n",resultPowerDiscovery.DC_EVSEChargeParameter->EVSEEnergyToBeDelivered.Value);
  673. /* show PMax schedule, if there one provided */
  674. if(resultPowerDiscovery.isused.SAScheduleList)
  675. {
  676. printf("\tSAScheduleList: \n");
  677. for(i=0; i< pmaxScheduleList.arraylen.SAScheduleTuple;i++)
  678. {
  679. printf("\t\t Tuple#%d: \n",(i+1));
  680. printf("\t\t SAScheduleTupleID=%d: \n", pmaxScheduleList.SAScheduleTuple[i].SAScheduleTupleID);
  681. printf("\t\t PMaxScheduleID=%d: \n",pmaxScheduleList.SAScheduleTuple[i].PMaxSchedule.PMaxScheduleID);
  682. for(j=0; j< pmaxScheduleList.SAScheduleTuple[i].PMaxSchedule.arraylen.PMaxScheduleEntry;j++)
  683. {
  684. printf("\t\t\t Entry#%d: \n",(j+1));
  685. printf("\t\t\t\t PMax=%d \n",pmaxScheduleList.SAScheduleTuple[i].PMaxSchedule.PMaxScheduleEntry[j].PMax);
  686. printf("\t\t\t\t Start=%d \n",pmaxScheduleList.SAScheduleTuple[i].PMaxSchedule.PMaxScheduleEntry[j].RelativeTimeInterval.start);
  687. if(pmaxScheduleList.SAScheduleTuple[i].PMaxSchedule.PMaxScheduleEntry[j].RelativeTimeInterval.isused.duration)
  688. printf("\t\t\t\t Duration=%d \n",pmaxScheduleList.SAScheduleTuple[i].PMaxSchedule.PMaxScheduleEntry[j].RelativeTimeInterval.duration);
  689. }
  690. }
  691. }
  692. }
  693. /*****************************
  694. * Setup data for cableCheck *
  695. *****************************/
  696. /* setup EVStatus */
  697. cableCheck.DC_EVStatus =EVStatus;
  698. printf("\n\nEV side: prepare EVSE cableCheck\n");
  699. /**********************
  700. * Prepare cableCheck *
  701. **********************/
  702. if(prepare_cableCheck(&service,&v2gHeader,&cableCheck,&resultCableCheck))
  703. {
  704. printErrorMessage(&service);
  705. return 0; /* stop here */
  706. }
  707. printf("EV side: call EVSE cableCheck \n");
  708. /* Use here your sending / receiving mechanism to / from the EVSE. The following serviceDataTransmitter method
  709. * is only an exemplary implementation which also shows how to add the V2GTP header information to
  710. * the output stream.
  711. * */
  712. serviceDataTransmitter(outStream, outPayloadLength, inStream);
  713. /* this methods deserialize the response EXI stream and determines the kind of
  714. * the response message */
  715. if(determineResponseMesssage(&service, &resMsg))
  716. {
  717. printErrorMessage(&service);
  718. }
  719. /* check, if this is the cableCheck response message */
  720. if(resMsg==CABLECHECKRES)
  721. {
  722. /* show result of the answer message of EVSE sessionSetup*/
  723. printf("EV side: received response message from EVSE\n");
  724. printf("\t\t Header SessionID=%d\n",v2gHeader.SessionID.data[0]);
  725. printf("\tResponseCode=%d\n",resultCableCheck.ResponseCode);
  726. printDCEVSEStatus(&(resultCableCheck.DC_EVSEStatus));
  727. }
  728. /*****************************
  729. * Setup data for preCharge *
  730. *****************************/
  731. /* setup EVStatus */
  732. preCharge.DC_EVStatus =EVStatus;
  733. float_type.Unit = V_unitSymbolType;
  734. float_type.Value = 100;
  735. preCharge.EVTargetCurrent = float_type;
  736. float_type.Unit = V_unitSymbolType;
  737. float_type.Value = 200;
  738. preCharge.EVTargetVoltage = float_type;
  739. printf("\n\nEV side: prepare EVSE preCharge\n");
  740. /**********************
  741. * Prepare preCharge *
  742. **********************/
  743. if(prepare_preCharge(&service,&v2gHeader,&preCharge,&resultPreCharge))
  744. {
  745. printErrorMessage(&service);
  746. return 0; /* stop here */
  747. }
  748. printf("EV side: call EVSE preCharge \n");
  749. /* Use here your sending / receiving mechanism to / from the EVSE. The following serviceDataTransmitter method
  750. * is only an exemplary implementation which also shows how to add the V2GTP header information to
  751. * the output stream.
  752. * */
  753. serviceDataTransmitter(outStream, outPayloadLength, inStream);
  754. /* this methods deserialize the response EXI stream and determines the kind of
  755. * the response message */
  756. if(determineResponseMesssage(&service, &resMsg))
  757. {
  758. printErrorMessage(&service);
  759. }
  760. /* check, if this is the preCharge response message */
  761. if(resMsg==PRECHARGERES)
  762. {
  763. /* show result of the answer message of EVSE sessionSetup*/
  764. printf("EV side: received response message from EVSE\n");
  765. /* show result of the answer message of EVSE powerDiscovery*/
  766. printf("\tResponseCode=%d\n",resultPreCharge.ResponseCode);
  767. printDCEVSEStatus(&resultPreCharge.DC_EVSEStatus);
  768. printf("\tEVSEPresentVoltage=%d\n",resultPreCharge.EVSEPresentVoltage.Value);
  769. }
  770. /*********************************
  771. * Setup data for powerDelivery *
  772. *********************************/
  773. powerDelivery.ReadyToChargeState = 1;
  774. EVPowerDelivery.DC_EVStatus = EVStatus;
  775. EVPowerDelivery.BulkChargingComplete = 1;
  776. EVPowerDelivery.isused.BulkChargingComplete = 1;
  777. EVPowerDelivery.ChargingComplete = 0;
  778. powerDelivery.DC_EVPowerDeliveryParameter = &EVPowerDelivery;
  779. powerDelivery.isused.DC_EVPowerDeliveryParameter = 1; /* DC parameters are send */
  780. /* we are using a charging profile */
  781. powerDelivery.isused.ChargingProfile=1;
  782. powerDelivery.ChargingProfile.SAScheduleTupleID = pmaxScheduleList.SAScheduleTuple[0].SAScheduleTupleID;
  783. /* set up 3 entries */
  784. powerDelivery.ChargingProfile.ProfileEntry[0].ChargingProfileEntryMaxPower=0;
  785. powerDelivery.ChargingProfile.ProfileEntry[0].ChargingProfileEntryStart=0;
  786. powerDelivery.ChargingProfile.ProfileEntry[1].ChargingProfileEntryMaxPower=20000;
  787. powerDelivery.ChargingProfile.ProfileEntry[1].ChargingProfileEntryStart=300; /* 5min */
  788. powerDelivery.ChargingProfile.ProfileEntry[2].ChargingProfileEntryMaxPower=0;
  789. powerDelivery.ChargingProfile.ProfileEntry[2].ChargingProfileEntryStart=1200; /* 20min */
  790. powerDelivery.ChargingProfile.arraylen.ProfileEntry=3;
  791. resultPowerDelivery.DC_EVSEStatus = &evseStatus; /* we expect the DC-based EVSE status */
  792. printf("\n\nEV side: prepare EVSE powerDelivery\n");
  793. /**************************
  794. * Prepare powerDelivery *
  795. **************************/
  796. if(prepare_powerDelivery(&service,&v2gHeader,&powerDelivery,&resultPowerDelivery))
  797. {
  798. printErrorMessage(&service);
  799. return 0; /* stop here */
  800. }
  801. printf("EV side: call EVSE powerDelivery \n");
  802. /* Use here your sending / receiving mechanism to / from the EVSE. The following serviceDataTransmitter method
  803. * is only an exemplary implementation which also shows how to add the V2GTP header information to
  804. * the output stream.
  805. * */
  806. serviceDataTransmitter(outStream, outPayloadLength, inStream);
  807. /* this methods deserialize the response EXI stream and determines the kind of
  808. * the response message */
  809. if(determineResponseMesssage(&service, &resMsg))
  810. {
  811. printErrorMessage(&service);
  812. }
  813. /* check, if this is the powerDelivery response message */
  814. if(resMsg==POWERDELIVERYRES)
  815. {
  816. /* show result of the answer message of EVSE sessionSetup*/
  817. printf("\nEV side: received response message from EVSE\n");
  818. /* show result of the answer message of EVSE powerDiscovery*/
  819. printf("\tResponseCode=%d\n",resultPreCharge.ResponseCode);
  820. printDCEVSEStatus(&resultPreCharge.DC_EVSEStatus);
  821. }
  822. /*********************************
  823. * Setup data for currentDemand *
  824. *********************************/
  825. currentDemand.DC_EVStatus = EVStatus;
  826. float_type.Unit = A_unitSymbolType;
  827. float_type.Value = 50;
  828. currentDemand.EVTargetCurrent = float_type;
  829. float_type.Unit = V_unitSymbolType;
  830. float_type.Value = 400;
  831. currentDemand.EVMaximumVoltageLimit = float_type;
  832. currentDemand.isused.EVMaximumVoltageLimit = 1;
  833. float_type.Unit = W_unitSymbolType;
  834. float_type.Value = 20000;
  835. currentDemand.EVMaximumPowerLimit = float_type;
  836. currentDemand.isused.EVMaximumPowerLimit = 1;
  837. float_type.Unit = A_unitSymbolType;
  838. float_type.Value = 50;
  839. currentDemand.EVMaximumCurrentLimit = float_type;
  840. currentDemand.isused.EVMaximumCurrentLimit = 1;
  841. currentDemand.BulkChargingComplete = 0;
  842. currentDemand.isused.BulkChargingComplete = 1;
  843. currentDemand.ChargingComplete = 0;
  844. /* float_type.Unit = s_unitSymbolType;
  845. float_type.Value = 1200;
  846. currentDemand.RemainingTimeToFullSoC = float_type; */
  847. currentDemand.isused.RemainingTimeToFullSoC = 0;
  848. /* float_type.Unit = s_unitSymbolType;
  849. float_type.Value = 1200;
  850. currentDemand.RemainingTimeToBulkSoC = float_type; */
  851. currentDemand.isused.RemainingTimeToBulkSoC = 0;
  852. float_type.Unit = V_unitSymbolType;
  853. float_type.Value = 400;
  854. currentDemand.EVTargetVoltage = float_type;
  855. printf("\n\nEV side: prepare EVSE currentDemand\n");
  856. /**************************
  857. * Prepare currentDemand *
  858. **************************/
  859. if(prepare_currentDemand(&service,&v2gHeader,&currentDemand,&resultCurrentDemand))
  860. {
  861. printErrorMessage(&service);
  862. return 0; /* stop here */
  863. }
  864. printf("EV side: call EVSE currentDemand \n");
  865. /* Use here your sending / receiving mechanism to / from the EVSE. The following serviceDataTransmitter method
  866. * is only an exemplary implementation which also shows how to add the V2GTP header information to
  867. * the output stream.
  868. * */
  869. serviceDataTransmitter(outStream, outPayloadLength, inStream);
  870. /* this methods deserialize the response EXI stream and determines the kind of
  871. * the response message */
  872. if(determineResponseMesssage(&service, &resMsg))
  873. {
  874. printErrorMessage(&service);
  875. }
  876. /* check, if this is the sessionSetup response message */
  877. if(resMsg==CURRENTDEMANDRES)
  878. {
  879. /* show result of the answer message of EVSE sessionSetup*/
  880. printf("\nEV side: received response message from EVSE\n");
  881. /* show result of the answer message of EVSE powerDiscovery*/
  882. printf("\tResponseCode=%d\n",resultCurrentDemand.ResponseCode);
  883. printDCEVSEStatus(&resultCurrentDemand.DC_EVSEStatus);
  884. printf("\t EVSEPresentVoltage=%d\n",resultCurrentDemand.EVSEPresentVoltage.Value);
  885. printf("\t EVSEPresentCurrent=%d\n",resultCurrentDemand.EVSEPresentCurrent.Value);
  886. printf("\t EVSECurrentLimitAchieved=%d\n",resultCurrentDemand.EVSECurrentLimitAchieved);
  887. printf("\t EVSEVoltageLimitAchieved=%d\n",resultCurrentDemand.EVSEVoltageLimitAchieved);
  888. printf("\t EVSEPowerLimitAchieved=%d\n",resultCurrentDemand.EVSEPowerLimitAchieved);
  889. printf("\t EVSEMaximumVoltageLimit=%d\n",resultCurrentDemand.EVSEMaximumVoltageLimit.Value);
  890. printf("\t EVSEMaximumCurrentLimit=%d\n",resultCurrentDemand.EVSEMaximumCurrentLimit.Value);
  891. printf("\t EVSEMaximumPowerLimit=%d\n",resultCurrentDemand.EVSEMaximumPowerLimit.Value);
  892. }
  893. /***********************************
  894. * Setup data for weldingDetection *
  895. ***********************************/
  896. weldingDetection.DC_EVStatus =EVStatus;
  897. printf("\n\nEV side: prepare EVSE weldingDetection\n");
  898. /**************************
  899. * Prepare weldingDetection *
  900. **************************/
  901. if(prepare_weldingDetection(&service,&v2gHeader,&weldingDetection,&resultWeldingDetection))
  902. {
  903. printErrorMessage(&service);
  904. return 0; /* stop here */
  905. }
  906. printf("EV side: call EVSE weldingDetection \n");
  907. /* Use here your sending / receiving mechanism to / from the EVSE. The following serviceDataTransmitter method
  908. * is only an exemplary implementation which also shows how to add the V2GTP header information to
  909. * the output stream.
  910. * */
  911. serviceDataTransmitter(outStream, outPayloadLength, inStream);
  912. /* this methods deserialize the response EXI stream and determines the kind of
  913. * the response message */
  914. if(determineResponseMesssage(&service, &resMsg))
  915. {
  916. printErrorMessage(&service);
  917. }
  918. /* check, if this is the sessionSetup response message */
  919. if(resMsg==WELDINGDETECTIONRES)
  920. {
  921. /* show result of the answer message of EVSE sessionSetup*/
  922. printf("EV side: received response message from EVSE\n");
  923. /* show result of the answer message of EVSE powerDiscovery*/
  924. printf("\tResponseCode=%d\n",resultCurrentDemand.ResponseCode);
  925. printDCEVSEStatus(&resultCurrentDemand.DC_EVSEStatus);
  926. printf("\tEVSEPresentVoltage=%d\n",resultWeldingDetection.EVSEPresentVoltage.Value);
  927. }
  928. /***********************************
  929. * Setup data for stopSession *
  930. ***********************************/
  931. printf("\n\nEV side: prepare EVSE stopSession\n");
  932. /************************
  933. * Prepare stopSession *
  934. ************************/
  935. if(prepare_sessionStop(&service,&v2gHeader,&resultSessionStop))
  936. {
  937. printErrorMessage(&service);
  938. return 0; /* stop here */
  939. }
  940. printf("EV side: call EVSE stopSession \n");
  941. /* Use here your sending / receiving mechanism to / from the EVSE. The following serviceDataTransmitter method
  942. * is only an exemplary implementation which also shows how to add the V2GTP header information to
  943. * the output stream.
  944. * */
  945. serviceDataTransmitter(outStream, outPayloadLength, inStream);
  946. /* this methods deserialize the response EXI stream and determines the kind of
  947. * the response message */
  948. if(determineResponseMesssage(&service, &resMsg))
  949. {
  950. printErrorMessage(&service);
  951. }
  952. /* check, if this is the sessionSetup response message */
  953. if(resMsg==SESSIONSTOPRES)
  954. {
  955. /* show result of the answer message of EVSE sessionSetup*/
  956. printf("EV side: received response message from EVSE\n");
  957. /* show result of the answer message of EVSE powerDiscovery*/
  958. printf("\tResponseCode=%d\n",resultCurrentDemand.ResponseCode);
  959. }
  960. return 0;
  961. }
  962. int main_service()
  963. {
  964. printf("+++ Start application handshake protocol example +++\n\n");
  965. appHandshake();
  966. printf("+++ Terminate application handshake protocol example +++\n\n");
  967. printf("\n\nPlease press enter for AC charging!\n");
  968. fflush(stdout);
  969. getchar();
  970. printf("+++ Start V2G client / service example for AC charging +++\n\n");
  971. ac_charging();
  972. printf("\n+++Terminate V2G Client / Service example for AC charging +++\n");
  973. printf("Please press enter for DC charging!\n");
  974. fflush(stdout);
  975. getchar();
  976. printf("+++ Start V2G client / service example for DC charging +++\n\n");
  977. dc_charging();
  978. printf("\n+++Terminate V2G client / service example for DC charging +++");
  979. return 0;
  980. }
  981. static void printACEVSEStatus(struct AC_EVSEStatusType* status)
  982. {
  983. printf("\tEVSEStatus:\n");
  984. printf("\t\tPowerSwitchClosed=%d\n",status->PowerSwitchClosed);
  985. printf("\t\tRCD=%d\n",status->RCD);
  986. printf("\t\tShutDownTime=%d\n",status->ShutDownTime);
  987. printf("\t\tStopCharging=%d\n",status->StopCharging);
  988. }
  989. static void printDCEVSEStatus(struct DC_EVSEStatusType* status)
  990. {
  991. if(status->isused.EVSEIsolationStatus)
  992. printf("\tEVSEStatus:\n\t\tEVSEIsolationStatus=%d\n",status->EVSEIsolationStatus);
  993. printf("\t\tEVSEStatusCode=%d\n",status->EVSEStatusCode);
  994. }
  995. static void printErrorMessage(struct EXIService* service)
  996. {
  997. if(service->errorCode==EXI_NON_VALID_MESSAGE)
  998. {
  999. printf("EV did not send a valid V2G message!\n");
  1000. }
  1001. else if(service->errorCode==EXI_SERIALIZATION_FAILED)
  1002. {
  1003. printf("EVSE error: Could not serialize the response message\n");
  1004. } else if(service->errorCode==EXI_SERIALIZATION_FAILED)
  1005. {
  1006. printf("EVSE error: Could not serialize the response message\n");
  1007. }
  1008. }
  1009. static void printASCIIString(uint32_t* string, uint32_t len) {
  1010. unsigned int i;
  1011. for(i=0; i<len; i++) {
  1012. printf("%c",(char)string[i]);
  1013. }
  1014. printf("\n");
  1015. }
  1016. static void printBinaryArray(uint8_t* byte, uint32_t len) {
  1017. unsigned int i;
  1018. for(i=0; i<len; i++) {
  1019. printf("%d ",byte[i]);
  1020. }
  1021. printf("\n");
  1022. }
  1023. static int writeStringToEXIString(char* string, uint32_t* exiString)
  1024. {
  1025. int pos=0;
  1026. while(string[pos]!='\0')
  1027. {
  1028. exiString[pos] = string[pos];
  1029. pos++;
  1030. }
  1031. return pos;
  1032. }