Module_Payment_Bazel8.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. /*
  2. * Module_Payment_Ominixpay.c
  3. *
  4. * Created on: 2022/04/29
  5. * Author: Folus Wen
  6. */
  7. #include "Module_Payment_Bazel8.h"
  8. struct COMMAND commandRaw;
  9. struct timespec tmr[TIMER_CNT];
  10. //==========================================
  11. // Common routine
  12. //==========================================
  13. int StoreLogMsg(const char *fmt, ...)
  14. {
  15. char Buf[65536+256];
  16. char buffer[65536];
  17. //char Buf[4096+256];
  18. //char buffer[4096];
  19. time_t CurrentTime;
  20. struct tm *tm;
  21. struct timeval tv;
  22. va_list args;
  23. va_start(args, fmt);
  24. int rc = vsnprintf(buffer, sizeof(buffer), fmt, args);
  25. va_end(args);
  26. memset(Buf,0,sizeof(Buf));
  27. CurrentTime = time(NULL);
  28. tm=localtime(&CurrentTime);
  29. gettimeofday(&tv, NULL); // get microseconds, 10^-6
  30. sprintf(Buf,"echo -n \"[%04d.%02d.%02d %02d:%02d:%02d.%06ld]%s\" >> /Storage/SystemLog/[%04d.%02d]PaymentLog",
  31. tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec,tv.tv_usec,
  32. buffer,
  33. tm->tm_year+1900,tm->tm_mon+1);
  34. system((const char*)Buf);
  35. #ifdef ConsloePrintLog
  36. printf("[%04d.%02d.%02d %02d:%02d:%02d.%06ld]%s", tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec,tv.tv_usec, buffer);
  37. #endif
  38. return rc;
  39. }
  40. /**
  41. * Execute shell command
  42. * @param cmd: shell command string
  43. * @return shell command execution result
  44. */
  45. int runShellCmd(const char*cmd)
  46. {
  47. int result = FAIL;
  48. char buf[256];
  49. FILE *fp;
  50. fp = popen(cmd, "r");
  51. if(fp != NULL)
  52. {
  53. while(fgets(buf, sizeof(buf), fp) != NULL)
  54. {
  55. DEBUG_INFO("%s\n", buf);
  56. }
  57. result = PASS;
  58. }
  59. pclose(fp);
  60. return result;
  61. }
  62. /**
  63. *
  64. * @param timer
  65. */
  66. void refreshStartTimer(struct timespec *timer)
  67. {
  68. clock_gettime(CLOCK_MONOTONIC, timer);
  69. }
  70. /**
  71. *
  72. * @param timer
  73. * @return
  74. */
  75. int getDiffSecNow(struct timespec timer)
  76. {
  77. struct timespec timerNow;
  78. clock_gettime(CLOCK_MONOTONIC, &timerNow);
  79. return (int)((((unsigned long)(timerNow.tv_sec - timer.tv_sec) * 1000) + ((unsigned long)((timerNow.tv_nsec / 1000000) - (timer.tv_nsec / 1000000))))/1000);
  80. }
  81. /**
  82. *
  83. * @param ST
  84. */
  85. long long DiffTimebWithNow(struct timeb ST)
  86. {
  87. //return milli-second
  88. struct timeb ET;
  89. long long StartTime,StopTime;
  90. ftime(&ET);
  91. StartTime=(long long)ST.time;
  92. StopTime=(long long)ET.time;
  93. return ((StopTime-StartTime)*1000) + (ET.millitm-ST.millitm);
  94. }
  95. /**
  96. *
  97. * @return
  98. */
  99. int getTimePassSinceToday()
  100. {
  101. int result = -1;
  102. static time_t lastTime;
  103. time_t t;
  104. struct tm *tmStartToday;
  105. struct timeb tbStartToday;
  106. t=time(NULL);
  107. if(difftime(t, lastTime)>0)
  108. {
  109. tmStartToday=localtime(&t);
  110. tmStartToday->tm_hour = 0;
  111. tmStartToday->tm_min = 0;
  112. tmStartToday->tm_sec = 0;
  113. tbStartToday.time = mktime(tmStartToday);
  114. tbStartToday.millitm = 0;
  115. result = DiffTimebWithNow(tbStartToday)/1000;
  116. lastTime = t;
  117. }
  118. return result;
  119. }
  120. /**
  121. * Calculate time differential
  122. * @param ST: start time
  123. * @param ET: end time
  124. * @return time differential in million seconds
  125. */
  126. int DiffTimeb(struct timeb ST, struct timeb ET)
  127. {
  128. //return milli-second
  129. unsigned int StartTime,StopTime;
  130. StartTime=(unsigned int)ST.time;
  131. StopTime=(unsigned int)ET.time;
  132. return (StopTime-StartTime)*1000+ET.millitm-ST.millitm;
  133. }
  134. /**
  135. * Show communication raw data to debug info
  136. * @param data: raw data
  137. * @param len: data length
  138. * @param isRX: is receive data
  139. */
  140. void show_raw(uint8_t *data, uint16_t len, uint8_t isRX)
  141. {
  142. uint8_t output[512]={0};
  143. if(isRX)
  144. DEBUG_INFO("RX ---------------------------------------------\n");
  145. else
  146. DEBUG_INFO("TX ---------------------------------------------\n");
  147. DEBUG_INFO(" 0 1 2 3 4 5 6 7 8 9 A B C D E F \n");
  148. DEBUG_INFO("------------------------------------------------\n");
  149. memset(output, 0x00, ARRAY_SIZE(output));
  150. for(int idx=0;idx<len;idx++)
  151. {
  152. if(strlen((char*)output)<48)
  153. sprintf((char*)output, "%s%02X ", output, data[idx]);
  154. else
  155. {
  156. DEBUG_INFO("%s\n", output);
  157. memset(output, 0x00, ARRAY_SIZE(output));
  158. sprintf((char*)output, "%s%02X ", output, data[idx]);
  159. }
  160. }
  161. DEBUG_INFO("%s\n", output);
  162. }
  163. /**
  164. *
  165. * @param dec: number in dec
  166. * @return number in bcd
  167. */
  168. int decTobcd(int dec)
  169. {
  170. return (dec/10 * 16)+ (dec%10);
  171. }
  172. /**
  173. *
  174. * @param data: message array
  175. * @param dataLen: command & data field length in array
  176. * @return check sum result
  177. */
  178. int calChksum(unsigned char *data)
  179. {
  180. int result = 0;
  181. for(uint16_t idx=0;idx<(((data[1] << 8) | (data[1]))+3);idx++)
  182. {
  183. result ^= data[idx];
  184. }
  185. return (result&0xff);
  186. }
  187. //==========================================
  188. // Init share memory
  189. //==========================================
  190. /**
  191. * Share memory initialization
  192. * @return function result
  193. */
  194. int InitShareMemory()
  195. {
  196. int result = PASS;
  197. int MeterSMId;
  198. #ifndef X86
  199. //init ShmSysConfigAndInfo
  200. if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo), 0777)) < 0)
  201. {
  202. DEBUG_ERROR("shmget ShmSysConfigAndInfo NG\n");
  203. result = FAIL;
  204. }
  205. else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1)
  206. {
  207. DEBUG_ERROR("shmat ShmSysConfigAndInfo NG\n");
  208. result = FAIL;
  209. }
  210. else
  211. {}
  212. //init ShmStatusCodeData
  213. if ((MeterSMId = shmget(ShmStatusCodeKey, sizeof(struct StatusCodeData), 0777)) < 0)
  214. {
  215. DEBUG_ERROR("shmget ShmStatusCodeData NG\n");
  216. result = FAIL;
  217. }
  218. else if ((ShmStatusCodeData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
  219. {
  220. DEBUG_ERROR("shmat ShmStatusCodeData NG\n");
  221. result = FAIL;
  222. }
  223. else
  224. {}
  225. //init ShmOCPP16Data
  226. if ((MeterSMId = shmget(ShmOcppModuleKey, sizeof(struct OCPP16Data), 0777)) < 0)
  227. {
  228. DEBUG_ERROR("shmget ShmOCPP16Data NG\n");
  229. result = FAIL;
  230. }
  231. else if ((ShmOCPP16Data = shmat(MeterSMId, NULL, 0)) == (void *) -1)
  232. {
  233. DEBUG_ERROR("shmat ShmOCPP16Data NG\n");
  234. result = FAIL;
  235. }
  236. else
  237. {}
  238. #endif
  239. return result;
  240. }
  241. //==========================================
  242. // Init com port
  243. //==========================================
  244. /**
  245. * TTY port initialization
  246. * @return port initial result
  247. */
  248. int InitComPort()
  249. {
  250. int fd;
  251. struct termios tios;
  252. fd = open(TTY_PORT, O_RDWR);
  253. if(fd<=0)
  254. {
  255. return FAIL;
  256. }
  257. ioctl (fd, TCGETS, &tios);
  258. tios.c_cflag = B9600| CS8 | CLOCAL | CREAD;
  259. tios.c_lflag = 0;
  260. tios.c_iflag = 0;
  261. tios.c_oflag = 0;
  262. tios.c_cc[VMIN]=0; // data length threshold, 0 bytes
  263. tios.c_cc[VTIME]=(unsigned char)5; // timeout threshold, 0.5 seconds
  264. tios.c_lflag=0;
  265. tcflush(fd, TCIFLUSH);
  266. ioctl (fd, TCSETS, &tios);
  267. return fd;
  268. }
  269. /**
  270. *
  271. * @param serial port handle
  272. * @param request message data
  273. * @param response message data
  274. * @return
  275. */
  276. int pollingRequest(int uart, unsigned char* cmd)
  277. {
  278. int result=FAIL;
  279. tcflush(uart,TCIOFLUSH);
  280. cmd[(cmd[1]<<8)|(cmd[2])] = calChksum(cmd);
  281. //show_raw(cmd, cmd_len, NO);
  282. if(write(uart, cmd, ARRAY_SIZE(cmd)) > 0)
  283. {
  284. result = PASS;
  285. }
  286. else
  287. {
  288. DEBUG_ERROR("pollingRequest fail.\n");
  289. }
  290. return result;
  291. }
  292. /**
  293. *
  294. * @param uart
  295. * @param rx
  296. * @return
  297. */
  298. int pollingResponse(int uart, unsigned char* rx)
  299. {
  300. int result=FAIL;
  301. read(uart, rx, RAW_DATA_LENGTH);
  302. //show_raw(rx, rx_len, YES);
  303. if(calChksum(&rx[0]) == rx[(((rx[1] << 8) | (rx[1]))+3)])
  304. {
  305. result = PASS;
  306. }
  307. return result;
  308. }
  309. /**
  310. *
  311. * @param uart
  312. * @return
  313. */
  314. int getInputBufferCount(int uart)
  315. {
  316. int bytes_avail;
  317. ioctl(uart, FIONREAD, &bytes_avail);
  318. return bytes_avail;
  319. }
  320. /**
  321. *
  322. * @param node
  323. * @param node_name
  324. * @return
  325. */
  326. xmlNode *find_node(xmlNode *node, char *node_name)
  327. {
  328. xmlNode *result;
  329. if (node == NULL) return NULL;
  330. while(node)
  331. {
  332. if((node->type == XML_ELEMENT_NODE) && (strcmp((char*)node->name, node_name) == 0)) return node;
  333. if((result = find_node(node->children, node_name))) return result;
  334. node = node->next;
  335. }
  336. return NULL;
  337. }
  338. //==========================================
  339. // Reader operation function
  340. //==========================================
  341. int preAuthRequest(int uart)
  342. {
  343. char xmlBody[512]={0};
  344. xmlBuffer * outputXmlPtr = xmlBufferCreate();
  345. xmlDocPtr doc = NULL;
  346. xmlNodePtr node_req = NULL;
  347. xmlNodePtr node_cmd = NULL;
  348. xmlNodePtr node_param = NULL;
  349. xmlNodePtr node_param_Txn = NULL;
  350. // Create xml message
  351. doc = xmlNewDoc(BAD_CAST "1.0");
  352. node_req = xmlNewNode(NULL, BAD_CAST "Req");
  353. xmlDocSetRootElement(doc, node_req);
  354. node_cmd = xmlNewNode(NULL, BAD_CAST "Cmd");
  355. xmlNewChild(node_cmd, NULL, BAD_CAST "CmdId", BAD_CAST "TxnStart");
  356. xmlNewChild(node_cmd, NULL, BAD_CAST "CmdTout", BAD_CAST "30");
  357. xmlAddChild(node_req, node_cmd);
  358. node_param = xmlNewNode(NULL, BAD_CAST "Param");
  359. node_param_Txn = xmlNewNode(NULL, BAD_CAST "Txn");
  360. xmlNewChild(node_param_Txn, NULL, BAD_CAST "TxnType", BAD_CAST "AuthOnly");
  361. xmlNewChild(node_param_Txn, NULL, BAD_CAST "CurrCode", BAD_CAST "840");
  362. xmlNewChild(node_param_Txn, NULL, BAD_CAST "TxnAmt", BAD_CAST "100");
  363. xmlAddChild(node_param, node_param_Txn);
  364. xmlAddChild(node_req, node_param);
  365. xmlNodeDump(outputXmlPtr, NULL, (xmlNode *)node_req, 0, 0);
  366. sprintf(xmlBody, "%s", (const char *)outputXmlPtr->content);
  367. xmlBufferFree(outputXmlPtr);
  368. xmlFreeDoc(doc);
  369. xmlCleanupParser();
  370. xmlMemoryDump();
  371. // Create protocol message
  372. memset(commandRaw.requestData, 0x00, ARRAY_SIZE(commandRaw.requestData));
  373. commandRaw.requestData[0] = STX;
  374. commandRaw.requestData[1] = (strlen(xmlBody)>>8)&0xff;
  375. commandRaw.requestData[2] = (strlen(xmlBody)>>0)&0xff;
  376. memcpy(&commandRaw.requestData[3], xmlBody, strlen(xmlBody));
  377. return pollingRequest(uart, commandRaw.requestData);
  378. }
  379. int preAuthResponse(int uart)
  380. {
  381. int result = pollingResponse(uart, commandRaw.responseData);
  382. //char *xmlTestBody = "<Event><MesgId>21</MesgId><MesgStr>PLEASE PRESENT CARD</MesgStr></Event>";
  383. //char *xmlTestBody = "<Event><MesgId>27</MesgId><MesgStr>AUTHORIZING. PLEASE WAIT...</MesgStr></Event>";
  384. //char *xmlTestBody = "<Resp><Cmd><CmdId>TxnStartResp</CmdId><StatusCode>001F</StatusCode><StatusText>TransactionDeferred</StatusText></Cmd><Data><Txn><TxnId>62</TxnId></Txn></Data></Resp>";
  385. char xmlTestBody[512] = {0};
  386. if(result == PASS)
  387. {
  388. memcpy(xmlTestBody, &commandRaw.responseData[3], ((commandRaw.responseData[1] << 8) | commandRaw.responseData[2]));
  389. xmlDocPtr doc = xmlParseDoc((const xmlChar *)xmlTestBody);
  390. xmlNode *root_element = xmlDocGetRootElement(doc);
  391. if(find_node(root_element, "Event") != NULL)
  392. {
  393. DEBUG_INFO("===== Get event =======================\n");
  394. ShmSysConfigAndInfo->SysInfo.bazel8.event.messageId = atoi((char*)xmlNodeGetContent(find_node(root_element, "MesgId")));
  395. sprintf(ShmSysConfigAndInfo->SysInfo.bazel8.event.messageString, "%s", xmlNodeGetContent(find_node(root_element, "MesgId")));
  396. ShmSysConfigAndInfo->SysInfo.bazel8.event.isGetOn = ON;
  397. DEBUG_INFO("Message id: %d\n", ShmSysConfigAndInfo->SysInfo.bazel8.event.messageId);
  398. DEBUG_INFO("%s: %s\n", root_element->children->next->name, xmlNodeGetContent(root_element->children->next));
  399. }
  400. else if((find_node(root_element, "Resp") != NULL) && (strstr((char*)xmlNodeGetContent(find_node(root_element, "CmdId")), "TxnStartResp") != NULL))
  401. {
  402. DEBUG_INFO("===== Get response =======================\n");
  403. sprintf(ShmSysConfigAndInfo->SysInfo.bazel8.txResp.statusCode, "%s", xmlNodeGetContent(find_node(root_element, "StatusCode")));
  404. sprintf(ShmSysConfigAndInfo->SysInfo.bazel8.txResp.statusText, "%s", xmlNodeGetContent(find_node(root_element, "StatusText")));
  405. sprintf(ShmSysConfigAndInfo->SysInfo.bazel8.txResp.txnId, "%s", xmlNodeGetContent(find_node(root_element, "TxnId")));
  406. ShmSysConfigAndInfo->SysInfo.bazel8.txResp.isGetOn = ON;
  407. DEBUG_INFO("Status code: %s\n", ShmSysConfigAndInfo->SysInfo.bazel8.txResp.statusCode);
  408. DEBUG_INFO("Status text: %s\n", ShmSysConfigAndInfo->SysInfo.bazel8.txResp.statusText);
  409. DEBUG_INFO("TxnId: %s\n", ShmSysConfigAndInfo->SysInfo.bazel8.txResp.txnId);
  410. }
  411. else
  412. {
  413. DEBUG_INFO("===== Get unknown node =======================\n");
  414. }
  415. xmlFreeDoc(doc);
  416. xmlCleanupParser();
  417. xmlMemoryDump();
  418. }
  419. return result;
  420. }
  421. //==========================================
  422. // Main loop
  423. //==========================================
  424. int main(void)
  425. {
  426. int UartFd;
  427. int preAuthRetry = 0;
  428. int cmdRepeatCount = 0;
  429. //===============================================
  430. // Initialization
  431. //===============================================
  432. #ifndef X86
  433. if(InitShareMemory() == FAIL)
  434. {
  435. DEBUG_ERROR("InitShareMemory NG\n");
  436. if(ShmStatusCodeData!=NULL)
  437. {
  438. ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FailToCreateShareMemory=1;
  439. }
  440. sleep(5);
  441. return FAIL;
  442. }
  443. #endif
  444. UartFd=InitComPort();
  445. if(UartFd<0)
  446. {
  447. DEBUG_ERROR("InitComPort NG\n");
  448. if(ShmStatusCodeData!=NULL)
  449. {
  450. #ifndef X86
  451. ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CsuInitFailed=1;
  452. #endif
  453. }
  454. sleep(5);
  455. return FAIL;
  456. }
  457. else
  458. {
  459. DEBUG_INFO("%s port open success.\n", TTY_PORT);
  460. }
  461. DEBUG_INFO("Payment module initialize completed.\n");
  462. //===============================================
  463. // Main loop
  464. //===============================================
  465. for(;;)
  466. {
  467. if(ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isReq)
  468. {
  469. // Pre auth request
  470. if(!ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isWaitRes)
  471. {
  472. ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isRes = false;
  473. ShmSysConfigAndInfo->SysInfo.bazel8.event.isGetOn = false;
  474. ShmSysConfigAndInfo->SysInfo.bazel8.txResp.isGetOn = false;
  475. if(preAuthRequest(UartFd))
  476. {
  477. ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isWaitRes = true;
  478. cmdRepeatCount = 0;
  479. refreshStartTimer(&tmr[TIMER_READ_RESPONSE]);
  480. }
  481. if(cmdRepeatCount > SPEC_REQUEST_RETRY)
  482. {
  483. DEBUG_WARN("preAuthRequest fail over count(%d).", cmdRepeatCount);
  484. cmdRepeatCount = 0;
  485. ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isReq = false;
  486. ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isResultPass = false;
  487. ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isRes = true;
  488. }
  489. else
  490. {
  491. cmdRepeatCount += 1;
  492. }
  493. }
  494. else
  495. {
  496. if((getInputBufferCount(UartFd) >= RAW_DATA_LENGTH))
  497. {
  498. if(preAuthResponse(UartFd))
  499. {
  500. if(ShmSysConfigAndInfo->SysInfo.bazel8.event.isGetOn)
  501. {
  502. /*
  503. * TODO:
  504. * 1. Announce CSU event content.
  505. */
  506. ShmSysConfigAndInfo->SysInfo.bazel8.event.isGetOn = false;
  507. }
  508. else if(ShmSysConfigAndInfo->SysInfo.bazel8.txResp.isGetOn)
  509. {
  510. ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isResultPass = ((strstr(ShmSysConfigAndInfo->SysInfo.bazel8.txResp.statusCode, "0000") != NULL)?true:false);
  511. if(ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isResultPass || (preAuthRetry++ >= 3))
  512. {
  513. ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isReq = false;
  514. ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isRes = true;
  515. preAuthRetry = 0;
  516. }
  517. ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isWaitRes = false;
  518. }
  519. }
  520. }
  521. if((getDiffSecNow(tmr[TIMER_READ_RESPONSE]) > TIMEOUT_REQUEST))
  522. {
  523. ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isReq = false;
  524. ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isWaitRes = false;
  525. ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isResultPass = false;
  526. ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isRes = true;
  527. DEBUG_WARN("Wait pre auth response timeout(%d secs).", TIMEOUT_REQUEST);
  528. }
  529. }
  530. }
  531. sleep(3);
  532. }
  533. return FAIL;
  534. }