pev_service.c 51 KB

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