|
@@ -3,12 +3,14 @@
|
|
|
*
|
|
|
* Created on: 2022/04/29
|
|
|
* Author: Folus Wen
|
|
|
+ * run_evse_stop.sh
|
|
|
*/
|
|
|
|
|
|
#include "Module_Payment_Bazel8.h"
|
|
|
|
|
|
struct COMMAND commandRaw;
|
|
|
struct timespec tmr[TIMER_CNT];
|
|
|
+uint16_t nSerial;
|
|
|
|
|
|
//==========================================
|
|
|
// Common routine
|
|
@@ -207,11 +209,11 @@ int calChksum(unsigned char *data)
|
|
|
{
|
|
|
int result = 0;
|
|
|
|
|
|
- for(uint16_t idx=0;idx<(((data[1] << 8) | (data[1]))+3);idx++)
|
|
|
+ for(uint16_t idx=1;idx<(((data[1] << 8) | (data[2]))+3); idx++)
|
|
|
{
|
|
|
result ^= data[idx];
|
|
|
}
|
|
|
-
|
|
|
+ // printf("\n\rThe checksum : %x \n\r", result);
|
|
|
return (result&0xff);
|
|
|
}
|
|
|
|
|
@@ -315,12 +317,16 @@ int InitComPort()
|
|
|
int pollingRequest(int uart, unsigned char* cmd)
|
|
|
{
|
|
|
int result=FAIL;
|
|
|
+ int length;
|
|
|
|
|
|
tcflush(uart,TCIOFLUSH);
|
|
|
- cmd[(cmd[1]<<8)|(cmd[2])] = calChksum(cmd);
|
|
|
+
|
|
|
+ length = ((cmd[1]<<8)|cmd[2])+4;
|
|
|
+ cmd[(length-1)] = calChksum(cmd);
|
|
|
|
|
|
- //show_raw(cmd, cmd_len, NO);
|
|
|
- if(write(uart, cmd, ARRAY_SIZE(cmd)) > 0)
|
|
|
+ show_raw(cmd, length, NO);
|
|
|
+
|
|
|
+ if(write(uart, cmd, length ) > 0)
|
|
|
{
|
|
|
result = PASS;
|
|
|
}
|
|
@@ -340,16 +346,51 @@ int pollingRequest(int uart, unsigned char* cmd)
|
|
|
*/
|
|
|
int pollingResponse(int uart, unsigned char* rx)
|
|
|
{
|
|
|
- int result=FAIL;
|
|
|
-
|
|
|
- read(uart, rx, RAW_DATA_LENGTH);
|
|
|
- //show_raw(rx, rx_len, YES);
|
|
|
-
|
|
|
- if(calChksum(&rx[0]) == rx[(((rx[1] << 8) | (rx[1]))+3)])
|
|
|
+ int result =FAIL;
|
|
|
+ int len = 0;
|
|
|
+ int Total_len[2] = {0, 0};
|
|
|
+ int CSUM[2]={0,0};
|
|
|
+ uint8_t buf[512];
|
|
|
+
|
|
|
+ // DEBUG_INFO("\n\r===== Prepare to read serial data. ===============\n\r");
|
|
|
+
|
|
|
+ do {
|
|
|
+ len =read(uart, buf, 512);
|
|
|
+ if(len == 0)
|
|
|
+ break;
|
|
|
+
|
|
|
+ // printf ("This is a string %d chars long\n", len);
|
|
|
+ for (int i=0; i<len; i++)
|
|
|
+ {
|
|
|
+ rx[(Total_len[0]+i)] =buf[i];
|
|
|
+ }
|
|
|
+
|
|
|
+ memcpy(&rx[(Total_len[0])], buf, len);
|
|
|
+
|
|
|
+ if(Total_len[0] == 0)
|
|
|
+ Total_len[1] = ((buf[1] << 8) | (buf[2]))+4; // lead 3 + csum
|
|
|
+ Total_len[0] = Total_len[0] + len;
|
|
|
+
|
|
|
+ usleep(10);
|
|
|
+ } while (Total_len[0] < Total_len[1]);
|
|
|
+
|
|
|
+ if(Total_len[0] >0)
|
|
|
{
|
|
|
- result = PASS;
|
|
|
- }
|
|
|
-
|
|
|
+ show_raw(rx, Total_len[1], YES);
|
|
|
+
|
|
|
+ CSUM[0] = rx[(((rx[1] << 8) | (rx[2]))+3)];
|
|
|
+ CSUM[1] = calChksum(&rx[0]);
|
|
|
+
|
|
|
+ if(CSUM[0] == CSUM[1])
|
|
|
+ {
|
|
|
+ result = PASS;
|
|
|
+ DEBUG_INFO("\n\r===== Receive data checksum (%x , %x) OK. ===============\n\r", CSUM[0], CSUM[1]);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ DEBUG_INFO("\n\r===== Receive data checksum (%x , %x) Fail. ===============\n\r", CSUM[0], CSUM[1]);
|
|
|
+ }
|
|
|
+ }
|
|
|
return result;
|
|
|
}
|
|
|
|
|
@@ -361,6 +402,7 @@ int pollingResponse(int uart, unsigned char* rx)
|
|
|
int getInputBufferCount(int uart)
|
|
|
{
|
|
|
int bytes_avail;
|
|
|
+
|
|
|
ioctl(uart, FIONREAD, &bytes_avail);
|
|
|
|
|
|
return bytes_avail;
|
|
@@ -395,7 +437,8 @@ xmlNode *find_node(xmlNode *node, char *node_name)
|
|
|
//==========================================
|
|
|
int preAuthRequest(int uart)
|
|
|
{
|
|
|
- char xmlBody[512]={0};
|
|
|
+ char xmlBody[1024]={0};
|
|
|
+ int n;
|
|
|
|
|
|
xmlBuffer * outputXmlPtr = xmlBufferCreate();
|
|
|
xmlDocPtr doc = NULL;
|
|
@@ -417,13 +460,19 @@ int preAuthRequest(int uart)
|
|
|
node_param = xmlNewNode(NULL, BAD_CAST "Param");
|
|
|
node_param_Txn = xmlNewNode(NULL, BAD_CAST "Txn");
|
|
|
xmlNewChild(node_param_Txn, NULL, BAD_CAST "TxnType", BAD_CAST "AuthOnly");
|
|
|
- xmlNewChild(node_param_Txn, NULL, BAD_CAST "CurrCode", BAD_CAST "840");
|
|
|
- xmlNewChild(node_param_Txn, NULL, BAD_CAST "TxnAmt", BAD_CAST "100");
|
|
|
+ xmlNewChild(node_param_Txn, NULL, BAD_CAST "AccType", BAD_CAST "Default");
|
|
|
+ xmlNewChild(node_param_Txn, NULL, BAD_CAST "CurrCode", BAD_CAST ISO_4217_Currency_Code[ShmSysConfigAndInfo->SysConfig.BillingData.Currency]);
|
|
|
+ //xmlNewChild(node_param_Txn, NULL, BAD_CAST "CurrCode", BAD_CAST "840");
|
|
|
+ xmlNewChild(node_param_Txn, NULL, BAD_CAST "TxnAmt", BAD_CAST ShmOCPP16Data->ConfigurationTable.CoreProfile[PreAuthAmount].ItemData);
|
|
|
+ //xmlNewChild(node_param_Txn, NULL, BAD_CAST "TxnAmt", BAD_CAST "0001.00");
|
|
|
+
|
|
|
xmlAddChild(node_param, node_param_Txn);
|
|
|
xmlAddChild(node_req, node_param);
|
|
|
|
|
|
xmlNodeDump(outputXmlPtr, NULL, (xmlNode *)node_req, 0, 0);
|
|
|
- sprintf(xmlBody, "%s", (const char *)outputXmlPtr->content);
|
|
|
+ n = sprintf(xmlBody, "%s", (const char *)outputXmlPtr->content);
|
|
|
+
|
|
|
+ printf ("[%s] is a string %d chars long\n", xmlBody, n);
|
|
|
|
|
|
xmlBufferFree(outputXmlPtr);
|
|
|
xmlFreeDoc(doc);
|
|
@@ -438,6 +487,7 @@ int preAuthRequest(int uart)
|
|
|
commandRaw.requestData[2] = (strlen(xmlBody)>>0)&0xff;
|
|
|
memcpy(&commandRaw.requestData[3], xmlBody, strlen(xmlBody));
|
|
|
|
|
|
+ show_raw(&commandRaw.requestData[0], (strlen(xmlBody)+3), NO);
|
|
|
|
|
|
return pollingRequest(uart, commandRaw.requestData);
|
|
|
}
|
|
@@ -445,10 +495,12 @@ int preAuthRequest(int uart)
|
|
|
int preAuthResponse(int uart)
|
|
|
{
|
|
|
int result = pollingResponse(uart, commandRaw.responseData);
|
|
|
+
|
|
|
//char *xmlTestBody = "<Event><MesgId>21</MesgId><MesgStr>PLEASE PRESENT CARD</MesgStr></Event>";
|
|
|
//char *xmlTestBody = "<Event><MesgId>27</MesgId><MesgStr>AUTHORIZING. PLEASE WAIT...</MesgStr></Event>";
|
|
|
//char *xmlTestBody = "<Resp><Cmd><CmdId>TxnStartResp</CmdId><StatusCode>001F</StatusCode><StatusText>TransactionDeferred</StatusText></Cmd><Data><Txn><TxnId>62</TxnId></Txn></Data></Resp>";
|
|
|
- char xmlTestBody[512] = {0};
|
|
|
+
|
|
|
+ char xmlTestBody[1024] = {0};
|
|
|
|
|
|
if(result == PASS)
|
|
|
{
|
|
@@ -470,24 +522,38 @@ int preAuthResponse(int uart)
|
|
|
else if((find_node(root_element, "Resp") != NULL) && (strstr((char*)xmlNodeGetContent(find_node(root_element, "CmdId")), "TxnStartResp") != NULL))
|
|
|
{
|
|
|
DEBUG_INFO("===== Get response =======================\n");
|
|
|
+ ShmSysConfigAndInfo->SysInfo.bazel8.txResp.isGetOn = ON;
|
|
|
+
|
|
|
sprintf(ShmSysConfigAndInfo->SysInfo.bazel8.txResp.statusCode, "%s", xmlNodeGetContent(find_node(root_element, "StatusCode")));
|
|
|
sprintf(ShmSysConfigAndInfo->SysInfo.bazel8.txResp.statusText, "%s", xmlNodeGetContent(find_node(root_element, "StatusText")));
|
|
|
- sprintf(ShmSysConfigAndInfo->SysInfo.bazel8.txResp.txnId, "%s", xmlNodeGetContent(find_node(root_element, "TxnId")));
|
|
|
- ShmSysConfigAndInfo->SysInfo.bazel8.txResp.isGetOn = ON;
|
|
|
|
|
|
DEBUG_INFO("Status code: %s\n", ShmSysConfigAndInfo->SysInfo.bazel8.txResp.statusCode);
|
|
|
DEBUG_INFO("Status text: %s\n", ShmSysConfigAndInfo->SysInfo.bazel8.txResp.statusText);
|
|
|
- DEBUG_INFO("TxnId: %s\n", ShmSysConfigAndInfo->SysInfo.bazel8.txResp.txnId);
|
|
|
+
|
|
|
+ if(strstr(ShmSysConfigAndInfo->SysInfo.bazel8.txResp.statusCode,"0000") != NULL)
|
|
|
+ {
|
|
|
+ sprintf(ShmSysConfigAndInfo->SysInfo.bazel8.txResp.txnId, "%s", xmlNodeGetContent(find_node(root_element, "TxnId")));
|
|
|
+ DEBUG_INFO("TxnId: %s\n", ShmSysConfigAndInfo->SysInfo.bazel8.txResp.txnId);
|
|
|
+ }
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
DEBUG_INFO("===== Get unknown node =======================\n");
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+ //DEBUG_INFO("===== End 0 =======================\n");
|
|
|
xmlFreeDoc(doc);
|
|
|
+ //DEBUG_INFO("===== End 1 =======================\n");
|
|
|
xmlCleanupParser();
|
|
|
+ //DEBUG_INFO("===== End 2 =======================\n");
|
|
|
xmlMemoryDump();
|
|
|
+ //DEBUG_INFO("===== End 3 =======================\n");
|
|
|
}
|
|
|
+ else
|
|
|
+ {
|
|
|
+ DEBUG_INFO("===== Get preAuth Response is Fail =====( %d)==========\n", nSerial++);
|
|
|
+ nSerial %= 0xffff;
|
|
|
+ }
|
|
|
|
|
|
return result;
|
|
|
}
|
|
@@ -500,10 +566,25 @@ int main(void)
|
|
|
int UartFd;
|
|
|
int preAuthRetry = 0;
|
|
|
int cmdRepeatCount = 0;
|
|
|
-
|
|
|
+
|
|
|
+ // Henry
|
|
|
+ int state[2] = {s_IDLE, s_IDLE};
|
|
|
+ //uint8_t Rx_Cir_Buf[1024];
|
|
|
+ //uint8_t Rx_Buf[1024];
|
|
|
+ //int Rx_Cir_Idx[2], Rx_Buf_Idx;
|
|
|
+
|
|
|
+
|
|
|
//===============================================
|
|
|
// Initialization
|
|
|
//===============================================
|
|
|
+
|
|
|
+// Rx_Cir_Idx[0] = Rx_Cir_Idx[1] = Rx_Buf_Idx = 0;
|
|
|
+//
|
|
|
+// for (int i=0; i<1024; i++)
|
|
|
+// {
|
|
|
+// Rx_Cir_Buf[i] =Rx_Buf[i] =0;
|
|
|
+// }
|
|
|
+
|
|
|
#ifndef X86
|
|
|
if(InitShareMemory() == FAIL)
|
|
|
{
|
|
@@ -538,13 +619,141 @@ int main(void)
|
|
|
|
|
|
DEBUG_INFO("Payment module initialize completed.\n");
|
|
|
|
|
|
+// ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isReq = true; // from CSU
|
|
|
+// ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isWaitRes = false;
|
|
|
+// ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isResultPass = false;
|
|
|
+// ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isRes = false;
|
|
|
+
|
|
|
//===============================================
|
|
|
// Main loop
|
|
|
//===============================================
|
|
|
+
|
|
|
+ while (1) {
|
|
|
+// if(state[0] != state[1])
|
|
|
+// {
|
|
|
+// state[1] = 1;
|
|
|
+//
|
|
|
+// preAuthRequest(UartFd);
|
|
|
+//
|
|
|
+// }
|
|
|
+//
|
|
|
+// if(state[1] == 1)
|
|
|
+// {
|
|
|
+// // pollingResponse(UartFd, Rx_Buf);
|
|
|
+// preAuthResponse(UartFd);
|
|
|
+// }
|
|
|
+
|
|
|
+ /*
|
|
|
+ CSU 將 cmdPreAuth.isReq 設定 true 的同時也要將 cmdPreAuth.isRes 設定為 false,然後等 cmdPreAuth.isRes 為 true 才表示交易已完成。
|
|
|
+ */
|
|
|
+ switch(state[0])
|
|
|
+ {
|
|
|
+ case s_IDLE:
|
|
|
+ if(state[0] != state[1])
|
|
|
+ {
|
|
|
+ state[1] = state[0];
|
|
|
+ DEBUG_INFO(" >> Back to Idle.\n");
|
|
|
+
|
|
|
+ ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isReq = false;
|
|
|
+ ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isResultPass = false;
|
|
|
+ //ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isRes = false; // The CSU should be set to false.
|
|
|
+ }
|
|
|
+
|
|
|
+ if(ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isReq)
|
|
|
+ {
|
|
|
+ ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isReq = false;
|
|
|
+ state[0] = s_SEND_AUTH_ONLY;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case s_SEND_AUTH_ONLY:
|
|
|
+ if(state[0] != state[1])
|
|
|
+ {
|
|
|
+ state[1] = state[0];
|
|
|
+
|
|
|
+ if(preAuthRequest(UartFd))
|
|
|
+ {
|
|
|
+ refreshStartTimer(&tmr[TIMER_READ_RESPONSE]);
|
|
|
+
|
|
|
+ cmdRepeatCount = 0;
|
|
|
+ state[0] = s_WAIT_RESPONE;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(cmdRepeatCount > SPEC_REQUEST_RETRY)
|
|
|
+ {
|
|
|
+ DEBUG_WARN("preAuthRequest fail over count(%d).", cmdRepeatCount);
|
|
|
+
|
|
|
+ cmdRepeatCount = 0;
|
|
|
+ ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isReq = false;
|
|
|
+ ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isResultPass = false;
|
|
|
+ ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isRes = true; // To tell CSU is done.
|
|
|
+
|
|
|
+ state[0] = s_IDLE;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ cmdRepeatCount++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case s_WAIT_RESPONE:
|
|
|
+ if(state[0] != state[1])
|
|
|
+ {
|
|
|
+ state[1] = state[0];
|
|
|
+ ShmSysConfigAndInfo->SysInfo.bazel8.txResp.isGetOn = OFF;
|
|
|
+ ShmSysConfigAndInfo->SysInfo.bazel8.event.isGetOn = OFF;
|
|
|
+ nSerial = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ do {
|
|
|
+ if( preAuthResponse(UartFd) )
|
|
|
+ {
|
|
|
+ if(ShmSysConfigAndInfo->SysInfo.bazel8.event.isGetOn)
|
|
|
+ {
|
|
|
+ // * 1. Announce CSU event content.
|
|
|
+
|
|
|
+ ShmSysConfigAndInfo->SysInfo.bazel8.event.isGetOn = false;
|
|
|
+
|
|
|
+// if(ShmSysConfigAndInfo->SysInfo.bazel8.event.messageId == 21) // Please Present Card.
|
|
|
+// refreshStartTimer(&tmr[TIMER_READ_RESPONSE]);
|
|
|
+ }
|
|
|
+ else if(ShmSysConfigAndInfo->SysInfo.bazel8.txResp.isGetOn)
|
|
|
+ {
|
|
|
+ ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isResultPass = \
|
|
|
+ ((strstr(ShmSysConfigAndInfo->SysInfo.bazel8.txResp.statusCode, "0000") != NULL)?true:false);
|
|
|
+
|
|
|
+ ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isRes = true; // To tell CSU is done.
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if((getDiffSecNow(tmr[TIMER_READ_RESPONSE]) > TIMEOUT_REQUEST))
|
|
|
+ {
|
|
|
+ DEBUG_WARN("Wait pre auth response timeout(%d secs).\n", TIMEOUT_REQUEST);
|
|
|
+
|
|
|
+ ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isResultPass = false;
|
|
|
+ ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isRes = true; // To tell CSU is done.
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ } while (ShmSysConfigAndInfo->SysInfo.bazel8.txResp.isGetOn != ON);
|
|
|
+
|
|
|
+ state[0] = s_IDLE;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ state[0] = s_IDLE;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return FAIL;
|
|
|
+
|
|
|
for(;;)
|
|
|
{
|
|
|
+
|
|
|
+ // need to run the script first : run_evse_stop.sh
|
|
|
+
|
|
|
if(ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isReq)
|
|
|
{
|
|
|
+
|
|
|
// Pre auth request
|
|
|
if(!ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isWaitRes)
|
|
|
{
|
|
@@ -575,15 +784,17 @@ int main(void)
|
|
|
else
|
|
|
{
|
|
|
if((getInputBufferCount(UartFd) >= RAW_DATA_LENGTH))
|
|
|
- {
|
|
|
+ {
|
|
|
+
|
|
|
+ //DEBUG_INFO("\n\rTo wait Payment preAuth Response.\n\r");
|
|
|
+
|
|
|
if(preAuthResponse(UartFd))
|
|
|
{
|
|
|
if(ShmSysConfigAndInfo->SysInfo.bazel8.event.isGetOn)
|
|
|
{
|
|
|
- /*
|
|
|
- * TODO:
|
|
|
- * 1. Announce CSU event content.
|
|
|
- */
|
|
|
+
|
|
|
+ // * 1. Announce CSU event content.
|
|
|
+
|
|
|
ShmSysConfigAndInfo->SysInfo.bazel8.event.isGetOn = false;
|
|
|
}
|
|
|
else if(ShmSysConfigAndInfo->SysInfo.bazel8.txResp.isGetOn)
|