pev_service.c 55 KB

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