瀏覽代碼

2021.06.07 / Jerry Wang

Actions:
1. Debug read ADC value Module_EvComm segment fault issue.

Files
1. As follow as commit history.
Jerry_Wang 3 年之前
父節點
當前提交
ae198ccc1b
共有 77 個文件被更改,包括 26706 次插入2970 次删除
  1. 0 17
      EVSE/Projects/DD360/Apps/CSU/AcPlug.c
  2. 278 0
      EVSE/Projects/DD360/Apps/CSU/Ethernet.c
  3. 0 0
      EVSE/Projects/DD360/Apps/CSU/Gpio.c
  4. 56 129
      EVSE/Projects/DD360/Apps/CSU/Primary.c
  5. 247 152
      EVSE/Projects/DD360/Apps/CSU/RFID.c
  6. 215 0
      EVSE/Projects/DD360/Apps/CSU/SelfTest.c
  7. 0 303
      EVSE/Projects/DD360/Apps/CSU/TimeTask.c
  8. 134 8
      EVSE/Projects/DD360/Apps/CSU/UpgradeFW.c
  9. 48 0
      EVSE/Projects/DD360/Apps/CSU/WatchDog.c
  10. 15 0
      EVSE/Projects/DD360/Apps/CSU/ZipFile.c
  11. 7407 0
      EVSE/Projects/DD360/Apps/CSU/main.c
  12. 29 9
      EVSE/Projects/DD360/Apps/CSU/main.h
  13. 282 256
      EVSE/Projects/DD360/Apps/CSU/mainNew.c
  14. 2 0
      EVSE/Projects/DD360/Apps/Config.h
  15. 54 53
      EVSE/Projects/DD360/Apps/DataBase/DataBase.c
  16. 15 10
      EVSE/Projects/DD360/Apps/Makefile
  17. 2 2
      EVSE/Projects/DD360/Apps/ModuleEvComm/Module_EvComm.c
  18. 31 29
      EVSE/Projects/DD360/Apps/ModuleEvComm/Module_EvRxComm.c
  19. 2 2
      EVSE/Projects/DD360/Apps/ModuleEvComm/Module_EvTxComm.c
  20. 2 1
      EVSE/Projects/DD360/Apps/ModuleInternalComm/RelayBoard.c
  21. 22 12
      EVSE/Projects/DD360/Apps/ShareMemory/shmMem.c
  22. 1 4
      EVSE/Projects/DD360/Apps/ShareMemory/shmMem.h
  23. 60 3
      EVSE/Projects/DD360/Apps/main.c
  24. 0 17
      EVSE/Projects/DD360Audi/Apps/CSU/AcPlug.c
  25. 278 0
      EVSE/Projects/DD360Audi/Apps/CSU/Ethernet.c
  26. 0 0
      EVSE/Projects/DD360Audi/Apps/CSU/Gpio.c
  27. 56 129
      EVSE/Projects/DD360Audi/Apps/CSU/Primary.c
  28. 247 152
      EVSE/Projects/DD360Audi/Apps/CSU/RFID.c
  29. 215 0
      EVSE/Projects/DD360Audi/Apps/CSU/SelfTest.c
  30. 0 303
      EVSE/Projects/DD360Audi/Apps/CSU/TimeTask.c
  31. 134 8
      EVSE/Projects/DD360Audi/Apps/CSU/UpgradeFW.c
  32. 48 0
      EVSE/Projects/DD360Audi/Apps/CSU/WatchDog.c
  33. 15 0
      EVSE/Projects/DD360Audi/Apps/CSU/ZipFile.c
  34. 7407 0
      EVSE/Projects/DD360Audi/Apps/CSU/main.c
  35. 29 9
      EVSE/Projects/DD360Audi/Apps/CSU/main.h
  36. 282 256
      EVSE/Projects/DD360Audi/Apps/CSU/mainNew.c
  37. 2 0
      EVSE/Projects/DD360Audi/Apps/Config.h
  38. 54 53
      EVSE/Projects/DD360Audi/Apps/DataBase/DataBase.c
  39. 15 10
      EVSE/Projects/DD360Audi/Apps/Makefile
  40. 2 2
      EVSE/Projects/DD360Audi/Apps/ModuleEvComm/Module_EvComm.c
  41. 31 29
      EVSE/Projects/DD360Audi/Apps/ModuleEvComm/Module_EvRxComm.c
  42. 2 2
      EVSE/Projects/DD360Audi/Apps/ModuleEvComm/Module_EvTxComm.c
  43. 2 1
      EVSE/Projects/DD360Audi/Apps/ModuleInternalComm/RelayBoard.c
  44. 22 12
      EVSE/Projects/DD360Audi/Apps/ShareMemory/shmMem.c
  45. 1 4
      EVSE/Projects/DD360Audi/Apps/ShareMemory/shmMem.h
  46. 60 3
      EVSE/Projects/DD360Audi/Apps/main.c
  47. 二進制
      EVSE/Projects/DD360Audi/Images/ramdisk.gz
  48. 二進制
      EVSE/Projects/DD360Audi/output/Module_DoComm
  49. 二進制
      EVSE/Projects/DD360Audi/output/Module_EvComm
  50. 二進制
      EVSE/Projects/DD360Audi/output/Module_EventLogging
  51. 二進制
      EVSE/Projects/DD360Audi/output/Module_InternalComm
  52. 二進制
      EVSE/Projects/DD360Audi/output/Module_LcmControl
  53. 二進制
      EVSE/Projects/DD360Audi/output/Module_PrimaryComm
  54. 二進制
      EVSE/Projects/DD360Audi/output/main
  55. 0 17
      EVSE/Projects/DD360ComBox/Apps/CSU/AcPlug.c
  56. 278 0
      EVSE/Projects/DD360ComBox/Apps/CSU/Ethernet.c
  57. 0 0
      EVSE/Projects/DD360ComBox/Apps/CSU/Gpio.c
  58. 56 129
      EVSE/Projects/DD360ComBox/Apps/CSU/Primary.c
  59. 247 152
      EVSE/Projects/DD360ComBox/Apps/CSU/RFID.c
  60. 215 0
      EVSE/Projects/DD360ComBox/Apps/CSU/SelfTest.c
  61. 0 303
      EVSE/Projects/DD360ComBox/Apps/CSU/TimeTask.c
  62. 134 8
      EVSE/Projects/DD360ComBox/Apps/CSU/UpgradeFW.c
  63. 48 0
      EVSE/Projects/DD360ComBox/Apps/CSU/WatchDog.c
  64. 15 0
      EVSE/Projects/DD360ComBox/Apps/CSU/ZipFile.c
  65. 7407 0
      EVSE/Projects/DD360ComBox/Apps/CSU/main.c
  66. 29 9
      EVSE/Projects/DD360ComBox/Apps/CSU/main.h
  67. 282 256
      EVSE/Projects/DD360ComBox/Apps/CSU/mainNew.c
  68. 2 0
      EVSE/Projects/DD360ComBox/Apps/Config.h
  69. 54 53
      EVSE/Projects/DD360ComBox/Apps/DataBase/DataBase.c
  70. 15 10
      EVSE/Projects/DD360ComBox/Apps/Makefile
  71. 2 2
      EVSE/Projects/DD360ComBox/Apps/ModuleEvComm/Module_EvComm.c
  72. 31 29
      EVSE/Projects/DD360ComBox/Apps/ModuleEvComm/Module_EvRxComm.c
  73. 2 2
      EVSE/Projects/DD360ComBox/Apps/ModuleEvComm/Module_EvTxComm.c
  74. 2 1
      EVSE/Projects/DD360ComBox/Apps/ModuleInternalComm/RelayBoard.c
  75. 22 12
      EVSE/Projects/DD360ComBox/Apps/ShareMemory/shmMem.c
  76. 1 4
      EVSE/Projects/DD360ComBox/Apps/ShareMemory/shmMem.h
  77. 60 3
      EVSE/Projects/DD360ComBox/Apps/main.c

+ 0 - 17
EVSE/Projects/DD360/Apps/CSU/AcPlug.c

@@ -1,17 +0,0 @@
-#include <stdio.h>      /*標準輸入輸出定義*/
-#include <stdlib.h>     /*標準函數庫定義*/
-#include <string.h>
-#include <stdint.h>
-
-#include "../Config.h"
-#include "../Log/log.h"
-#include "../Define/define.h"
-#include "../ShareMemory/shmMem.h"
-
-//------------------------------------------------------------------------------
-void AcChargingTerminalProcess(void)
-{
-    struct ChargingInfoData *pAcChargingInfoData = (struct ChargingInfoData *)GetAcChargingInfoData(0);
-
-    pAcChargingInfoData->SystemStatus = MODE_TERMINATING;
-}

+ 278 - 0
EVSE/Projects/DD360/Apps/CSU/Ethernet.c

@@ -0,0 +1,278 @@
+#include <stdio.h>      /*標準輸入輸出定義*/
+#include <stdlib.h>     /*標準函數庫定義*/
+#include <string.h>
+#include <stdint.h>
+
+#include "../Config.h"
+#include "../Log/log.h"
+#include "../Define/define.h"
+#include "../ShareMemory/shmMem.h"
+
+#include "../common.h"
+
+//------------------------------------------------------------------------------
+void GetMacAddress(void)
+{
+    uint8_t index = 0;
+    struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
+
+    for (index = 0; index < 2; index++) {
+        int fd;
+        struct ifreq ifr;
+        char tarEth[5];
+        char Mac[18];
+
+        sprintf(tarEth, "eth%d", index);
+        fd = socket(AF_INET, SOCK_DGRAM, 0);
+
+        ifr.ifr_addr.sa_family = AF_INET;
+        strncpy(ifr.ifr_name, tarEth, IFNAMSIZ - 1);
+
+        ioctl(fd, SIOCGIFHWADDR, &ifr);
+        close(fd);
+
+        sprintf(Mac, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
+                ifr.ifr_hwaddr.sa_data[0],
+                ifr.ifr_hwaddr.sa_data[1],
+                ifr.ifr_hwaddr.sa_data[2],
+                ifr.ifr_hwaddr.sa_data[3],
+                ifr.ifr_hwaddr.sa_data[4],
+                ifr.ifr_hwaddr.sa_data[5]
+               );
+
+        if (index == 0) {
+            strcpy((char *) pSysConfig->Eth0Interface.EthMacAddress, Mac);
+        } else {
+            strcpy((char *) pSysConfig->Eth1Interface.EthMacAddress, Mac);
+        }
+    }
+}
+
+static int isRouteFail(void)
+{
+    int result = YES;
+    FILE *fp;
+    char buf[512];
+
+    fp = popen("route -n", "r");
+    if (fp != NULL) {
+        while (fgets(buf, sizeof(buf), fp) != NULL) {
+            if (strstr(buf, "eth0") != NULL) {
+                result = NO;
+            }
+        }
+    }
+    pclose(fp);
+
+    return result;
+}
+
+static int isReachableInternet(void)
+{
+    int result = FAIL;
+    FILE *fp;
+    char cmd[256];
+    char buf[512];
+    char tmp[512];
+    struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
+    struct AlarmCodeData *pAlarmCode = (struct AlarmCodeData *)GetShmAlarmCodeData();
+
+    strcpy(cmd, "ifconfig eth0");
+    fp = popen(cmd, "r");
+
+    if (fp != NULL) {
+        while (fgets(buf, sizeof(buf), fp) != NULL) {
+            if (strstr(buf, "inet addr:") > 0) {
+                sscanf(buf, "%*s%s", tmp);
+                substr(tmp, tmp, strspn(tmp, "addr:"), strlen(buf) - strspn(tmp, "addr:"));
+
+                if (strcmp(tmp, (char *)pSysConfig->Eth0Interface.EthIpAddress) != EQUAL) {
+                    strcpy((char *) pSysConfig->Eth0Interface.EthIpAddress, tmp);
+                }
+            }
+        }
+    }
+    pclose(fp);
+
+#if defined DD360 ||defined DD360Audi || defined DD360ComBox
+    if (pAlarmCode->AlarmEvents.bits.DisconnectedFromDo == NORMAL) {
+        result = FAIL;
+    } else {
+        result = PASS;
+    }
+#else
+    memset(buf, 0x00, sizeof(buf));
+    for (int idx = 0; idx < ARRAY_SIZE(valid_Internet); idx++) {
+        sprintf(cmd, "ping -c 1 -w 3 -I eth0 %s", valid_Internet[idx]);
+        fp = popen(cmd, "r");
+        if (fp != NULL) {
+            while (fgets(buf, sizeof(buf), fp) != NULL) {
+                if (strstr(buf, "transmitted") > 0) {
+                    //sscanf(buf, "%*s%*s%*s%*s%*s%*s%s", tmp);
+
+                    if (strstr(buf, "100%") != NULL) {
+                    } else {
+                        result = PASS;
+                    }
+                    //DEBUG_INFO("%s",buf);
+                    //DEBUG_INFO("%s\n",tmp);
+                }
+            }
+        }
+        pclose(fp);
+    }
+
+#endif //defined DD360 || defined DD360Audi
+
+    return result;
+}
+
+void InitEthernet(void)
+{
+    char tmpbuf[256];
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+    bool ethResult = false;
+    uint8_t cnt_pingDNS_Fail = 0;
+#endif //!defined DD360 && !defined DD360Audi
+
+    struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
+
+    system("ifconfig eth0 down");// eth0 down
+    system("ifconfig eth1 down");// eth1 down
+    sleep(2);
+
+    // /sbin/ifconfig eth0 192.168.1.10 netmask 255.255.255.0 down
+    system("echo 1 > /sys/class/gpio/gpio110/value");//reset PHY
+    sleep(2);
+    //Init Eth0 for internet
+    memset(tmpbuf, 0, 256);
+    sprintf(tmpbuf, "/sbin/ifconfig eth0 %s netmask %s up",
+            pSysConfig->Eth0Interface.EthIpAddress,
+            pSysConfig->Eth0Interface.EthSubmaskAddress);
+    //sprintf(tmpbuf,"/sbin/ifconfig eth0 192.168.100.10 netmask 255.255.255.0 up");
+    system(tmpbuf);
+
+    memset(tmpbuf, 0, 256);
+    sprintf(tmpbuf, "route add default gw %s eth0 ",
+            pSysConfig->Eth0Interface.EthGatewayAddress);
+    //sprintf(tmpbuf,"route add default gw 192.168.100.1 eth0 ");
+    system(tmpbuf);
+    //system("ifconfig lo up");
+    //  /sbin/ifconfig eth0 192.168.1.10 netmask 255.255.255.0 up
+    //Init Eth1 for administrator tool
+    memset(tmpbuf, 0, 256);
+    sprintf(tmpbuf, "/sbin/ifconfig eth1 %s netmask %s up",
+            pSysConfig->Eth1Interface.EthIpAddress,
+            pSysConfig->Eth1Interface.EthSubmaskAddress);
+    system(tmpbuf);
+
+    //Run DHCP client if enabled
+    system("killall udhcpc");
+    system("rm -rf /etc/resolv.conf");
+    system("echo nameserver 8.8.8.8 > /etc/resolv.conf");       //Google DNS server
+    system("echo nameserver 180.76.76.76 > /etc/resolv.conf");  //Baidu DNS server
+    //system("/sbin/ifconfig eth0 down;/sbin/ifconfig eth0 up");
+
+    if (pSysConfig->Eth0Interface.EthDhcpClient == 0) {
+        sprintf(tmpbuf, "/sbin/udhcpc -i eth0 -x hostname:CSU3_%s -s /root/dhcp_script/eth0.script > /dev/null &",
+                pSysConfig->SystemId);
+        system(tmpbuf);
+    }
+
+    //Upgrade system id to /etc/hostname
+    sprintf(tmpbuf, "echo %s > /etc/hostname", pSysConfig->SystemId);
+    system(tmpbuf);
+
+    pid_t pid = fork();
+    if (pid == 0) {
+        log_info("InitEthernet = %d\r\n", pid);
+        for (;;) {
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+            if (isRouteFail()) {
+                //log_info("eth0 not in route, restart eht0. \n");
+                system("/sbin/ifconfig eth0 down;/sbin/ifconfig eth0 up");
+
+                if (pSysConfig->Eth0Interface.EthDhcpClient == 0) {
+                    InitialDHCP();
+                }
+            }
+
+            if (isReachableInternet() == PASS) {
+                pSysInfo->ethInternetConn = YES;
+                cnt_pingDNS_Fail = 0;
+            } else {
+                if (++cnt_pingDNS_Fail > 3) {
+                    pSysInfo->ethInternetConn = NO;
+                }
+            }
+
+            ethResult = pSysInfo->ethInternetConn;
+
+            if (ethResult == YES) {
+                system("/sbin/ifmetric eth0 0");
+
+                if ((pSysConfig->ModelName[10] == 'W') ||
+                        (pSysConfig->ModelName[10] == 'D')) {
+                    system("/sbin/ifmetric mlan0 1");
+                }
+
+                if ((pSysConfig->ModelName[10] == 'T') ||
+                        (pSysConfig->ModelName[10] == 'D')) {
+                    system("/sbin/ifmetric ppp0 2");
+                }
+            }
+
+            if (!ethResult &&
+                    pSysConfig->AthInterface.WifiMode != _SYS_WIFI_MODE_DISABLE &&
+                    (pSysConfig->ModelName[10] == 'W' ||
+                     pSysConfig->ModelName[10] == 'D')) {
+                //ethResult = pSysConfig->AthInterface.WifiNetworkConn;
+                ethResult = pInfoCode->InfoEvents.bits.InternetDisconnectViaWiFi == YES ? NO : YES;
+
+                if (ethResult) {
+                    if ((pSysConfig->ModelName[10] == 'W') ||
+                            (pSysConfig->ModelName[10] == 'D')) {
+                        system("/sbin/ifmetric eth0 1");
+                        system("/sbin/ifmetric mlan0 0");
+                    }
+
+
+                    if ((pSysConfig->ModelName[10] == 'T') ||
+                            (pSysConfig->ModelName[10] == 'D')) {
+                        system("/sbin/ifmetric ppp0 2");
+                    }
+                }
+            }
+
+            if (!ethResult &&
+                    pSysConfig->TelecomInterface.TelcomEnabled == YES &&
+                    (pSysConfig->ModelName[10] == 'T' ||
+                     pSysConfig->ModelName[10] == 'D')) {
+                //ethResult = pSysConfig->TelecomInterface.TelcomNetworkConn;
+                ethResult = pInfoCode->InfoEvents.bits.InternetDisconnectVia4Gi == YES ? NO : YES;
+
+                if (ethResult) {
+                    if ((pSysConfig->ModelName[10] == 'W') ||
+                            (pSysConfig->ModelName[10] == 'D')) {
+                        system("/sbin/ifmetric mlan0 2");
+                    }
+
+                    if ((pSysConfig->ModelName[10] == 'T') ||
+                            (pSysConfig->ModelName[10] == 'D')) {
+                        system("/sbin/ifmetric eth0 1");
+                        system("/sbin/ifmetric ppp0 0");
+                    }
+                }
+            }
+
+            pSysInfo->InternetConn = ethResult;
+#else
+            isReachableInternet();
+#endif //!defined DD360 && !defined DD360
+
+            sleep(5);
+        }
+    }
+
+    log_info("Initial Ethernet OK\r\n");
+}

+ 0 - 0
EVSE/Projects/DD360/Apps/CSU/Gpio.c


+ 56 - 129
EVSE/Projects/DD360/Apps/CSU/Primary.c

@@ -42,22 +42,22 @@ void PrimaryLedIndicatorCtrlFork(void)
     if (pid == 0) {
         uint8_t gunIndex = 0;
         int isContinue = 1;
-        LedConfig *pLedConfig = NULL;
+
         struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
         struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
-        struct WARNING_CODE_INFO *pSysWarningInfo = (struct WARNING_CODE_INFO *)GetShmSysWarningInfo();
+        struct WARNING_CODE_INFO *pSysWarning = (struct WARNING_CODE_INFO *)GetShmSysWarningInfo();
         struct PrimaryMcuData *ShmPrimaryMcuData = (struct PrimaryMcuData *)GetShmPrimaryMcuData();
-        struct ChargingInfoData *pDcChargingInfoData = NULL;
+        struct ChargingInfoData *pDcChargingInfo = NULL;
 
-        pLedConfig = (LedConfig *)&ShmPrimaryMcuData->OutputDrv.OutputDrvValue[0];
+        LedConfig *pLedConfig = (LedConfig *)&ShmPrimaryMcuData->OutputDrv.OutputDrvValue[0];
 
         while (isContinue) {
             for (gunIndex = 0; gunIndex < pSysConfig->TotalConnectorCount; gunIndex++) {
-                pDcChargingInfoData = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+                pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
 
-                //printf("led indicator status = %d\r\n", pDcChargingInfoData->SystemStatus);
-                //printf("level = %d\r\n", pSysWarningInfo->Level);
-                switch (pDcChargingInfoData->SystemStatus) {
+                //printf("led indicator status = %d\r\n", chargingInfo[gunIndex]->SystemStatus);
+                //printf("level = %d\r\n", pSysWarning->Level);
+                switch (pDcChargingInfo->SystemStatus) {
                 case S_BOOTING:
                     if (pSysInfo->SelfTestSeq == _STEST_COMPLETE) {
                         //Module_DoComm tcp disconnect
@@ -127,7 +127,7 @@ void PrimaryLedIndicatorCtrlFork(void)
 
                 case S_TERMINATING:
                 case S_COMPLETE:
-                    if (pSysWarningInfo->Level == 2) {
+                    if (pSysWarning->Level == 2) {
                         pLedConfig->YellowLED = NO;
                         pLedConfig->GreenLED = NO;
                         if (checkCabinetEthConnectState(pLedConfig) == YES) {
@@ -146,7 +146,7 @@ void PrimaryLedIndicatorCtrlFork(void)
                 case S_FAULT:
                     pLedConfig->YellowLED = NO;
                     pLedConfig->GreenLED = NO;
-                    if (pSysWarningInfo->Level == 2) {
+                    if (pSysWarning->Level == 2) {
                         if (checkCabinetEthConnectState(pLedConfig) == YES) {
                             break;
                         }
@@ -160,125 +160,47 @@ void PrimaryLedIndicatorCtrlFork(void)
                 case S_UPDATE:
                 case S_NONE:
                     break;
-                }//switch
+                }
 
-            } //for
-            usleep(500000);
-        } //while
-    } //fork
+                usleep(500000);
+            }//switch
+        }//for
+    }//while
 }
 
 //------------------------------------------------------------------------------
-// 急停狀況的停止充電處理函式
-void EmcOccureByString(char *code)
-{
-    uint8_t level = 2;
-    uint8_t gunIndex = 0;
-    struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
-    struct ChargingInfoData *pDcChargingInfoData = NULL;
-
-
-    // 嚴重的急停有以下幾種 : EMC 按鈕、Mainbreak、Dooropen
-    // 其錯誤等級為 2
-
-//#if defined DD360 ||defined DD360Audi || defined DD360ComBox
-//    //DS60-120 remove
-//    if (strncmp(code, "012251", 6) == EQUAL ||
-//            strncmp(code, "012252", 6) == EQUAL ||
-//            strncmp(code, "012238", 6) == EQUAL ||
-//            strncmp(code, "042251", 6) == EQUAL ||
-//            strncmp(code, "042252", 6) == EQUAL ||
-//            strncmp(code, "012304", 6) == EQUAL ||
-//            strncmp(code, "042200", 6) == EQUAL ||
-//            strncmp(code, "042201", 6) == EQUAL ||
-//            strncmp(code, "042202", 6) == EQUAL ||
-//            strncmp(code, "042267", 6) == EQUAL)
-//#endif //defined DD360 || defined DD360Audi
-    {
-        for (gunIndex = 0; gunIndex < pSysConfig->TotalConnectorCount; gunIndex++) {
-            pDcChargingInfoData = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
-
-            //strncpy((char *)ShmOCPP16Data->StatusNotification[gunIndex].VendorErrorCode, code, 6);
-
-            if ((pDcChargingInfoData->SystemStatus > S_IDLE &&
-                    pDcChargingInfoData->SystemStatus < S_TERMINATING) ||
-                    (pDcChargingInfoData->SystemStatus >= S_CCS_PRECHARGE_ST0 &&
-                     pDcChargingInfoData->SystemStatus <= S_CCS_PRECHARGE_ST1)) {
-                //ChargingTerminalProcess(gunIndex);
-                ChargingAlarmProcess(gunIndex);
-            }
-        }
-//#if defined DD360 ||defined DD360Audi || defined DD360ComBox
-        StopChargingProcessByString(level);
-        //InformOcppErrOccur(4);
-//#endif //defined DD360 || defined DD360Audi
-    }
-}
-
-void ReleaseEmsOccureByString(uint8_t index, char *code)
-{
-    bool isTrigger = false;
-    uint8_t level = 2;
-    struct AlarmCodeData *pAlarmCode = (struct AlarmCodeData *)GetShmAlarmCodeData();
-
-    if (strncmp(code, "042251", 6) == 0 ) {
-        isTrigger = true;
-    } else if (strncmp(code, "012251", 6) == 0 &&
-               pAlarmCode->AlarmEvents.bits.EmergencyStopTrip == YES) {
-        isTrigger = true;
-        pAlarmCode->AlarmEvents.bits.EmergencyStopTrip = NO;
-    } else if (strncmp(code, "012252", 6) == 0 &&
-               pAlarmCode->AlarmEvents.bits.DoorOpen == YES) {
-        isTrigger = true;
-        pAlarmCode->AlarmEvents.bits.DoorOpen = NO;
-    } else if (strncmp(code, "012237", 6) == 0 &&
-               pAlarmCode->AlarmEvents.bits.SpdTrip == YES) {
-        isTrigger = true;
-        pAlarmCode->AlarmEvents.bits.SpdTrip = NO;
-    } else if (strncmp(code, "012238", 6) == 0 &&
-               pAlarmCode->AlarmEvents.bits.MainPowerBreakerTrip == YES) {
-        isTrigger = true;
-        pAlarmCode->AlarmEvents.bits.MainPowerBreakerTrip = NO;
-    }
-
-    if (isTrigger) {
-        ReleaseChargingProcessByString(level);
-        InformOcppErrOccur(6);
-    }
-}
-
 void ChkPrimaryStatus(void)
 {
-    uint8_t Rtn;
     static bool leftBtnPush = false;
     static bool rightBtnPush = false;
+    uint8_t Rtn;
     struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
     struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
-    struct WARNING_CODE_INFO *pSysWarningInfo = (struct WARNING_CODE_INFO *)GetShmSysWarningInfo();
+    struct WARNING_CODE_INFO *pSysWarning = (struct WARNING_CODE_INFO *)GetShmSysWarningInfo();
     struct PrimaryMcuData *ShmPrimaryMcuData = (struct PrimaryMcuData *)GetShmPrimaryMcuData();
     struct AlarmCodeData *pAlarmCode = (struct AlarmCodeData *)GetShmAlarmCodeData();
-    struct ChargingInfoData *pDcChargingInfoData = NULL;
-    struct ChargingInfoData *pAcChargingInfoData = (struct ChargingInfoData *)GetAcChargingInfoData(0);
+    struct ChargingInfoData *pDcChargingInfo = NULL;
+    struct ChargingInfoData *pAcChargingInfo = NULL;
 
-    if (pSysWarningInfo->WarningCount > 0) {
+    if (pSysWarning->WarningCount > 0) {
         Rtn = 0;
-        for (uint8_t i = 0; i < pSysWarningInfo->WarningCount; i++) {
-            if (memcmp(&pSysWarningInfo->WarningCode[i][0], "042251", 6) == 0) {
+        for (uint8_t i = 0; i < pSysWarning->WarningCount; i++) {
+            if (memcmp(&pSysWarning->WarningCode[i][0], "042251", 6) == 0) {
                 EmcOccureByString("042251");
                 Rtn = 1;
-            } else if (memcmp(&pSysWarningInfo->WarningCode[i][0], "042252", 6) == 0) {
+            } else if (memcmp(&pSysWarning->WarningCode[i][0], "042252", 6) == 0) {
                 EmcOccureByString("042252");
                 Rtn = 1;
-            } else if (memcmp(&pSysWarningInfo->WarningCode[i][0], "042200", 6) == 0) {
+            } else if (memcmp(&pSysWarning->WarningCode[i][0], "042200", 6) == 0) {
                 EmcOccureByString("042200");
                 Rtn = 1;
-            } else if (memcmp(&pSysWarningInfo->WarningCode[i][0], "042201", 6) == 0) {
+            } else if (memcmp(&pSysWarning->WarningCode[i][0], "042201", 6) == 0) {
                 EmcOccureByString("042201");
                 Rtn = 1;
-            } else if (memcmp(&pSysWarningInfo->WarningCode[i][0], "042202", 6) == 0) {
+            } else if (memcmp(&pSysWarning->WarningCode[i][0], "042202", 6) == 0) {
                 EmcOccureByString("042202");
                 Rtn = 1;
-            } else if (memcmp(&pSysWarningInfo->WarningCode[i][0], "012304", 6) == 0) {
+            } else if (memcmp(&pSysWarning->WarningCode[i][0], "012304", 6) == 0) {
                 EmcOccureByString("012304");
                 Rtn = 1;
             }
@@ -335,17 +257,25 @@ void ChkPrimaryStatus(void)
     //    pSysConfig->ShowInformation = NO;
     //}
 
-    pDcChargingInfoData = (struct ChargingInfoData *)GetDcChargingInfoData(pSysInfo->CurGunSelected);
-
     if (ShmPrimaryMcuData->InputDet.bits.Button1 == BTN_PRESS &&
-            !leftBtnPush &&
-            WaitAuthorPageState()
+            !leftBtnPush
+#if defined DD360Audi
+            &&
+            pSysInfo->SystemPage != _LCM_AUTHORIZING &&
+            pSysInfo->SystemPage != _LCM_AUTHORIZ_COMP &&
+            pSysInfo->SystemPage != _LCM_AUTHORIZ_FAIL
+#endif //defined DD360Audi
        ) {
+        pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(pSysInfo->CurGunSelected);
+
         if (!leftBtnPush) {
             leftBtnPush = true;
-            log_info("left btn down...............................%x\n", pDcChargingInfoData->SystemStatus);
+            log_info("left btn down...............................%x\n",
+                     pDcChargingInfo->SystemStatus);
             if (pSysInfo->CurGunSelectedByAc != NO_DEFINE) {
-                switch (pAcChargingInfoData->SystemStatus) {
+                pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(0);
+
+                switch (pAcChargingInfo->SystemStatus) {
                 case S_IDLE:
                     if (isDetectPlugin()) {
                         _DetectPlugInTimeout();
@@ -376,17 +306,14 @@ void ChkPrimaryStatus(void)
                 }
             }
 
-            switch (pDcChargingInfoData->SystemStatus) {
+            switch (pDcChargingInfo->SystemStatus) {
             case S_IDLE:
                 if (isDetectPlugin()) {
                     _DetectPlugInTimeout();
                     StopSystemTimeoutDet();
-#if defined DD360Audi
                     destroySelGun(pSysInfo->CurGunSelected);
-#endif //defined DD360Audi
-                }
+                }             else {
 #if defined DD360Audi
-                else {
                     if (getConfirmSelectedGun(pSysInfo->CurGunSelected) == PASS) {
                         //printf("destroy gun = %d\r\n", pSysInfo->CurGunSelected);
                         destroySelGun(pSysInfo->CurGunSelected);
@@ -395,8 +322,9 @@ void ChkPrimaryStatus(void)
                         log_info("confirm select gun ............................... %d \n",
                                  pSysInfo->CurGunSelected);
                     }
-                }
+
 #endif //defined DD360Audi
+                }
                 break;
 
             case S_REASSIGN_CHECK:
@@ -425,7 +353,7 @@ void ChkPrimaryStatus(void)
             case S_COMPLETE:
                 // 回 IDLE
                 //log_info("right btn down.................S_COMPLETE \n");
-                //pDcChargingInfoData->SystemStatus = S_IDLE;
+                //pDcChargingInfo->SystemStatus = S_IDLE;
                 break;
             }
         }
@@ -440,18 +368,17 @@ void ChkPrimaryStatus(void)
             !rightBtnPush
 #if defined DD360Audi
             &&
-            getCurLcmPage() != _LCM_IDLE &&
-            getCurLcmPage() != _LCM_AUTHORIZING &&
-            getCurLcmPage() != _LCM_AUTHORIZ_COMP &&
-            getCurLcmPage() != _LCM_AUTHORIZ_FAIL &&
-            getCurLcmPage() != _LCM_WAIT_FOR_PLUG
+            pSysInfo->SystemPage != _LCM_IDLE &&
+            pSysInfo->SystemPage != _LCM_AUTHORIZING &&
+            pSysInfo->SystemPage != _LCM_AUTHORIZ_COMP &&
+            pSysInfo->SystemPage != _LCM_AUTHORIZ_FAIL &&
+            pSysInfo->SystemPage != _LCM_WAIT_FOR_PLUG
 #endif //defined DD360Audi
        ) {
         if (!rightBtnPush) {
             rightBtnPush = true;
             //log_info("right btn down............................... %d \n", pSysInfo->CurGunSelected);
-            if (pSysInfo->CurGunSelected + 1 <
-                    pSysConfig->TotalConnectorCount &&
+            if (pSysInfo->CurGunSelected + 1 < pSysConfig->TotalConnectorCount &&
                     pSysInfo->IsAlternatvieConf == NO) {
                 pSysInfo->CurGunSelected++;
                 ChangeGunSelectByIndex(pSysInfo->CurGunSelected);
@@ -460,11 +387,11 @@ void ChkPrimaryStatus(void)
                 pSysInfo->CurGunSelectedByAc = DEFAULT_AC_INDEX;
             } else if (pSysInfo->IsAlternatvieConf == YES) {
                 for (uint8_t _index = 0; _index < pSysConfig->TotalConnectorCount; _index++) {
-                    pDcChargingInfoData = (struct ChargingInfoData *)GetDcChargingInfoData(_index);
+                    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_index);
 
-                    if (pDcChargingInfoData->SystemStatus != S_BOOTING &&
-                            pDcChargingInfoData->SystemStatus != S_IDLE &&
-                            pDcChargingInfoData->SystemStatus != S_RESERVATION) {
+                    if (pDcChargingInfo->SystemStatus != S_BOOTING &&
+                            pDcChargingInfo->SystemStatus != S_IDLE &&
+                            pDcChargingInfo->SystemStatus != S_RESERVATION) {
                         pSysInfo->CurGunSelected = _index;
                         ChangeGunSelectByIndex(pSysInfo->CurGunSelected);
                         return;

+ 247 - 152
EVSE/Projects/DD360/Apps/CSU/RFID.c

@@ -7,19 +7,55 @@
 #include "../Log/log.h"
 #include "../Define/define.h"
 #include "../ShareMemory/shmMem.h"
+#include "../SelectGun/SelectGun.h"
+
+#include "../main.h"
+#include "../timeout.h"
+
+//------------------------------------------------------------------------------
+static char *rfidPortName = "/dev/ttyS2";
+
+static bool isCardScan = false;
 
 //------------------------------------------------------------------------------
+static bool canStartCharging(void)
+{
+    char buf2[16] = "";
+    memset(buf2, 0, ARRAY_SIZE(buf2));
+    struct OCPP16Data *ShmOCPP16Data = (struct OCPP16Data *)GetShmOCPP16Data();
+
+    for (uint8_t index = 0; index < strlen((char *)ShmOCPP16Data->Authorize.ResponseIdTagInfo.Status); index++) {
+        sprintf(buf2 + (index - 1) * 2, "%02X", ShmOCPP16Data->Authorize.ResponseIdTagInfo.Status[index]);
+    }
+    sprintf(buf2, "%s", ShmOCPP16Data->Authorize.ResponseIdTagInfo.Status);
+
+    // 因為無法得知實際的長度,所以只能用搜尋的方式
+    if (strcmp(buf2, "Accepted") == EQUAL) {
+        return true;
+    } else {
+
+    }
+
+    return false;
+}
+
 static void UserScanFunction(void)
 {
     bool idleReq = false;
-    uint8_t stopReq = 255;
+    uint8_t stopReq = NO_DEFINE;
+    static uint8_t _authorizeIndex = NO_DEFINE;
+    struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
+    struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
+    struct ChargingInfoData *pAcChargingInfo =  (struct ChargingInfoData *)GetAcChargingInfoData(0);
+    struct ChargingInfoData *pDcChargingInfo = NULL;
+    GunIndexInfo *pGunIndexInfo = (GunIndexInfo *)GetGunIndexInfo();
 
     // 當前非驗證的狀態
     if (!IsAuthorizingMode()) {
 #if defined DD360Audi
         //當前沒有選槍
-        if (getConfirmSelectedGun(ShmSysConfigAndInfo->SysInfo.CurGunSelected) == FAIL) { //Jerry add
-            strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+        if (getConfirmSelectedGun(pSysInfo->CurGunSelected) == FAIL) { //Jerry add
+            strcpy((char *)pSysConfig->UserId, "");
             return;
         }
 #endif //defined DD360Audi
@@ -27,139 +63,145 @@ static void UserScanFunction(void)
         // 先判斷現在是否可以提供刷卡
         // 1. 如果當前沒有槍是閒置狀態,則無提供刷卡功能
         // 2. 停止充電
-        if (ShmSysConfigAndInfo->SysInfo.PageIndex == _LCM_FIX) {
-            strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+        if (pSysInfo->PageIndex == _LCM_FIX) {
+            strcpy((char *)pSysConfig->UserId, "");
             return;
         }
 
-        for (uint8_t i = 0; i < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; i++) {
-            if (chargingInfo[i]->SystemStatus == S_CHARGING) {
+        for (uint8_t i = 0; i < pSysConfig->TotalConnectorCount; i++) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(i);
+
+            if (pDcChargingInfo->SystemStatus == S_CHARGING) {
                 stopReq = i;
             }
-            if ((chargingInfo[i]->SystemStatus == S_IDLE &&
-                    chargingInfo[i]->IsAvailable) == YES ||
-                    (_acgunIndex > 0 && ac_chargingInfo[0]->SystemStatus ==
-                     S_IDLE && ac_chargingInfo[0]->IsAvailable)
+            if ((pDcChargingInfo->SystemStatus == S_IDLE &&
+                    pDcChargingInfo->IsAvailable) == YES ||
+                    (pGunIndexInfo->AcGunIndex > 0 && pAcChargingInfo->SystemStatus ==
+                     S_IDLE && pAcChargingInfo->IsAvailable)
                ) {
                 idleReq = true;
             }
         }
 
-        if (_acgunIndex > 0 && ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc == DEFAULT_AC_INDEX &&
-                ac_chargingInfo[0]->SystemStatus == S_CHARGING) {
+        if (pGunIndexInfo->AcGunIndex > 0 && pSysInfo->CurGunSelectedByAc == DEFAULT_AC_INDEX &&
+                pAcChargingInfo->SystemStatus == S_CHARGING) {
             stopReq = DEFAULT_AC_INDEX;
         }
 
-        if (strlen((char *)ShmSysConfigAndInfo->SysConfig.UserId) > 0) {
-            if (_acgunIndex > 0 && stopReq == DEFAULT_AC_INDEX &&
-                    ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc == DEFAULT_AC_INDEX) {
+        if (strlen((char *)pSysConfig->UserId) > 0) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(pSysInfo->CurGunSelected);
+
+            if (pGunIndexInfo->AcGunIndex > 0 && stopReq == DEFAULT_AC_INDEX &&
+                    pSysInfo->CurGunSelectedByAc == DEFAULT_AC_INDEX) {
                 char value[32];
 
                 log_info("ac stop charging \n");
-                log_info("index = %d, card number = %s, UserId = %s \n", ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc,
-                         ac_chargingInfo[0]->StartUserId, ShmSysConfigAndInfo->SysConfig.UserId);
-                memcpy(value, (uint8_t *)ac_chargingInfo[0]->StartUserId,
-                       ARRAY_SIZE(ac_chargingInfo[0]->StartUserId));
-                if (strcmp((char *)ShmSysConfigAndInfo->SysConfig.UserId, value) == EQUAL) {
+                log_info("index = %d, card number = %s, UserId = %s \n", pSysInfo->CurGunSelectedByAc,
+                         pAcChargingInfo->StartUserId, pSysConfig->UserId);
+                memcpy(value, (uint8_t *)pAcChargingInfo->StartUserId,
+                       ARRAY_SIZE(pAcChargingInfo->StartUserId));
+                if (strcmp((char *)pSysConfig->UserId, value) == EQUAL) {
                     AcChargingTerminalProcess();
                 }
-                strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
-            } else if (stopReq < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount &&
-                       chargingInfo[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus == S_CHARGING &&
-                       (_acgunIndex <= 0 || (_acgunIndex > 0 && ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc == NO_DEFINE))) {
+                strcpy((char *)pSysConfig->UserId, "");
+            } else if (stopReq < pSysConfig->TotalConnectorCount &&
+                       pDcChargingInfo->SystemStatus == S_CHARGING &&
+                       (pGunIndexInfo->AcGunIndex <= 0 || (pGunIndexInfo->AcGunIndex > 0 && pSysInfo->CurGunSelectedByAc == NO_DEFINE))) {
                 char value[32];
 
                 log_info("stop charging \n");
                 log_info("index = %d, card number = %s, UserId = %s \n",
-                         ShmSysConfigAndInfo->SysInfo.CurGunSelected,
-                         chargingInfo[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->StartUserId,
-                         ShmSysConfigAndInfo->SysConfig.UserId);
-                memcpy(value, (uint8_t *)chargingInfo[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->StartUserId,
-                       ARRAY_SIZE(chargingInfo[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->StartUserId));
+                         pSysInfo->CurGunSelected,
+                         pDcChargingInfo->StartUserId,
+                         pSysConfig->UserId);
+                memcpy(value, (uint8_t *)pDcChargingInfo->StartUserId,
+                       ARRAY_SIZE(pDcChargingInfo->StartUserId));
 
                 // 同一張卡直接停掉
-                if (strcmp((char *)ShmSysConfigAndInfo->SysConfig.UserId, value) == EQUAL) {
-                    ChargingTerminalProcess(ShmSysConfigAndInfo->SysInfo.CurGunSelected);
-                    strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                if (strcmp((char *)pSysConfig->UserId, value) == EQUAL) {
+                    ChargingTerminalProcess(pSysInfo->CurGunSelected);
+                    strcpy((char *)pSysConfig->UserId, "");
                 } else {
                     // 進驗證
-                    if (_acgunIndex > 0 && ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc == DEFAULT_AC_INDEX) {
-                        _authorizeIndex = ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc;
+                    if (pGunIndexInfo->AcGunIndex > 0 && pSysInfo->CurGunSelectedByAc == DEFAULT_AC_INDEX) {
+                        _authorizeIndex = pSysInfo->CurGunSelectedByAc;
                     } else {
-                        _authorizeIndex = ShmSysConfigAndInfo->SysInfo.CurGunSelected;
+                        _authorizeIndex = pSysInfo->CurGunSelected;
                     }
 #if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
                     StartSystemTimeoutDet(Timeout_AuthorizingForStop);
                     AuthorizingStart();
 #else
-                    strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                    strcpy((char *)pSysConfig->UserId, "");
 #endif //!defined DD360 && !defined DD360Audi
                 }
             } else if (idleReq) {
-                if (ShmSysConfigAndInfo->SysConfig.TotalConnectorCount > 1 &&
+                if (pSysConfig->TotalConnectorCount > 1 &&
                         stopReq != 255 &&
-                        ShmSysConfigAndInfo->SysInfo.IsAlternatvieConf == YES) {
+                        pSysInfo->IsAlternatvieConf == YES) {
                     idleReq = false;
-                    strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
-                } else if ((_acgunIndex > 0 && ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc == DEFAULT_AC_INDEX) ||
-                           chargingInfo[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus == S_IDLE) {
+                    strcpy((char *)pSysConfig->UserId, "");
+                } else if ((pGunIndexInfo->AcGunIndex > 0 && pSysInfo->CurGunSelectedByAc == DEFAULT_AC_INDEX) ||
+                           pDcChargingInfo->SystemStatus == S_IDLE) {
                     log_info("// LCM => Authorizing \n");
 #if defined DD360Audi
-                    setSelGunWaitToAuthor(ShmSysConfigAndInfo->SysInfo.CurGunSelected); //Jerry add
+                    setSelGunWaitToAuthor(pSysInfo->CurGunSelected); //Jerry add
 #endif //defined DD360Audi
                     // LCM => Authorizing
-                    ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_AUTHORIZING;
+                    pSysInfo->SystemPage = _LCM_AUTHORIZING;
                     // 進入確認卡號狀態
                     AuthorizingStart();
                 } else {
-                    strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                    strcpy((char *)pSysConfig->UserId, "");
                 }
             } else {
-                strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                strcpy((char *)pSysConfig->UserId, "");
             }
         }
     } else {
         // 透過後臺停止充電的判斷
         if (isAuthorizedComplete()
 #if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
-                || (ShmSysConfigAndInfo->SysInfo.OcppConnStatus == NO &&
-                    ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING)
+                || (pSysInfo->OcppConnStatus == NO &&
+                    pSysConfig->OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING)
 #endif //!defined DD360 && !defined DD360Audi
            ) {
             // 判斷後台回覆狀態
             if (canStartCharging()
 #if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
-                    || (ShmSysConfigAndInfo->SysInfo.OcppConnStatus == NO &&
-                        ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING)
+                    || (pSysInfo->OcppConnStatus == NO &&
+                        pSysConfig->OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING)
 #endif //!defined DD360 && !defined DD360Audi
                ) {
                 if (_authorizeIndex != NO_DEFINE) {
+                    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_authorizeIndex);
+
                     // 先找 AC
                     if (_authorizeIndex == DEFAULT_AC_INDEX) {
-                        if (ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST &&
-                                strcmp((char *)chargingInfo[_authorizeIndex]->StartUserId, "") != EQUAL) {
+                        if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST &&
+                                strcmp((char *)pDcChargingInfo->StartUserId, "") != EQUAL) {
                             AcChargingTerminalProcess();
                         }
                     } else {
-                        if (ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST &&
-                                strcmp((char *)chargingInfo[_authorizeIndex]->StartUserId, "") != EQUAL) {
+                        if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST &&
+                                strcmp((char *)pDcChargingInfo->StartUserId, "") != EQUAL) {
                             ChargingTerminalProcess(_authorizeIndex);
                         }
                     }
-                    strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                    strcpy((char *)pSysConfig->UserId, "");
                     _authorizeIndex = NO_DEFINE;
                 }
             } else {
-                strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                strcpy((char *)pSysConfig->UserId, "");
             }
             ClearAuthorizedFlag();
-        } else if (ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST) {
+        } else if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST) {
             // 白名單驗證
             for (int i = 0; i < 10; i++) {
-                if (strcmp((char *)ShmSysConfigAndInfo->SysConfig.LocalWhiteCard[i], "") != EQUAL) {
-                    if (strcmp((char *)ShmSysConfigAndInfo->SysConfig.LocalWhiteCard[i], (char *)ShmSysConfigAndInfo->SysConfig.UserId) == EQUAL) {
+                if (strcmp((char *)pSysConfig->LocalWhiteCard[i], "") != EQUAL) {
+                    if (strcmp((char *)pSysConfig->LocalWhiteCard[i], (char *)pSysConfig->UserId) == EQUAL) {
                         ChargingTerminalProcess(_authorizeIndex);
-                        strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                        strcpy((char *)pSysConfig->UserId, "");
                         ClearAuthorizedFlag();
                         break;
                     }
@@ -169,152 +211,205 @@ static void UserScanFunction(void)
     }
 }
 
-void ScannerCardProcess()
+bool GetIsCardScan(void)
+{
+    return isCardScan;
+}
+
+void SetIsCardScan(bool value)
+{
+    isCardScan = value;
+}
+
+void ScannerCardProcess(void)
 {
-    if (!isDetectPlugin() && !isCardScan && ShmSysConfigAndInfo->SysWarningInfo.Level != 2 &&
-            ShmSysConfigAndInfo->SysConfig.AuthorisationMode == AUTH_MODE_ENABLE) {
+    struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
+    struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
+    struct WARNING_CODE_INFO *pSysWarning = (struct WARNING_CODE_INFO *)GetShmSysWarningInfo();
+    SelectGunInfo *ShmSelectGunInfo = (SelectGunInfo *)GetShmSelectGunInfo();
+
+    if (!isDetectPlugin() && !isCardScan && pSysWarning->Level != 2 &&
+            pSysConfig->AuthorisationMode == AUTH_MODE_ENABLE) {
         isCardScan = true;
         // 處理刷卡及驗證卡號的動作
         UserScanFunction();
     }
 
-    if (ShmSysConfigAndInfo->SysInfo.PageIndex == _LCM_AUTHORIZING) {
+    if (pSysInfo->PageIndex == _LCM_AUTHORIZING) {
         StartSystemTimeoutDet(Timeout_Authorizing);
 
         // 確認驗證卡號完成沒
         if (isAuthorizedComplete()
 #if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
-                || ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING
+                || pSysConfig->OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING
 #else
-                && gAudiCustInfo->PricesInfo[ShmSysConfigAndInfo->SysInfo.CurGunSelected].Balance != FAIL_BALANCE_PRICES
+                && ShmSelectGunInfo->PricesInfo[pSysInfo->CurGunSelected].Balance != FAIL_BALANCE_PRICES
 #endif //!defined DD360 && !defined DD360Audi
            ) {
             StopSystemTimeoutDet();
             // 判斷後台回覆狀態
             if (canStartCharging()
 #if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
-                    || ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING
+                    || pSysConfig->OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING
 #endif //!defined DD360 && !defined DD360Audi
                ) {
                 // LCM => Authorize complete
-                ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_AUTHORIZ_COMP;
+                pSysInfo->SystemPage = _LCM_AUTHORIZ_COMP;
             } else {
                 // LCM => Authorize fail
-                ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_AUTHORIZ_FAIL;
-                strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                pSysInfo->SystemPage = _LCM_AUTHORIZ_FAIL;
+                strcpy((char *)pSysConfig->UserId, "");
             }
             ClearAuthorizedFlag();
-        } else if (ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST) {
+        } else if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST) {
             // 白名單驗證
             for (int i = 0; i < 10; i++) {
-                if (strcmp((char *)ShmSysConfigAndInfo->SysConfig.LocalWhiteCard[i], "") != EQUAL) {
-                    if (strcmp((char *)ShmSysConfigAndInfo->SysConfig.LocalWhiteCard[i], (char *)ShmSysConfigAndInfo->SysConfig.UserId) == EQUAL) {
-                        ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_AUTHORIZ_COMP;
+                if (strcmp((char *)pSysConfig->LocalWhiteCard[i], "") != EQUAL) {
+                    if (strcmp((char *)pSysConfig->LocalWhiteCard[i], (char *)pSysConfig->UserId) == EQUAL) {
+                        pSysInfo->SystemPage = _LCM_AUTHORIZ_COMP;
                         ClearAuthorizedFlag();
                         break;
                     }
                 }
             }
         }
-    } else if (ShmSysConfigAndInfo->SysInfo.PageIndex == _LCM_AUTHORIZ_FAIL) {
+    } else if (pSysInfo->PageIndex == _LCM_AUTHORIZ_FAIL) {
         StartSystemTimeoutDet(Timeout_VerifyFail);
         isCardScan = false;
-    } else if (ShmSysConfigAndInfo->SysInfo.PageIndex == _LCM_AUTHORIZ_COMP) {
+    } else if (pSysInfo->PageIndex == _LCM_AUTHORIZ_COMP) {
         StartSystemTimeoutDet(Timeout_VerifyComp);
-    } else if (ShmSysConfigAndInfo->SysInfo.PageIndex == _LCM_WAIT_FOR_PLUG) {
+    } else if (pSysInfo->PageIndex == _LCM_WAIT_FOR_PLUG) {
         StartSystemTimeoutDet(Timeout_WaitPlug);
     } else {
         isCardScan = false;
     }
 }
 
-void CreateRfidFork()
+
+static int InitialRfidPort(void)
+{
+    int fd = open(rfidPortName, O_RDWR);
+    struct termios tios;
+    struct AlarmCodeData *pAlarmCode = (struct AlarmCodeData *)GetShmAlarmCodeData();
+
+    if (fd != FAIL) {
+        ioctl (fd, TCGETS, &tios);
+        tios.c_cflag = B19200 | CS8 | CLOCAL | CREAD;
+        tios.c_lflag = 0;
+        tios.c_iflag = 0;
+        tios.c_oflag = 0;
+        tios.c_cc[VMIN] = 0;
+        tios.c_cc[VTIME] = (uint8_t) 1;
+        tios.c_lflag = 0;
+        tcflush(fd, TCIFLUSH);
+        ioctl(fd, TCSETS, &tios);
+    }
+
+    if (fd < 0) {
+        pAlarmCode->AlarmEvents.bits.RfidModuleCommFail = 1;
+    }
+
+    return fd;
+}
+
+void CreateRfidFork(void)
 {
     pid_t rfidRecPid;
 
     rfidRecPid = fork();
     log_info("CreateRfidFork = %d\r\n", rfidRecPid);
     if (rfidRecPid == 0) {
+        int fd = -1;
+        RFID rfid = {0};
+        fd = InitialRfidPort();
+        struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
+
         while (true) {
             // 刷卡判斷
-            RFID rfid;
-            if (ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_NO_CHARGING ||
-                    !ShmSysConfigAndInfo->SysConfig.isRFID)
-            {}
-            else if (getRequestCardSN(rfidFd, 0, &rfid)) {
-                //log_info("Get Card..-%s- \n", ShmSysConfigAndInfo->SysConfig.UserId);
-                if (strlen((char *)ShmSysConfigAndInfo->SysConfig.UserId) == 0) {
-                    if (ShmSysConfigAndInfo->SysConfig.RfidCardNumEndian == RFID_ENDIAN_LITTLE) {
-                        switch (rfid.snType) {
-                        case RFID_SN_TYPE_6BYTE:
-                            sprintf((char *) ShmSysConfigAndInfo->SysConfig.UserId,
-                                    "%02X%02X%02X%02X%02X%02X",
-                                    rfid.currentCard[0], rfid.currentCard[1],
-                                    rfid.currentCard[2], rfid.currentCard[3],
-                                    rfid.currentCard[4], rfid.currentCard[5]);
-                            break;
-                        case RFID_SN_TYPE_7BYTE:
-                            sprintf((char *) ShmSysConfigAndInfo->SysConfig.UserId,
-                                    "%02X%02X%02X%02X%02X%02X%02X",
-                                    rfid.currentCard[0], rfid.currentCard[1],
-                                    rfid.currentCard[2], rfid.currentCard[3],
-                                    rfid.currentCard[4], rfid.currentCard[5],
-                                    rfid.currentCard[6]);
-                            break;
-                        case RFID_SN_TYPE_10BYTE:
-                            sprintf((char *) ShmSysConfigAndInfo->SysConfig.UserId,
-                                    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
-                                    rfid.currentCard[0], rfid.currentCard[1],
-                                    rfid.currentCard[2], rfid.currentCard[3],
-                                    rfid.currentCard[4], rfid.currentCard[5],
-                                    rfid.currentCard[6], rfid.currentCard[7],
-                                    rfid.currentCard[8], rfid.currentCard[9]);
-                            break;
-                        case RFID_SN_TYPE_4BYTE:
-                            sprintf((char *) ShmSysConfigAndInfo->SysConfig.UserId,
-                                    "%02X%02X%02X%02X",
-                                    rfid.currentCard[0], rfid.currentCard[1],
-                                    rfid.currentCard[2], rfid.currentCard[3]);
-                            break;
-                        }
-                    } else if (ShmSysConfigAndInfo->SysConfig.RfidCardNumEndian == RFID_ENDIAN_BIG) {
-                        switch (rfid.snType) {
-                        case RFID_SN_TYPE_6BYTE:
-                            sprintf((char *) ShmSysConfigAndInfo->SysConfig.UserId,
-                                    "%02X%02X%02X%02X%02X%02X",
-                                    rfid.currentCard[5], rfid.currentCard[4],
-                                    rfid.currentCard[3], rfid.currentCard[2],
-                                    rfid.currentCard[1], rfid.currentCard[0]);
-                            break;
-                        case RFID_SN_TYPE_7BYTE:
-                            sprintf((char *) ShmSysConfigAndInfo->SysConfig.UserId,
-                                    "%02X%02X%02X%02X%02X%02X%02X",
-                                    rfid.currentCard[6], rfid.currentCard[5],
-                                    rfid.currentCard[4], rfid.currentCard[3],
-                                    rfid.currentCard[2], rfid.currentCard[1],
-                                    rfid.currentCard[0]);
-                            break;
-                        case RFID_SN_TYPE_10BYTE:
-                            sprintf((char *) ShmSysConfigAndInfo->SysConfig.UserId,
-                                    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
-                                    rfid.currentCard[9], rfid.currentCard[8],
-                                    rfid.currentCard[7], rfid.currentCard[6],
-                                    rfid.currentCard[5], rfid.currentCard[4],
-                                    rfid.currentCard[3], rfid.currentCard[2],
-                                    rfid.currentCard[1], rfid.currentCard[0]);
-                            break;
-                        case RFID_SN_TYPE_4BYTE:
-                            sprintf((char *) ShmSysConfigAndInfo->SysConfig.UserId,
-                                    "%02X%02X%02X%02X",
-                                    rfid.currentCard[3], rfid.currentCard[2],
-                                    rfid.currentCard[1], rfid.currentCard[0]);
-                            break;
-                        }
+            if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_NO_CHARGING ||
+                    !pSysConfig->isRFID) {
+                usleep(500000);
+                continue;
+            }
+
+            if (getRequestCardSN(fd, 0, &rfid) == false) {
+                usleep(500000);
+                continue;
+            }
+
+            //log_info("Get Card..-%s- \n", pSysConfig->UserId);
+            if (strlen((char *)pSysConfig->UserId) == 0) {
+                if (pSysConfig->RfidCardNumEndian == RFID_ENDIAN_LITTLE) {
+                    switch (rfid.snType) {
+                    case RFID_SN_TYPE_6BYTE:
+                        sprintf((char *) pSysConfig->UserId,
+                                "%02X%02X%02X%02X%02X%02X",
+                                rfid.currentCard[0], rfid.currentCard[1],
+                                rfid.currentCard[2], rfid.currentCard[3],
+                                rfid.currentCard[4], rfid.currentCard[5]);
+                        break;
+                    case RFID_SN_TYPE_7BYTE:
+                        sprintf((char *) pSysConfig->UserId,
+                                "%02X%02X%02X%02X%02X%02X%02X",
+                                rfid.currentCard[0], rfid.currentCard[1],
+                                rfid.currentCard[2], rfid.currentCard[3],
+                                rfid.currentCard[4], rfid.currentCard[5],
+                                rfid.currentCard[6]);
+                        break;
+                    case RFID_SN_TYPE_10BYTE:
+                        sprintf((char *) pSysConfig->UserId,
+                                "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
+                                rfid.currentCard[0], rfid.currentCard[1],
+                                rfid.currentCard[2], rfid.currentCard[3],
+                                rfid.currentCard[4], rfid.currentCard[5],
+                                rfid.currentCard[6], rfid.currentCard[7],
+                                rfid.currentCard[8], rfid.currentCard[9]);
+                        break;
+                    case RFID_SN_TYPE_4BYTE:
+                        sprintf((char *) pSysConfig->UserId,
+                                "%02X%02X%02X%02X",
+                                rfid.currentCard[0], rfid.currentCard[1],
+                                rfid.currentCard[2], rfid.currentCard[3]);
+                        break;
+                    }
+                } else if (pSysConfig->RfidCardNumEndian == RFID_ENDIAN_BIG) {
+                    switch (rfid.snType) {
+                    case RFID_SN_TYPE_6BYTE:
+                        sprintf((char *) pSysConfig->UserId,
+                                "%02X%02X%02X%02X%02X%02X",
+                                rfid.currentCard[5], rfid.currentCard[4],
+                                rfid.currentCard[3], rfid.currentCard[2],
+                                rfid.currentCard[1], rfid.currentCard[0]);
+                        break;
+                    case RFID_SN_TYPE_7BYTE:
+                        sprintf((char *) pSysConfig->UserId,
+                                "%02X%02X%02X%02X%02X%02X%02X",
+                                rfid.currentCard[6], rfid.currentCard[5],
+                                rfid.currentCard[4], rfid.currentCard[3],
+                                rfid.currentCard[2], rfid.currentCard[1],
+                                rfid.currentCard[0]);
+                        break;
+                    case RFID_SN_TYPE_10BYTE:
+                        sprintf((char *) pSysConfig->UserId,
+                                "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
+                                rfid.currentCard[9], rfid.currentCard[8],
+                                rfid.currentCard[7], rfid.currentCard[6],
+                                rfid.currentCard[5], rfid.currentCard[4],
+                                rfid.currentCard[3], rfid.currentCard[2],
+                                rfid.currentCard[1], rfid.currentCard[0]);
+                        break;
+                    case RFID_SN_TYPE_4BYTE:
+                        sprintf((char *) pSysConfig->UserId,
+                                "%02X%02X%02X%02X",
+                                rfid.currentCard[3], rfid.currentCard[2],
+                                rfid.currentCard[1], rfid.currentCard[0]);
+                        break;
                     }
-                    log_info("card number = %s\n", ShmSysConfigAndInfo->SysConfig.UserId);
                 }
+                log_info("card number = %s\n", pSysConfig->UserId);
             }
             usleep(500000);
         }
     }
 }
+

+ 215 - 0
EVSE/Projects/DD360/Apps/CSU/SelfTest.c

@@ -0,0 +1,215 @@
+#include <stdio.h>      /*標準輸入輸出定義*/
+#include <stdlib.h>     /*標準函數庫定義*/
+#include <string.h>
+#include <stdint.h>
+
+#include "../Config.h"
+#include "../Log/log.h"
+#include "../Define/define.h"
+#include "../ShareMemory/shmMem.h"
+
+#include "../main.h"
+#include "../timeout.h"
+
+//------------------------------------------------------------------------------
+extern void ChkPrimaryStatus(void);
+
+//------------------------------------------------------------------------------
+void SelfTestRun(void)
+{
+    bool evInitFlag = false;
+    struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
+    struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
+    struct WARNING_CODE_INFO *pSysWarning = (struct WARNING_CODE_INFO *)GetShmSysWarningInfo();
+
+    struct PsuData *ShmPsuData = (struct PsuData *)GetShmPsuData();
+    struct CHAdeMOData *ShmCHAdeMOData = (struct CHAdeMOData *)GetShmCHAdeMOData();
+    struct GBTData *ShmGBTData = (struct GBTData *)GetShmGBTData();
+    struct CcsData *ShmCcsData = (struct CcsData *)GetShmCcsData();
+
+    struct PrimaryMcuData *ShmPrimaryMcuData = (struct PrimaryMcuData *)GetShmPrimaryMcuData();
+    struct FanModuleData *ShmFanModuleData = (struct FanModuleData *)GetShmFanModuleData();
+    struct RelayModuleData *ShmRelayModuleData = (struct RelayModuleData *)GetShmRelayModuleData();
+    struct ChargingInfoData *pDcChargingInfo = NULL;
+    struct ChargingInfoData *pAcChargingInfo = NULL;
+
+    StartSystemTimeoutDet(Timeout_SelftestChk);
+    pSysInfo->SelfTestSeq = _STEST_VERSION;
+
+    while (pSysInfo->SelfTestSeq != _STEST_COMPLETE //||
+            //GetTimeoutValue(pSysInfo->SystemTimeoutTimer) / uSEC_VAL <= 20 //DS60-120 add
+          ) {
+        if (pSysInfo->SelfTestSeq == _STEST_COMPLETE) {
+            return;
+        }
+
+        ChkPrimaryStatus();
+        if (pSysWarning->Level == 2 //||
+                //pAlarmCode->AlarmEvents.bits.PsuDipSwitchStestFail == YES //DS60-120 add
+           ) {
+            pSysInfo->SelfTestSeq = _STEST_FAIL;
+            return;
+        }
+
+        if (pSysConfig->TotalConnectorCount > 0) {
+            if (ShmPsuData->Work_Step == _NO_WORKING ||
+                    pSysInfo->SelfTestSeq == _STEST_FAIL) {
+                pSysInfo->SelfTestSeq = _STEST_FAIL;
+                return;
+            }
+
+            switch (pSysInfo->SelfTestSeq) {
+            case _STEST_VERSION: {
+                if ((strlen((char *)pSysInfo->RelayModuleFwRev) != 0 ||
+                        pSysInfo->RelayModuleFwRev[0] != '\0')
+                        && (ShmRelayModuleData->SelfTest_Comp != YES)
+                   ) {
+                    log_info("Relay Board FW Rev = %s", pSysInfo->RelayModuleFwRev);
+                    ShmRelayModuleData->SelfTest_Comp = YES;
+                }
+#if !defined NO_FAN_BOARD && !defined DD360ComBox
+                if ((strlen((char *)pSysInfo->FanModuleFwRev) != 0 ||
+                        pSysInfo->FanModuleFwRev[0] != '\0')
+                        && (ShmFanModuleData->SelfTest_Comp != YES)
+                   ) {
+                    log_info("Fan Board FW Rev = %s", pSysInfo->FanModuleFwRev);
+                    ShmFanModuleData->SelfTest_Comp = YES;
+                }
+#else
+                ShmFanModuleData->SelfTest_Comp = YES;
+#endif //NO_FAN_BOARD
+
+                if ((strlen((char *)ShmPrimaryMcuData->version) != 0 ||
+                        ShmPrimaryMcuData->version[0] != '\0')
+                        && (ShmPrimaryMcuData->SelfTest_Comp != YES)
+                   ) {
+                    log_info("Primary FW Rev = %s", pSysInfo->CsuPrimFwRev);
+                    ShmPrimaryMcuData->SelfTest_Comp = YES;
+                }
+
+                // EV 小板
+                if (!evInitFlag) {
+                    evInitFlag = YES;
+                    for (uint8_t index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+                        pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+                        //log_info("index = %d, charging index = %d, type = %d\r\n",
+                        //         index,
+                        //         chargingInfo[index]->type_index,
+                        //         chargingInfo[index]->Type);
+                        if (pDcChargingInfo->Type == _Type_Chademo) {
+                            if ((strlen((char *)ShmCHAdeMOData->evse[pDcChargingInfo->type_index].version) != 0 ||
+                                    ShmCHAdeMOData->evse[pDcChargingInfo->type_index].version[0] != '\0')
+                                    //&& (ShmCHAdeMOData->evse[pDcChargingInfo->type_index].SelfTest_Comp != YES)
+                               ) {
+                                log_info("CHAdeMO[%d] FW Rev = %s", pDcChargingInfo->type_index, ShmCHAdeMOData->evse[pDcChargingInfo->type_index].version);
+                                ShmCHAdeMOData->evse[pDcChargingInfo->type_index].SelfTest_Comp = YES;
+                            } else {
+                                //log_info("chademo fw lose...... %s \n", ShmCHAdeMOData->evse[pDcChargingInfo->type_index].version);
+                                evInitFlag = NO;
+                            }
+                        } else if (pDcChargingInfo->Type == _Type_GB) {
+                            if ((strlen((char *)ShmGBTData->evse[pDcChargingInfo->type_index].version) != 0 ||
+                                    ShmGBTData->evse[pDcChargingInfo->type_index].version[0] != '\0')
+                                    //&& (ShmGBTData->evse[pDcChargingInfo->type_index].SelfTest_Comp != YES)
+                               ) {
+                                log_info("GBT[%d] FW Rev = %s", pDcChargingInfo->type_index, ShmGBTData->evse[pDcChargingInfo->type_index].version);
+                                ShmGBTData->evse[pDcChargingInfo->type_index].SelfTest_Comp = YES;
+                            } else {
+                                //log_info("GBT fw lose...... %s \n", ShmCHAdeMOData->evse[pDcChargingInfo->type_index].version);
+                                evInitFlag = NO;
+                            }
+                        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                            if (ShmCcsData->CommProtocol == _CCS_COMM_V2GMessage_DIN70121) {
+                                if ((strlen((char *)ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].version) != 0 ||
+                                        ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].version[0] != '\0')
+                                        /*&&(ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].SelfTest_Comp != YES)*/
+                                   ) {
+                                    log_info("CCS[%d] FW Rev = %s",
+                                             pDcChargingInfo->type_index,
+                                             ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].version);
+                                    ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].SelfTest_Comp = YES;
+                                } else {
+                                    //log_info("CCS[%d] ccs fw lose...... %s \n",
+                                    //         chargingInfo[index]->type_index,
+                                    //         ShmCcsData->V2GMessage_DIN70121[chargingInfo[index]->type_index].version);
+                                    evInitFlag = NO;
+                                }
+                            }
+                        }
+                    }
+
+                    for (uint8_t index = 0; index < pSysConfig->AcConnectorCount; index++) {
+                        pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(index);
+
+                        if (pAcChargingInfo->Type == _Type_AC) {
+                            if ((strlen((char *)pAcChargingInfo->version) != 0 || pAcChargingInfo->version[0] != '\0')
+                                    && (pAcChargingInfo->SelfTest_Comp != YES)
+                               ) {
+                                log_info("AC connector[%d] FW Rev = %s", index, pAcChargingInfo->version);
+                                pAcChargingInfo->SelfTest_Comp = YES;
+                            } else {
+                                evInitFlag = NO;
+                            }
+                        }
+                    }
+                }
+
+                if ( ShmFanModuleData->SelfTest_Comp &&
+                        ShmRelayModuleData->SelfTest_Comp &&
+                        ShmPrimaryMcuData->SelfTest_Comp &&
+                        evInitFlag
+                   ) {
+                    pSysInfo->SelfTestSeq = _STEST_AC_CONTACTOR;
+                }
+            }
+            break;
+            case _STEST_AC_CONTACTOR: {
+                //ShmPsuData->Work_Step = _TEST_COMPLETE;
+                // 因為 30KW 以下沒有 Relay feedback 功能,所以暫時先直接跳過
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                if (pSysInfo->AcContactorStatus == YES) {
+                    pSysInfo->SelfTestSeq = _STEST_PSU_DETECT;
+                    log_info("AC contactor self test OK");
+                }
+#else
+                pSysInfo->SelfTestSeq = _STEST_PSU_DETECT;
+                log_info("Waiting for DO communication");
+#endif //!defined DD360 && !defined DD360Audi
+            }
+            break;
+            case _STEST_PSU_DETECT: {
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                if (ShmPsuData->Work_Step >= GET_SYS_CAP) {
+                    pSysInfo->SelfTestSeq = _STEST_PSU_CAP;
+                }
+#else
+                pSysInfo->SelfTestSeq = _STEST_PSU_CAP;
+#endif //defined DD360 && !defined DD360Audi
+            }
+            break;
+            case _STEST_PSU_CAP: {
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                // 此測試是要確認當前總輸出能力
+                // 如果沒有 PSU 模組請 bypass
+                if (ShmPsuData->Work_Step == BOOTING_COMPLETE) {
+                    sleep(1);
+                    pSysInfo->SelfTestSeq = _STEST_COMPLETE;
+                    pSysInfo->BootingStatus = BOOT_COMPLETE;
+                }
+#else
+                //check the power limit from DO
+                pSysInfo->SelfTestSeq = _STEST_COMPLETE;
+                pSysInfo->BootingStatus = BOOT_COMPLETE;
+                log_info("Successful Self Test");
+#endif //defined DD360 && !defined DD360Audi
+            }
+            break;
+            }
+        } else {
+            break;
+        }
+
+        usleep(100000);
+    }
+}

+ 0 - 303
EVSE/Projects/DD360/Apps/CSU/TimeTask.c

@@ -1,303 +0,0 @@
-
-void _CcsPrechargeTimeout(uint8_t gunIndex)
-{
-    log_info("*********** _CcsPrechargeTimeout ***********\n");
-    setChargerMode(gunIndex, MODE_IDLE);
-}
-
-void _DetectEvseChargingEnableTimeout(uint8_t gunIndex)
-{
-    log_info("*********** _DetectEvseChargingEnableTimeout (GFD timeout) ***********\n");
-    //if (chargingInfo[gunIndex]->GroundFaultStatus != GFD_PASS)
-    {
-        setChargerMode(gunIndex, MODE_IDLE);
-        _AutoReturnTimeout();
-    }
-}
-
-void _DetectEvChargingEnableTimeout(uint8_t gunIndex)
-{
-    if (chargingInfo[gunIndex]->Type == _Type_Chademo) {
-        if (!isEvGunLocked_chademo(gunIndex)) {
-            log_info("*********** _DetectEvChargingEnableTimeout (chademo) ***********\n");
-        }
-    } else if (chargingInfo[gunIndex]->Type == _Type_GB) {
-        if (!isEvGunLocked_ccs(gunIndex)) {
-            log_info("*********** _DetectEvChargingEnableTimeout (gb) ***********\n");
-        }
-    } else if (chargingInfo[gunIndex]->Type == _Type_CCS_2) {
-        if (!isEvGunLocked_ccs(gunIndex)) {
-            log_info("*********** _DetectEvChargingEnableTimeout (ccs) ***********\n");
-        }
-    }
-    ChargingTerminalProcess(gunIndex);
-    _AutoReturnTimeout();
-}
-
-void _PrepareTimeout(uint8_t gunIndex)
-{
-    log_info("*********** _PrepareTimeout ***********\n");
-    setChargerMode(gunIndex, MODE_IDLE);
-    ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuNoResource = YES;
-    _AutoReturnTimeout();
-}
-
-void ClearAuthorizedFlag()
-{
-    ShmOCPP16Data->SpMsg.bits.AuthorizeConf = NO;
-    ShmSysConfigAndInfo->SysInfo.AuthorizeFlag = NO;
-}
-
-void DisplayChargingInfo()
-{
-    log_info("*********** DisplayChargingInfo *********** \n");
-    for (uint8_t i = 0; i < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; i++) {
-        if (chargingInfo[i]->SystemStatus != S_IDLE &&
-                chargingInfo[i]->SystemStatus != S_RESERVATION) {
-            ChangeGunSelectByIndex(i);
-            return;
-        }
-    }
-
-    if (ShmSysConfigAndInfo->SysConfig.AcConnectorCount > 0 &&
-            ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc == NO_DEFINE &&
-            ac_chargingInfo[0]->SystemStatus >= S_PREPARNING && ac_chargingInfo[0]->SystemStatus <= S_COMPLETE) {
-        ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc = DEFAULT_AC_INDEX;
-    }
-
-    usleep(50000);
-#if defined DD360Audi
-    ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_SELECT_GUN;
-#else
-    ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_NONE;
-#endif //defined DD360Audi
-}
-
-void _DetectPlugInTimeout()
-{
-    log_info("*********** _DetectPlugInTimeout *********** \n");
-    strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
-    ClearDetectPluginFlag();
-    //usleep(50000);
-    sleep(1); //Jerry add
-#if defined DD360Audi
-    ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_SELECT_GUN;
-#else
-    ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_NONE;
-#endif //defined DD360Audi
-}
-
-void _AutoReturnTimeout()
-{
-    log_info("*********** _AutoReturnTimeout %d*********** \n", ShmSysConfigAndInfo->SysInfo.PageIndex);
-    if (ShmSysConfigAndInfo->SysInfo.PageIndex == _LCM_WAIT_FOR_PLUG) {
-        ClearDetectPluginFlag();
-    } else if (ShmSysConfigAndInfo->SysInfo.PageIndex == _LCM_AUTHORIZ_COMP) {
-        DetectPluginStart();
-    }
-    usleep(50000);
-#if defined DD360Audi
-    ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_SELECT_GUN;
-#else
-    ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_NONE;
-#endif //defined DD360Audi
-}
-
-void StopSystemTimeoutDet()
-{
-    gettimeofday(&ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer, NULL);
-    ShmSysConfigAndInfo->SysInfo.SystemTimeoutFlag = Timeout_None;
-}
-
-void _SelfTestTimeout()
-{
-    if (ShmSysConfigAndInfo->SysInfo.BootingStatus != BOOT_COMPLETE) {
-        for (uint8_t gun_index = 0; gun_index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; gun_index++) {
-            setChargerMode(gun_index, MODE_ALARM);
-        }
-    }
-    ShmPsuData->Work_Step = _NO_WORKING;
-    ShmSysConfigAndInfo->SysInfo.SelfTestSeq = _STEST_FAIL;
-    log_info("Self test timeout. \n");
-}
-
-void CheckConnectionTimeout(void)
-{
-#if defined DD360 || defined DD360Audi || defined DD360ComBox
-    if (gAudiCustInfo->RemoteSetup.ConnectionTimeout != 0) { //Jerry add
-        _connectionTimeout = gAudiCustInfo->RemoteSetup.ConnectionTimeout;
-    } else {
-        _connectionTimeout = CONN_PLUG_TIME_OUT;
-    }
-
-    return;
-#endif //defined DD360 || defined DD360Audi || defined DD360ComBox
-
-    if (system("pidof -s OcppBackend > /dev/null") != 0) {
-        _connectionTimeout = CONN_PLUG_TIME_OUT;
-    } else {
-        if (strcmp((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[ConnectionTimeOut].ItemData, "") != 0) {
-            _connectionTimeout = atoi((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[ConnectionTimeOut].ItemData);
-            if (_connectionTimeout <= 0) {
-                _connectionTimeout = CONN_PLUG_TIME_OUT;
-            }
-        } else {
-            _connectionTimeout = CONN_PLUG_TIME_OUT;
-        }
-    }
-}
-
-void CreateTimeoutFork(void)
-{
-    pid_t timeoutPid;
-
-    timeoutPid = fork();
-    log_info("CreateTimeoutFork = %d\r\n", timeoutPid);
-    if (timeoutPid == 0) {
-        gettimeofday(&_cmdSubPriority_time, NULL);
-        CheckConnectionTimeout();
-
-        while (1) {
-            if ((GetTimeoutValue(_cmdSubPriority_time) / 1000) > 5000) {
-                CheckConnectionTimeout();
-                gettimeofday(&_cmdSubPriority_time, NULL);
-            }
-
-            //printf("Timeout ***********SystemTimeoutFlag = %d, ********\n", ShmSysConfigAndInfo->SysInfo.SystemTimeoutFlag);
-            // 系統
-            switch (ShmSysConfigAndInfo->SysInfo.SystemTimeoutFlag) {
-            case Timeout_SelftestChk:
-                if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) / uSEC_VAL >= SELFTEST_TIMEOUT) {
-                    _SelfTestTimeout();
-                    StopSystemTimeoutDet();
-                    destroySelGun(DESTROY_ALL_SEL); //jerry add
-                }
-                break;
-
-            case Timeout_Authorizing:
-                if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) / uSEC_VAL >= AUTHORIZE_TIMEOUT) {
-                    _AuthorizedTimeout();
-                    StopSystemTimeoutDet();
-                    destroySelGun(ShmSysConfigAndInfo->SysInfo.CurGunSelected);
-                    if (gAudiCustInfo->AuthorStateFromCabinet[ShmSysConfigAndInfo->SysInfo.CurGunSelected] == YES) { //DoComm no ask cabinet balance
-                        gAudiCustInfo->AuthorStateFromCabinet[ShmSysConfigAndInfo->SysInfo.CurGunSelected] = NO;
-                        ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DisconnectedFromDo = ABNORMAL;
-                        log_error("Author timeout restart DoComm\r\n");
-                        system("killall Module_DoComm");
-                        sleep(1);
-                        system("/root/Module_DoComm &");
-                    }
-                }
-                break;
-
-            case Timeout_VerifyFail:
-                if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) / uSEC_VAL >= AUTHORIZE_FAIL_TIMEOUT) {
-                    _AutoReturnTimeout();
-                    StopSystemTimeoutDet();
-                    destroySelGun(ShmSysConfigAndInfo->SysInfo.CurGunSelected);
-                    if (gAudiCustInfo->AuthorStateFromCabinet[ShmSysConfigAndInfo->SysInfo.CurGunSelected] == YES) { //DoComm no ask cabinet balance
-                        gAudiCustInfo->AuthorStateFromCabinet[ShmSysConfigAndInfo->SysInfo.CurGunSelected] = NO;
-                        ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DisconnectedFromDo = ABNORMAL;
-                        log_error("Author timeout restart DoComm\r\n");
-                        system("killall Module_DoComm");
-                        sleep(1);
-                        system("/root/Module_DoComm &");
-                    }
-                }
-                break;
-
-            case Timeout_VerifyComp:
-                if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) / uSEC_VAL >= AUTHORIZE_COMP_TIMEOUT) {
-                    _AutoReturnTimeout();
-                    StopSystemTimeoutDet();
-                }
-                break;
-
-            case Timeout_WaitPlug:
-                if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) / uSEC_VAL >= _connectionTimeout) {
-                    _DetectPlugInTimeout();
-                    StopSystemTimeoutDet();
-                    destroySelGun(ShmSysConfigAndInfo->SysInfo.CurGunSelected);
-                }
-                break;
-
-            case Timeout_ReturnToChargingGunDet:
-                if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) / uSEC_VAL >= RETURN_TO_CHARGING_PAGE) {
-#if defined DD360Audi
-                    if (getCurLcmPage() != _LCM_PRE_CHARGE &&
-                            getCurLcmPage() != _LCM_CHARGING &&
-                            getCurLcmPage() != _LCM_COMPLETE) {
-                        destroySelGun(ShmSysConfigAndInfo->SysInfo.CurGunSelected); //jerry add
-
-                    }
-#endif //defined DD360Audi
-                    DisplayChargingInfo();
-                    StopSystemTimeoutDet();
-                }
-                break;
-
-            case Timeout_AuthorizingForStop:
-                if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) / uSEC_VAL >= AUTHORIZE_STOP_TIMEOUT) {
-                    strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
-                    ClearAuthorizedFlag();
-                    StopSystemTimeoutDet();
-                }
-                break;
-
-            } //switch
-
-            // 各槍
-            for (uint8_t gun_index = 0; gun_index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; gun_index++) {
-                //printf("Timeout ***********TimeoutFlag = %d, ********\n", chargingInfo[gun_index]->TimeoutFlag);
-                switch (chargingInfo[gun_index]->TimeoutFlag) {
-                case Timeout_Preparing:
-                    if (GetTimeoutValue(chargingInfo[gun_index]->TimeoutTimer) / uSEC_VAL >= GUN_PREPARE_TIMEOUT) {
-                        _PrepareTimeout(gun_index);
-                        StopGunInfoTimeoutDet(gun_index);
-                        destroySelGun(gun_index); //jerry add
-                    }
-                    break;
-
-                case Timeout_EvChargingDet:
-                    if (GetTimeoutValue(chargingInfo[gun_index]->TimeoutTimer) / uSEC_VAL >= GUN_EV_WAIT_TIMEOUT) {
-                        _DetectEvChargingEnableTimeout(gun_index);
-                        StopGunInfoTimeoutDet(gun_index);
-                        destroySelGun(gun_index); //jerry add
-                    }
-                    break;
-
-                case Timeout_EvseChargingDet:
-                    if (GetTimeoutValue(chargingInfo[gun_index]->TimeoutTimer) / uSEC_VAL >= GUN_EVSE_WAIT_TIMEOUT) {
-                        _DetectEvseChargingEnableTimeout(gun_index);
-                        StopGunInfoTimeoutDet(gun_index);
-                        destroySelGun(gun_index); //jerry add
-                    }
-                    break;
-
-                case Timeout_EvseCompleteDet:
-                    if (GetTimeoutValue(chargingInfo[gun_index]->TimeoutTimer) / uSEC_VAL >= GUN_COMP_WAIT_TIMEOUT) {
-                        StopGunInfoTimeoutDet(gun_index);
-                        destroySelGun(gun_index); //jerry add
-                    }
-                    break;
-
-                case Timeout_ForCcsPrechargeDet:
-                    if (GetTimeoutValue(chargingInfo[gun_index]->TimeoutTimer) / uSEC_VAL >= GUN_PRECHARGING_TIMEOUT) {
-                        _CcsPrechargeTimeout(gun_index);
-                        StopGunInfoTimeoutDet(gun_index);
-                        destroySelGun(gun_index); //jerry add
-                    }
-                    break;
-
-                case Timeout_SelectGun: //Jerry add
-                    if (GetTimeoutValue(chargingInfo[gun_index]->TimeoutTimer) / uSEC_VAL >= SEL_GUN_TIMEOUT) {
-                        StopGunInfoTimeoutDet(gun_index);
-                        destroySelGun(gun_index); //jerry add
-                    }
-                    break;
-                } //switch
-            } //for
-            sleep(1);
-        }//while
-    }
-}

+ 134 - 8
EVSE/Projects/DD360ComBox/Apps/CSU/Update.c → EVSE/Projects/DD360/Apps/CSU/UpgradeFW.c

@@ -3,30 +3,115 @@
 #include <string.h>
 #include <stdint.h>
 
+#include <sys/types.h>
+#include <dirent.h>
+
 #include "../Config.h"
 #include "../Log/log.h"
 #include "../Define/define.h"
 #include "../ShareMemory/shmMem.h"
 
+#include "../main.h"
+
+//------------------------------------------------------------------------------
+static char *_priPortName = "/dev/ttyS1";
+static char *_485PortName = "/dev/ttyS5";
+
 //------------------------------------------------------------------------------
-int CheckUpdateProcess(void)
+static int InitComPort(uint8_t target)
+{
+    int fd;
+    struct termios tios;
+
+    if (target == UPGRADE_PRI) {
+        fd = open(_priPortName, O_RDWR);
+    } else if (target == UPGRADE_FAN ||  target == UPGRADE_RB || target == UPGRADE_AC || target == UPGRADE_LED) {
+        fd = open(_485PortName, O_RDWR);
+    }
+
+    if (fd <= 0) {
+#ifdef SystemLogMessage
+        log_error("open 407 Communication port NG \n");
+#endif
+        return -1;
+    }
+    ioctl (fd, TCGETS, &tios);
+    tios.c_cflag = B115200 | CS8 | CLOCAL | CREAD;
+    tios.c_lflag = 0;
+    tios.c_iflag = 0;
+    tios.c_oflag = 0;
+    tios.c_cc[VMIN] = 0;
+    tios.c_cc[VTIME] = (uint8_t)1;
+    tios.c_lflag = 0;
+    tcflush(fd, TCIFLUSH);
+    ioctl (fd, TCSETS, &tios);
+
+    return fd;
+}
+
+static int InitCanBus(void)
+{
+    int fd = -1;
+    int nbytes;
+    struct timeval tv;
+    struct ifreq ifr0;
+    struct sockaddr_can addr0;
+
+    system("/sbin/ip link set can0 down");
+    system("/sbin/ip link set can0 type can bitrate 500000 restart-ms 100");
+    system("/sbin/ip link set can0 up");
+
+    fd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
+
+    tv.tv_sec = 0;
+    tv.tv_usec = 10000;
+    if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct  timeval)) < 0) {
+#ifdef SystemLogMessage
+        log_error("Set SO_RCVTIMEO NG");
+#endif
+    }
+    nbytes = 40960;
+    if (setsockopt(fd, SOL_SOCKET,  SO_RCVBUF, &nbytes, sizeof(int)) < 0) {
+#ifdef SystemLogMessage
+        log_error("Set SO_RCVBUF NG");
+#endif
+    }
+    nbytes = 40960;
+    if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &nbytes, sizeof(int)) < 0) {
+#ifdef SystemLogMessage
+        log_error("Set SO_SNDBUF NG");
+#endif
+    }
+
+    strcpy(ifr0.ifr_name, "can0");
+    ioctl(fd, SIOCGIFINDEX, &ifr0); /* ifr.ifr_ifindex gets filled with that device's index */
+    addr0.can_family = AF_CAN;
+    addr0.can_ifindex = ifr0.ifr_ifindex;
+    bind(fd, (struct sockaddr *)&addr0, sizeof(addr0));
+
+    return fd;
+}
+
+static int CheckUpdateProcess(void)
 {
     //bool isPass = true;
     uint8_t retSucc = 0;
     uint8_t retFail = 0;
     uint8_t index = 0;
     uint8_t target = 0;
+    char Buf[256];
     char *new_str = NULL;
     uint8_t *ptr = NULL;
     int fd = 0;
     int CanFd = 0;
     int uartFd = 0;
     unsigned int Type = 0;
-    long int MaxLen = (48 * 1024 * 1024, ImageLen = 0);
+    long int MaxLen = 48 * 1024 * 1024, ImageLen = 0;
     DIR *d;
     struct dirent *dir;
     struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
-    struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
+    DcCommonInfo *ShmDcCommonData = (DcCommonInfo *)GetShmDcCommonData();
+    struct ChargingInfoData *pDcChargingInfo = NULL;
 
     d = opendir("/mnt/");
     if (d) {
@@ -84,14 +169,47 @@ int CheckUpdateProcess(void)
                 case 0x10000008:
                 case 0x10000009:
                 case 0x1000000A:
+                    CanFd = InitCanBus();
+                    if (CanFd > 0) {
+                        for (index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+                            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+                            if (pDcChargingInfo->Type == _Type_CCS_2) {
+                                uint8_t targetID = pDcChargingInfo->Evboard_id;
+
+                                if (pSysConfig->TotalConnectorCount == 1 &&
+                                        ShmDcCommonData->CcsVersion == _CCS_VERSION_CHECK_TAG_V015S0) {
+                                    targetID += 1;
+                                }
+
+                                system("echo 3 > /proc/sys/vm/drop_caches");
+                                sleep(2);
+                                log_info("Upgrade CCS Processing..target id = %d \n", targetID);
+                                if (Upgrade_CCS(CanFd,
+                                                Type,
+                                                targetID,
+                                                new_str,
+                                                (char *)pSysConfig->ModelName) == FAIL) {
+                                    log_info("Upgrade CCS Failed \n");
+                                    retFail++;
+                                } else {
+                                    retSucc++;
+                                }
+                            }
+                        }
+                        close(CanFd);
+                    }
+                    memset(Buf, 0, sizeof(Buf));
+                    sprintf(Buf, "rm -rvf /mnt/%s", new_str);
+                    system(Buf);
                     //isPass = true;
+#if 0
                     CanFd = InitCanBus();
                     if (CanFd > 0) {
                         for (index = 0; index < pSysConfig->TotalConnectorCount; index++) {
                             //if (!isPass) {
                             //    break;
                             //}
-
                             if (chargingInfo[index]->Type == _Type_CCS_2) {
                                 if (Upgrade_CCS(CanFd, Type, chargingInfo[index]->Evboard_id, new_str, (char *)pSysConfig->ModelName) == FAIL) {
                                     //isPass = false;
@@ -112,6 +230,7 @@ int CheckUpdateProcess(void)
                         retSucc++;
                     }
                     //return isPass;
+#endif //0
                     break;
 
                 case 0x10000006:
@@ -157,13 +276,15 @@ int CheckUpdateProcess(void)
                     CanFd = InitCanBus();
                     if (CanFd > 0) {
                         for (index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+                            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
                             //if (!isPass) {
                             //    break;
                             //}
 
-                            if ((Type == 0x1000000B && chargingInfo[index]->Type == _Type_Chademo) ||
-                                    (Type == 0x1000000C && chargingInfo[index]->Type == _Type_GB)) {
-                                if (Upgrade_CAN(CanFd, Type, chargingInfo[index]->Evboard_id, new_str, (char *)pSysConfig->ModelName) == PASS) {
+                            if ((Type == 0x1000000B && pDcChargingInfo->Type == _Type_Chademo) ||
+                                    (Type == 0x1000000C && pDcChargingInfo->Type == _Type_GB)) {
+                                if (Upgrade_CAN(CanFd, Type, pDcChargingInfo->Evboard_id, new_str, (char *)pSysConfig->ModelName) == PASS) {
                                     //isPass = PASS;
                                     retSucc++;
                                 } else {
@@ -201,6 +322,8 @@ void CheckFwUpdateFunction(void)
 {
     struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
     struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
+    struct OCPP16Data *ShmOCPP16Data = (struct OCPP16Data *)GetShmOCPP16Data();
+    struct ChargingInfoData *pAcChargingInfo = NULL;
 
     //log_info("pSysInfo->FirmwareUpdate = %d \n", pSysInfo->FirmwareUpdate);
     if (pSysInfo->FirmwareUpdate == YES) {
@@ -240,8 +363,11 @@ void CheckFwUpdateFunction(void)
             for (uint8_t _index = 0; _index < pSysConfig->TotalConnectorCount; _index++) {
                 setChargerMode(_index, MODE_UPDATE);
             }
+
             for (uint8_t _index = 0; _index < pSysConfig->AcConnectorCount; _index++) {
-                ac_chargingInfo[_index]->SystemStatus = MODE_UPDATE;
+                pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(_index);
+
+                pAcChargingInfo->SystemStatus = MODE_UPDATE;
             }
 
             uint8_t updateResult = CheckUpdateProcess();

+ 48 - 0
EVSE/Projects/DD360/Apps/CSU/WatchDog.c

@@ -0,0 +1,48 @@
+#include <stdio.h>      /*標準輸入輸出定義*/
+#include <stdlib.h>     /*標準函數庫定義*/
+#include <string.h>
+#include <stdint.h>
+
+#include "../Config.h"
+#include "../Log/log.h"
+#include "../Define/define.h"
+#include "../ShareMemory/shmMem.h"
+
+//------------------------------------------------------------------------------
+static int gWatchDogfd = -1;
+
+//------------------------------------------------------------------------------
+void WriteWatchDogState(char *value)
+{
+    write(gWatchDogfd, value, 1);
+}
+
+static int initWatchDog(void)
+{
+    int fd;
+    system("/usr/bin/fuser -k /dev/watchdog");
+    sleep(1);
+    system("echo V > /dev/watchdog");
+    sleep(1);
+    fd = open("/dev/watchdog", O_RDWR);
+
+    if (fd <= 0) {
+        log_error("System watch dog initial fail.\r\n");
+    }
+
+    return fd;
+}
+
+void CreateWatchdog(void)
+{
+    struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
+    struct AlarmCodeData *pAlarmCode = (struct AlarmCodeData *)GetShmAlarmCodeData();
+
+    if (pSysConfig->SwitchDebugFlag == NO) {
+        gWatchDogfd = initWatchDog();
+
+        if (gWatchDogfd < 0) {
+            pAlarmCode->AlarmEvents.bits.CsuInitFailed = 1;
+        }
+    }
+}

+ 15 - 0
EVSE/Projects/DD360/Apps/CSU/ZipFile.c

@@ -1,7 +1,21 @@
+#include <stdio.h>      /*標準輸入輸出定義*/
+#include <stdlib.h>     /*標準函數庫定義*/
+#include <string.h>
+#include <stdint.h>
 
+#include <sys/types.h>
+#include <dirent.h>
+
+#include "../Config.h"
+#include "../Log/log.h"
+#include "../Define/define.h"
+#include "../ShareMemory/shmMem.h"
+
+//------------------------------------------------------------------------------
 void zipLogFiles(void)
 {
     const char *logPath = "/Storage/SystemLog";
+
     // 獲取目錄
     DIR *pDir = opendir(logPath);
     if (pDir != NULL) {
@@ -57,6 +71,7 @@ void zipLogFiles(void)
             }
         }
     }
+
     // Close folder
     closedir(pDir);
 }

+ 7407 - 0
EVSE/Projects/DD360/Apps/CSU/main.c

@@ -0,0 +1,7407 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/mman.h>
+#include <linux/wireless.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include <unistd.h>
+#include <stdarg.h>
+#include <stdio.h>      /*標準輸入輸出定義*/
+#include <stdlib.h>     /*標準函數庫定義*/
+#include <unistd.h>     /*Unix 標準函數定義*/
+#include <fcntl.h>      /*檔控制定義*/
+#include <termios.h>    /*PPSIX 終端控制定義*/
+#include <errno.h>      /*錯誤號定義*/
+#include <errno.h>
+#include <string.h>
+#include <stdint.h>
+#include <time.h>
+#include <ctype.h>
+#include <ifaddrs.h>
+#include <math.h>
+#include "./Define/define.h"
+#include <stdbool.h>
+#include <dirent.h>
+
+#include "Config.h"
+#include "main.h"
+#include "common.h"
+#include "timeout.h"
+
+#include "./Log/log.h"
+#include "./Define/define.h"
+#include "./ShareMemory/shmMem.h"
+
+#if defined DD360 ||defined DD360Audi || defined DD360ComBox
+#include "./SelectGun/SelectGun.h"
+#endif //defined DD360Audi
+
+//------------------------------------------------------------------------------
+char *valid_Internet[2] = {"8.8.8.8", "180.76.76.76"};
+uint8_t mask_table[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
+int whileLoopTime = 10000; // 10 ms
+//int wtdFd = -1;
+//uint8_t _authorizeIndex = NO_DEFINE;
+
+//struct SysConfigAndInfo         *ShmSysConfigAndInfo;
+//struct StatusCodeData           *ShmStatusCodeData;
+static struct SysInfoData *pSysInfo = NULL;
+static struct SysConfigData *pSysConfig = NULL;
+static struct WARNING_CODE_INFO *pSysWarning = NULL;
+
+static struct AlarmCodeData *pAlarmCode = NULL;
+static struct FaultCodeData *pFaultCode = NULL;
+static struct InfoCodeData  *pInfoCode = NULL;
+
+static struct PsuData *ShmPsuData = NULL;
+static struct CHAdeMOData *ShmCHAdeMOData = NULL;
+static struct GBTData *ShmGBTData = NULL;
+static struct CcsData *ShmCcsData = NULL;
+static struct PrimaryMcuData *ShmPrimaryMcuData = NULL;
+static struct FanModuleData *ShmFanModuleData = NULL;
+static struct RelayModuleData *ShmRelayModuleData = NULL;
+static struct LedModuleData *ShmLedModuleData = NULL;
+static struct OCPP16Data *ShmOCPP16Data = NULL;
+static DcCommonInfo *ShmDcCommonData = NULL;
+
+static struct ChargingInfoData *pDcChargingInfo = NULL;
+static struct ChargingInfoData *pAcChargingInfo = NULL;
+
+//struct ChargingInfoData *chargingInfo[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
+//struct ChargingInfoData *ac_chargingInfo[AC_QUANTITY];
+struct timeb startChargingTime[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
+struct timeb endChargingTime[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
+
+#if defined DD360 ||defined DD360Audi || defined DD360ComBox
+static SelectGunInfo             *gAudiCustInfo = NULL; //Jerry add
+#endif //defined DD360Audi
+static EvBoardErrMsg gEvBoardErr = {0};
+
+// for initial index to check EV board type is correct
+//uint8_t _gunIndex = 0;
+//uint8_t _acgunIndex = 0;
+//uint8_t _chademoIndex = 0;
+//uint8_t _ccsIndex = 0;
+//uint8_t _gb_Index = 0;
+//uint8_t _ac_Index = 0;
+uint8_t bd0_1_status = 0;
+uint8_t bd0_2_status = 0;
+uint8_t bd1_1_status = 0;
+uint8_t bd1_2_status = 0;
+
+//static uint8_t restartFlag = 0;
+
+//bool isCardScan = false;
+//bool isModelNameMatch = true;
+
+//int rfidFd = -1;
+//char *rfidPortName = "/dev/ttyS2";
+char *fwVersion = "V1.08.00.0000.00"; // "V0.16.00.0000.00";
+
+//sqlite3 *localDb;
+bool isDb_ready;
+
+//------------------------------------------------------------------------------
+//bool IsAuthorizingMode();
+//void ClearAuthorizedFlag();
+//bool isDetectPlugin();
+void ClearDetectPluginFlag();
+
+long long DiffTimebWithNow(struct timeb ST);
+uint8_t DetectBitValue(uint8_t _byte, uint8_t _bit);
+void SetBitValue(uint8_t *_byte, uint8_t _bit, uint8_t value);
+//void ChargingTerminalProcess(uint8_t gunIndex);
+//void ChkPrimaryStatus();
+//void StartSystemTimeoutDet(uint8_t flag);
+//void StopSystemTimeoutDet();
+//void StartGunInfoTimeoutDet(uint8_t gunIndex, uint8_t flag);
+//void StopGunInfoTimeoutDet(uint8_t gunIndex);
+//int StoreLogMsg_1(const char *fmt, ...);
+unsigned long GetTimeoutValue(struct timeval _sour_time);
+void gpio_set_value(unsigned int gpio, unsigned int value);
+//void ChangeGunSelectByIndex(uint8_t sel);
+void InformOcppErrOccur(uint8_t codeType);
+
+void RecordAlarmCode(uint8_t gunIndex, char *code);
+void RecordWarningCode(uint8_t gunIndex, char *code);
+void ReleaseWarningCodeByString(uint8_t gunIndex, char *code);
+void ReleaseAlarmCode(uint8_t gunIndex);
+void ResetChargerAlarmCode(uint8_t gunIndex, char *code);
+
+void AdjustChargerCurrent();
+
+//------------------------------------------------------------------------------
+//Primary.c
+extern void PrimaryLedIndicatorCtrlFork(void);
+extern void ChkPrimaryStatus(void);
+
+//RFID.c
+extern void CreateRfidFork(void);
+extern void ScannerCardProcess(void);
+extern bool GetIsCardScan(void);
+extern void SetIsCardScan(bool value);
+
+//SelfTest.c
+extern void SelfTestRun(void);
+
+//UpgradeFW.c
+extern void CheckFwUpdateFunction(void);
+
+//Ethernet.c
+extern void InitEthernet(void);
+extern void GetMacAddress(void);
+
+//WatchDog.c
+extern void CreateWatchdog(void);
+extern void WriteWatchDogState(char *value);
+
+//ZipFile.c
+extern void zipLogFiles(void);
+
+///DataBase/DataBase.c
+extern int DB_Open(void);
+extern int DB_Insert_Record(int gun_index);
+extern int DB_Update_Operactive(uint8_t gun_index, uint8_t IsAvailable);
+extern int DB_Get_Operactive(uint8_t gun_index);
+extern int DB_Reboot_Record(void);
+
+//------------------------------------------------------------------------------
+//--- share memory value ---
+//------------------------------------------------------------------------------
+static void changeLcmPage(uint8_t index)
+{
+    pSysInfo->SystemPage = index;
+}
+
+static uint8_t getCurLcmPage(void)
+{
+    return pSysInfo->SystemPage;
+}
+
+//------------------------------------------------------------------------------
+void destroySelGun(uint8_t curGun)
+{
+    uint8_t i = 0;
+    uint8_t totalGun = pSysConfig->TotalConnectorCount;
+
+#if !defined DD360Audi
+    return;
+#endif //!defined DD360Audi
+
+    //for status timeout
+    if (curGun == DESTROY_ALL_SEL) {
+        gAudiCustInfo->SelGunInfo.RightGun = SEL_GUN_RELEASE;
+        gAudiCustInfo->SelGunInfo.LeftGun = SEL_GUN_RELEASE;
+        log_info("destroy all gun = %d, %d\r\n",
+                 gAudiCustInfo->SelGunInfo.LeftGun,
+                 gAudiCustInfo->SelGunInfo.RightGun);
+        for (i = 0; i < totalGun; i++) {
+            StopGunInfoTimeoutDet(i);
+            memset(&gAudiCustInfo->PricesInfo[i], 0, sizeof(PricesInfo));
+        }
+        pSysInfo->CurGunSelected = 0;
+        strcpy((char *)pSysConfig->UserId, "");
+        //changeLcmPage(_LCM_SELECT_GUN);
+        return;
+    }
+
+    //for charging timeout or complete
+    if ((curGun == LEFT_GUN_NUM) && (gAudiCustInfo->SelGunInfo.LeftGun != SEL_GUN_RELEASE)) {
+        if (gAudiCustInfo->SelGunInfo.LeftGun == SEL_GUN_CONFIRM ||
+                gAudiCustInfo->SelGunInfo.LeftGun == SEL_GUN_ATHOR) {
+            changeLcmPage(_LCM_SELECT_GUN);
+        }
+        gAudiCustInfo->SelGunInfo.LeftGun = SEL_GUN_RELEASE;
+        StopGunInfoTimeoutDet(LEFT_GUN_NUM);
+        if (ShmOCPP16Data->SpMsg.bits.AuthorizeConf != NO) {
+            ClearAuthorizedFlag();
+        }
+
+        log_info("destroy left gun, cur page = %d\r\n", getCurLcmPage());
+        if (getCurLcmPage() == pSysInfo->SystemPage) {
+            log_info("clear left balance\r\n");
+            memset(&gAudiCustInfo->PricesInfo[curGun], 0, sizeof(PricesInfo));
+            gAudiCustInfo->PricesInfo[curGun].Balance = FAIL_BALANCE_PRICES;
+        }
+    }
+
+    if ((curGun == RIGHT_GUN_NUM) && (gAudiCustInfo->SelGunInfo.RightGun != SEL_GUN_RELEASE)) {
+        if (gAudiCustInfo->SelGunInfo.RightGun == SEL_GUN_CONFIRM ||
+                gAudiCustInfo->SelGunInfo.RightGun == SEL_GUN_ATHOR) {
+            changeLcmPage(_LCM_SELECT_GUN);
+        }
+        gAudiCustInfo->SelGunInfo.RightGun = SEL_GUN_RELEASE;
+        StopGunInfoTimeoutDet(RIGHT_GUN_NUM);
+        if (ShmOCPP16Data->SpMsg.bits.AuthorizeConf != NO) {
+            ClearAuthorizedFlag();
+        }
+
+        log_info("destroy right gun, cur page = %d\r\n", getCurLcmPage());
+        if (getCurLcmPage() == pSysInfo->SystemPage) {
+            log_info("clear right balance\r\n");
+            memset(&gAudiCustInfo->PricesInfo[curGun], 0, sizeof(PricesInfo));
+            gAudiCustInfo->PricesInfo[curGun].Balance = FAIL_BALANCE_PRICES;
+        }
+    }
+}
+
+static int waitRightGunPlugIt(uint8_t curGun)
+{
+#if !defined DD360Audi
+    return;
+#endif //!defined DD360Audi
+
+    if ((curGun == RIGHT_GUN_NUM) && (gAudiCustInfo->SelGunInfo.RightGun == SEL_GUN_ATHOR)) {
+        return PASS;
+    }
+
+    return FAIL;
+}
+
+static int waitLeftGunPlugIt(uint8_t curGun)
+{
+#if !defined DD360Audi
+    return;
+#endif //!defined DD360Audi
+
+    if ((curGun == LEFT_GUN_NUM) && (gAudiCustInfo->SelGunInfo.LeftGun == SEL_GUN_ATHOR)) {
+        return PASS;
+    }
+
+    return FAIL;
+}
+
+void setSelGunWaitToAuthor(uint8_t curSel)
+{
+#if !defined DD360Audi
+    return;
+#endif //!defined DD360Audi
+
+    if (curSel == LEFT_GUN_NUM && gAudiCustInfo->SelGunInfo.LeftGun == SEL_GUN_CONFIRM) {
+        gAudiCustInfo->SelGunInfo.LeftGun = SEL_GUN_ATHOR;
+        //printf("setSelGunWaitToAuthor left\r\n");
+        StopGunInfoTimeoutDet(curSel);
+    } else if (curSel == RIGHT_GUN_NUM && gAudiCustInfo->SelGunInfo.RightGun == SEL_GUN_CONFIRM) {
+        gAudiCustInfo->SelGunInfo.RightGun = SEL_GUN_ATHOR;
+        //printf("setSelGunWaitToAuthor right\r\n");
+        StopGunInfoTimeoutDet(curSel);
+    }
+}
+
+int getConfirmSelectedGun(uint8_t curSel)
+{
+#if !defined DD360Audi
+    return;
+#endif //!defined DD360Audi
+
+    if (((curSel == LEFT_GUN_NUM) && (gAudiCustInfo->SelGunInfo.LeftGun >= SEL_GUN_CONFIRM)) ||
+            ((curSel == RIGHT_GUN_NUM) && (gAudiCustInfo->SelGunInfo.RightGun >= SEL_GUN_CONFIRM))) {
+        return PASS;
+    }
+
+    return FAIL;
+}
+
+void confirmSelGun(uint8_t selGun)
+{
+#if !defined DD360Audi
+    return;
+#endif //!defined DD360Audi
+
+    if (selGun == LEFT_GUN_NUM) {
+        gAudiCustInfo->SelGunInfo.LeftGun = SEL_GUN_CONFIRM;
+        StopGunInfoTimeoutDet(selGun);
+        //printf("confirmSelGun left\r\n");
+    } else if (selGun == RIGHT_GUN_NUM) {
+        gAudiCustInfo->SelGunInfo.RightGun = SEL_GUN_CONFIRM;
+        StopGunInfoTimeoutDet(selGun);
+        //printf("confirmSelGun right\r\n");
+    }
+
+    changeLcmPage(_LCM_IDLE);
+
+    StartGunInfoTimeoutDet(selGun, Timeout_SelectGun);
+}
+
+static void checkGunOTPState(uint8_t _index)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_index);
+
+    switch (pDcChargingInfo->Type) {
+    case _Type_Chademo:
+        if (pDcChargingInfo->ConnectorTemp != UNDEFINED_TEMP) {
+            if (pDcChargingInfo->ConnectorTemp >= GUN_OTP_VALUE) {
+                RecordAlarmCode(_index, "012229");
+            } else if (pDcChargingInfo->ConnectorTemp != 0 &&
+                       pDcChargingInfo->ConnectorTemp < GUN_OTP_RECOVERY) {
+                ResetChargerAlarmCode(_index, "012229");
+            }
+        } else {
+            // 沒接上 Sensor or 異常
+            //RecordAlarmCode(_index, "011018");
+            ResetChargerAlarmCode(_index, "012229");
+        }
+        break;
+
+    case _Type_CCS_2:
+        // CCS 不管甚麼輸出都會有槍溫偵測!!~
+        if (pDcChargingInfo->ConnectorTemp != UNDEFINED_TEMP) {
+            ResetChargerAlarmCode(_index, "011019");
+
+            if (pDcChargingInfo->ConnectorTemp >= GUN_OTP_VALUE) {
+                RecordAlarmCode(_index, "012230");
+            } else if (pDcChargingInfo->ConnectorTemp != 0 &&
+                       pDcChargingInfo->ConnectorTemp < GUN_OTP_RECOVERY) {
+                ResetChargerAlarmCode(_index, "012230");
+            }
+
+            //ResetChargerAlarmCode(_index, "011019");
+        } else {
+            // 沒接上 Sensor or 異常
+            RecordAlarmCode(_index, "011019");
+            ResetChargerAlarmCode(_index, "012230");
+        }
+        break;
+
+    case _Type_GB:
+        if (pDcChargingInfo->ConnectorTemp != UNDEFINED_TEMP) {
+            if (pDcChargingInfo->ConnectorTemp >= GUN_OTP_VALUE) {
+                RecordAlarmCode(_index, "012231");
+            } else if (pDcChargingInfo->ConnectorTemp != 0 &&
+                       pDcChargingInfo->ConnectorTemp < GUN_OTP_RECOVERY) {
+                ResetChargerAlarmCode(_index, "012231");
+            }
+        } else {
+            // 沒接上 Sensor or 異常
+            RecordAlarmCode(_index, "011020");
+            ResetChargerAlarmCode(_index, "012231");
+        }
+        break;
+    }
+}
+
+static void collectError(uint8_t gunIndex)
+{
+    gEvBoardErr.GunErrMessage |= ShmDcCommonData->ConnectErrList[gunIndex].GunErrMessage;
+}
+
+static void checkGBTAlarmState(uint8_t gunType)
+{
+    // GFD Trip
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 0)) {
+        pAlarmCode->AlarmEvents.bits.GbGfdTrip = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.GbGfdTrip = NO;
+    }
+
+    // UVP
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 1)) {
+        pAlarmCode->AlarmEvents.bits.GbtOutputUVPFail = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.GbtOutputUVPFail = NO;
+    }
+
+    // OTP
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 2)) {
+        pAlarmCode->AlarmEvents.bits.GbConnectorOTP = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.GbConnectorOTP = NO;
+    }
+
+    // OVP
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 3)) {
+        pAlarmCode->AlarmEvents.bits.SystemGbOutputOVP = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.SystemGbOutputOVP = NO;
+    }
+
+    // GFD Warning
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 4)) {
+        pAlarmCode->AlarmEvents.bits.GbGroundfaultWarning = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.GbGroundfaultWarning = NO;
+    }
+
+    // Relay Welding
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 5)) {
+        pFaultCode->FaultEvents.bits.GbOutputRelayWelding = YES;
+    } else {
+        pFaultCode->FaultEvents.bits.GbOutputRelayWelding = NO;
+    }
+
+    // Relay Driving
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 6)) {
+        pFaultCode->FaultEvents.bits.GbOutputRelayDrivingFault = YES;
+    } else {
+        pFaultCode->FaultEvents.bits.GbOutputRelayDrivingFault = NO;
+    }
+
+    // Connect temp Sensor broken
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 7)) {
+        pFaultCode->FaultEvents.bits.GbConnectorTempSensorBroken = YES;
+    } else {
+        pFaultCode->FaultEvents.bits.GbConnectorTempSensorBroken = NO;
+    }
+}
+
+static void checkCCSAlarmState(uint8_t gunType)
+{
+    // GFD Trip
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 0)) {
+        pAlarmCode->AlarmEvents.bits.CcsGfdTrip = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.CcsGfdTrip = NO;
+    }
+
+    // UVP
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 1)) {
+        pAlarmCode->AlarmEvents.bits.CcsOutputUVPFail = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.CcsOutputUVPFail = NO;
+    }
+
+    // OTP
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 2)) {
+        pAlarmCode->AlarmEvents.bits.CcsConnectorOTP = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.CcsConnectorOTP = NO;
+    }
+
+    // OVP
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 3)) {
+        pAlarmCode->AlarmEvents.bits.SystemCcsOutputOVP = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.SystemCcsOutputOVP = NO;
+    }
+
+    // GFD Warning
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 4)) {
+        pAlarmCode->AlarmEvents.bits.CcsGroundfaultWarning = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.CcsGroundfaultWarning = NO;
+    }
+
+    // Relay Welding
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 5)) {
+        pFaultCode->FaultEvents.bits.CcsOutputRelayWelding = YES;
+    } else {
+        pFaultCode->FaultEvents.bits.CcsOutputRelayWelding = NO;
+    }
+
+    // Relay Driving
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 6)) {
+        pFaultCode->FaultEvents.bits.CcsOutputRelayDrivingFault = YES;
+    } else {
+        pFaultCode->FaultEvents.bits.CcsOutputRelayDrivingFault = NO;
+    }
+
+    // Connect temp Sensor broken
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 7)) {
+        pFaultCode->FaultEvents.bits.CcsConnectorTempSensorBroken = YES;
+    } else {
+        pFaultCode->FaultEvents.bits.CcsConnectorTempSensorBroken = NO;
+    }
+}
+
+static void checkChaDeMoAlarmState(uint8_t gunType)
+{
+    // GFD Trip
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 0)) {
+        pAlarmCode->AlarmEvents.bits.ChademoGfdTrip = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.ChademoGfdTrip = NO;
+    }
+
+    // UVP
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 1)) {
+        pAlarmCode->AlarmEvents.bits.ChademoOutputUVPFail = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.ChademoOutputUVPFail = NO;
+    }
+
+    // OTP
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 2)) {
+        pAlarmCode->AlarmEvents.bits.ChademoConnectorOTP = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.ChademoConnectorOTP = NO;
+    }
+
+    // OVP
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 3)) {
+        pAlarmCode->AlarmEvents.bits.SystemChademoOutputOVP = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.SystemChademoOutputOVP = NO;
+    }
+
+    // GFD Warning
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 4)) {
+        pAlarmCode->AlarmEvents.bits.ChademoGroundWarning = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.ChademoGroundWarning = NO;
+    }
+
+    // Relay Welding
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 5)) {
+        pFaultCode->FaultEvents.bits.ChademoOutputRelayWelding = YES;
+    } else {
+        pFaultCode->FaultEvents.bits.ChademoOutputRelayWelding = NO;
+    }
+
+    // Relay Driving
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 6)) {
+        pFaultCode->FaultEvents.bits.ChademoOutputRelayDrivingFault = YES;
+    } else {
+        pFaultCode->FaultEvents.bits.ChademoOutputRelayDrivingFault = NO;
+    }
+
+    // Connect temp Sensor broken
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 7)) {
+        pFaultCode->FaultEvents.bits.ChademoConnectorTempSensorBroken = YES;
+    } else {
+        pFaultCode->FaultEvents.bits.ChademoConnectorTempSensorBroken = NO;
+    }
+}
+
+static void checkEvBoardAlarmState(uint8_t gunType)
+{
+    switch (gunType) {
+    case _Type_Chademo:
+        checkChaDeMoAlarmState(gunType);
+        break;
+
+    case _Type_CCS_2:
+        checkCCSAlarmState(gunType);
+        break;
+
+    case _Type_GB:
+        checkGBTAlarmState(gunType);
+        break;
+    }
+}
+
+#if 0
+static uint8_t checkCabinetEthConnectState(LedConfig *ledConfig)
+{
+    uint8_t ret = NO;
+    LedConfig *pLedConfig = (LedConfig *)ledConfig;
+
+    if (pAlarmCode->AlarmEvents.bits.DisconnectedFromDo == YES) {
+        ret = YES;
+        if (pLedConfig->RedLED == YES) {
+            pLedConfig->RedLED = NO;
+        } else {
+            pLedConfig->RedLED = YES;
+        }
+    }
+
+    return ret;
+}
+
+static void PrimaryLedIndicatorCtrlFork(void)
+{
+#if !defined DD360ComBox
+    return;
+#endif //!defined DD360ComBox
+
+    pid_t pid = fork();
+    if (pid == 0) {
+        uint8_t totalGun = pSysConfig->TotalConnectorCount;
+        uint8_t gunIndex = 0;
+        int isContinue = 1;
+        LedConfig *pLedConfig = (LedConfig *)&ShmPrimaryMcuData->OutputDrv.OutputDrvValue[0];
+
+        while (isContinue) {
+            for (gunIndex = 0; gunIndex < totalGun; gunIndex++) {
+                pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+                //printf("led indicator status = %d\r\n", chargingInfo[gunIndex]->SystemStatus);
+                //printf("level = %d\r\n", pSysWarning->Level);
+                switch (pDcChargingInfo->SystemStatus) {
+                case S_BOOTING:
+                    if (pSysInfo->SelfTestSeq == _STEST_COMPLETE) {
+                        //Module_DoComm tcp disconnect
+                        if (pLedConfig->RedLED == YES ||
+                                pLedConfig->YellowLED == YES ||
+                                pLedConfig->GreenLED == YES) {
+                            pLedConfig->RedLED = NO;
+                            pLedConfig->YellowLED = NO;
+                            pLedConfig->GreenLED = NO;
+                        } else {
+                            pLedConfig->RedLED = YES;
+                            pLedConfig->YellowLED = YES;
+                            pLedConfig->GreenLED = YES;
+                        }
+                        break;
+                    }
+
+                    pLedConfig->RedLED = YES;
+                    pLedConfig->YellowLED = YES;
+                    pLedConfig->GreenLED = YES;
+                    break;
+
+                case S_IDLE:
+                    //Module_DoComm connected and system idle
+                    pLedConfig->RedLED = NO;
+                    pLedConfig->YellowLED = NO;
+                    pLedConfig->GreenLED = YES;
+                    break;
+
+                case S_RESERVATION:
+                case S_AUTHORIZING:
+                case S_REASSIGN_CHECK:
+                case S_REASSIGN:
+                case S_PREPARNING:
+                case S_PREPARING_FOR_EV:
+                case S_PREPARING_FOR_EVSE:
+                case S_CCS_PRECHARGE_ST0:
+                case S_CCS_PRECHARGE_ST1:
+                    //precharging status
+                    if (pLedConfig->GreenLED == YES) {
+                        pLedConfig->GreenLED = NO;
+                    } else {
+                        pLedConfig->GreenLED = YES;
+                    }
+                    break;
+
+                case S_CHARGING:
+                    pLedConfig->RedLED = NO;
+                    if (pLedConfig->YellowLED == YES) {
+                        pLedConfig->YellowLED = NO;
+                    } else {
+                        pLedConfig->YellowLED = YES;
+                    }
+                    pLedConfig->GreenLED = NO;
+                    break;
+
+                case S_ALARM:
+                    pLedConfig->YellowLED = NO;
+                    pLedConfig->GreenLED = NO;
+
+                    if (checkCabinetEthConnectState(pLedConfig) == YES) {
+                        break;
+                    }
+
+                    pLedConfig->RedLED = YES;
+                    break;
+
+                case S_TERMINATING:
+                case S_COMPLETE:
+                    if (pSysWarning->Level == 2) {
+                        pLedConfig->YellowLED = NO;
+                        pLedConfig->GreenLED = NO;
+                        if (checkCabinetEthConnectState(pLedConfig) == YES) {
+                            break;
+                        }
+
+                        pLedConfig->RedLED = YES;
+                    } else {
+                        pLedConfig->RedLED = NO;
+                        pLedConfig->YellowLED = YES;
+                        pLedConfig->GreenLED = NO;
+                    }
+                    break;
+
+                case S_MAINTAIN:
+                case S_FAULT:
+                    pLedConfig->YellowLED = NO;
+                    pLedConfig->GreenLED = NO;
+                    if (pSysWarning->Level == 2) {
+                        if (checkCabinetEthConnectState(pLedConfig) == YES) {
+                            break;
+                        }
+
+                        pLedConfig->RedLED = YES;
+                    }
+                    break;
+
+                case S_BOOKING:
+                case S_DEBUG:
+                case S_UPDATE:
+                case S_NONE:
+                    break;
+                }
+
+                usleep(500000);
+            }//switch
+        }//for
+    }//while
+}
+
+//================================================
+// initial can-bus
+//================================================
+int InitCanBus()
+{
+    int                     s0, nbytes;
+    struct timeval          tv;
+    struct ifreq            ifr0;
+    struct sockaddr_can     addr0;
+
+    system("/sbin/ip link set can0 down");
+    system("/sbin/ip link set can0 type can bitrate 500000 restart-ms 100");
+    system("/sbin/ip link set can0 up");
+
+    s0 = socket(PF_CAN, SOCK_RAW, CAN_RAW);
+
+    tv.tv_sec = 0;
+    tv.tv_usec = 10000;
+    if (setsockopt(s0, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct  timeval)) < 0) {
+#ifdef SystemLogMessage
+        log_error("Set SO_RCVTIMEO NG");
+#endif
+    }
+    nbytes = 40960;
+    if (setsockopt(s0, SOL_SOCKET,  SO_RCVBUF, &nbytes, sizeof(int)) < 0) {
+#ifdef SystemLogMessage
+        log_error("Set SO_RCVBUF NG");
+#endif
+    }
+    nbytes = 40960;
+    if (setsockopt(s0, SOL_SOCKET, SO_SNDBUF, &nbytes, sizeof(int)) < 0) {
+#ifdef SystemLogMessage
+        log_error("Set SO_SNDBUF NG");
+#endif
+    }
+
+    strcpy(ifr0.ifr_name, "can0" );
+    ioctl(s0, SIOCGIFINDEX, &ifr0); /* ifr.ifr_ifindex gets filled with that device's index */
+    addr0.can_family = AF_CAN;
+    addr0.can_ifindex = ifr0.ifr_ifindex;
+    bind(s0, (struct sockaddr *)&addr0, sizeof(addr0));
+    return s0;
+}
+
+//================================================
+// initial uart port
+//================================================
+char *_priPortName = "/dev/ttyS1";
+char *_485PortName = "/dev/ttyS5";
+
+int InitComPort(uint8_t target)
+{
+    int fd;
+    struct termios tios;
+
+    if (target == UPGRADE_PRI) {
+        fd = open(_priPortName, O_RDWR);
+    } else if (target == UPGRADE_FAN ||  target == UPGRADE_RB || target == UPGRADE_AC || target == UPGRADE_LED) {
+        fd = open(_485PortName, O_RDWR);
+    }
+
+    if (fd <= 0) {
+#ifdef SystemLogMessage
+        log_error("open 407 Communication port NG \n");
+#endif
+        return -1;
+    }
+    ioctl (fd, TCGETS, &tios);
+    tios.c_cflag = B115200 | CS8 | CLOCAL | CREAD;
+    tios.c_lflag = 0;
+    tios.c_iflag = 0;
+    tios.c_oflag = 0;
+    tios.c_cc[VMIN] = 0;
+    tios.c_cc[VTIME] = (uint8_t)1;
+    tios.c_lflag = 0;
+    tcflush(fd, TCIFLUSH);
+    ioctl (fd, TCSETS, &tios);
+
+    return fd;
+}
+
+//=================================
+// Common routine
+//=================================
+int StoreLogMsg_1(const char *fmt, ...)
+{
+    char Buf[4096 + 256];
+    char buffer[4096];
+    va_list args;
+    struct timeb  SeqEndTime;
+    struct tm *tm;
+
+    va_start(args, fmt);
+    int rc = vsnprintf(buffer, sizeof(buffer), fmt, args);
+    va_end(args);
+
+    memset(Buf, 0, sizeof(Buf));
+    ftime(&SeqEndTime);
+    SeqEndTime.time = time(NULL);
+    tm = localtime(&SeqEndTime.time);
+
+    if (pSysConfig->SwitchDebugFlag == YES) {
+        sprintf(Buf, "%02d:%02d:%02d:%03d - %s",
+                tm->tm_hour, tm->tm_min, tm->tm_sec, SeqEndTime.millitm, buffer);
+        printf("%s \n", Buf);
+    } else {
+        sprintf(Buf, "echo \"%04d-%02d-%02d %02d:%02d:%02d:%03d - %s\" >> /Storage/SystemLog/[%04d.%02d]SystemLog",
+                tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, SeqEndTime.millitm,
+                buffer,
+                tm->tm_year + 1900, tm->tm_mon + 1);
+        system(Buf);
+    }
+
+    return rc;
+}
+#endif //0
+
+unsigned long GetTimeoutValue(struct timeval _sour_time)
+{
+    struct timeval _end_time;
+    gettimeofday(&_end_time, NULL);
+
+    return 1000000 * (_end_time.tv_sec - _sour_time.tv_sec) + _end_time.tv_usec - _sour_time.tv_usec;
+}
+
+int DiffTimeb(struct timeb ST, struct timeb ET)
+{
+    //return milli-second
+    unsigned int StartTime, StopTime;
+
+    StartTime = (unsigned int)ST.time;
+    StopTime = (unsigned int)ET.time;
+    //return (StopTime-StartTime)*1000+ET.millitm-ST.millitm;
+    return (StopTime - StartTime);
+}
+
+bool CheckTimeOut(struct timeb ST)
+{
+    struct timeb ET;
+    unsigned int StartTime, StopTime;
+
+    ftime(&ET);
+    StartTime = (unsigned int) ST.time;
+    StopTime = (unsigned int) ET.time;
+    return (StopTime > StartTime) ? YES : NO;
+}
+
+void setChargerMode(uint8_t gun_index, uint8_t mode)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun_index);
+
+    pDcChargingInfo->SystemStatus = mode;
+}
+
+long long DiffTimebWithNow(struct timeb ST)
+{
+    //return milli-second
+    struct timeb ET;
+    long long StartTime, StopTime;
+
+    ftime(&ET);
+    StartTime = (long long)ST.time;
+    StopTime = (long long)ET.time;
+    return ((StopTime - StartTime) * 1000) + (ET.millitm - ST.millitm);
+}
+
+//==========================================
+// Log
+//==========================================
+void CheckFwSlotStatusLog()
+{
+    if (bd0_1_status == 0 && bd0_2_status == 1) {
+        log_info("Connector 1 : Chademo");
+    } else if (bd0_1_status == 1 && bd0_2_status == 0) {
+        log_info("Connector 1 : CCS");
+    } else if (bd0_1_status == 1 && bd0_2_status == 1) {
+        log_info("Connector 1 : GB");
+    }
+
+    if (bd1_1_status == 0 && bd1_2_status == 1) {
+        log_info("Connector 2 : Chademo");
+    } else if (bd1_1_status == 1 && bd1_2_status == 0) {
+        log_info("Connector 2 : CCS");
+    } else if (bd1_1_status == 1 && bd1_2_status == 1) {
+        log_info("Connector 2 : GB");
+    }
+}
+
+void CheckHwSlotStatusLog(uint8_t index)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+    if (pDcChargingInfo->Type == _Type_Chademo) {
+        log_info("Hw check : Connector %d, Type : Chademo, Evboard_id = %d \n",
+                 index, pDcChargingInfo->Evboard_id);
+    } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+        log_info("Hw check : Connector %d, Type : CCS, Evboard_id = %d \n",
+                 index, pDcChargingInfo->Evboard_id);
+    } else if (pDcChargingInfo->Type == _Type_GB) {
+        log_info("Hw check : Connector %d, Type : GB, Evboard_id = %d \n",
+                 index, pDcChargingInfo->Evboard_id);
+    }
+}
+
+//==========================================
+// Check interface status
+//==========================================
+int isInterfaceUp(const char *interface)
+{
+    int result = FAIL;
+
+    FILE *fp;
+    char cmd[256];
+    char buf[512];
+
+    strcpy(cmd, "ifconfig");
+    fp = popen(cmd, "r");
+    if (fp != NULL) {
+        while (fgets(buf, sizeof(buf), fp) != NULL) {
+            if (strstr(buf, interface) > 0) {
+                result = PASS;
+            }
+        }
+    }
+    pclose(fp);
+
+    return result;
+}
+
+#if 0
+//=================================
+// Create all share memory
+//=================================
+int CreateShareMemory()
+{
+    uint8_t rebootCount = 0;
+
+    int MeterSMId = FAIL;
+
+    if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo), IPC_CREAT | 0777)) < 0) {
+        return FAIL;
+    } else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0))  == (void *) - 1) {
+        return FAIL;
+    }
+    memset(ShmSysConfigAndInfo, 0, sizeof(struct SysConfigAndInfo));
+
+    if ((MeterSMId = shmget(ShmStatusCodeKey, sizeof(struct StatusCodeData), IPC_CREAT | 0777)) < 0) {
+        return FAIL;
+    } else if ((ShmStatusCodeData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+        return FAIL;
+    }
+
+    memset(ShmStatusCodeData, 0, sizeof(struct StatusCodeData));
+
+    //creat ShmPsuData
+    if ((MeterSMId = shmget(ShmPsuKey, sizeof(struct PsuData), IPC_CREAT | 0777)) < 0) {
+        return FAIL;
+    } else if ((ShmPsuData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+        return FAIL;
+    }
+    memset(ShmPsuData, 0, sizeof(struct PsuData));
+
+    if (CHAdeMO_QUANTITY > 0) {
+        if ((MeterSMId = shmget(ShmCHAdeMOCommKey, sizeof(struct CHAdeMOData),  IPC_CREAT | 0777)) < 0) {
+            return FAIL;
+        } else if ((ShmCHAdeMOData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+            return FAIL;
+        }
+        memset(ShmCHAdeMOData, 0, sizeof(struct CHAdeMOData));
+    }
+
+    if (GB_QUANTITY > 0) {
+        if ((MeterSMId = shmget(ShmGBTCommKey, sizeof(struct GBTData),  IPC_CREAT | 0777)) < 0) {
+            return FAIL;
+        } else if ((ShmGBTData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+            return FAIL;
+        }
+        memset(ShmGBTData, 0, sizeof(struct GBTData));
+    }
+
+    //creat ShmCcsData
+    if (CCS_QUANTITY > 0) {
+        if ((MeterSMId = shmget(ShmCcsCommKey, sizeof(struct CcsData),  IPC_CREAT | 0777)) < 0) {
+            return FAIL;
+        } else if ((ShmCcsData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+            return FAIL;
+        }
+        memset(ShmCcsData, 0, sizeof(struct CcsData));
+    }
+
+    //creat ShmPrimaryMcuData
+    if ((MeterSMId = shmget(ShmPrimaryMcuKey, sizeof(struct PrimaryMcuData), IPC_CREAT | 0777)) < 0) {
+        return FAIL;
+    } else if ((ShmPrimaryMcuData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+        return FAIL;
+    }
+    memset(ShmPrimaryMcuData, 0, sizeof(struct PrimaryMcuData));
+
+    //creat ShmFanModuleData
+    if ((MeterSMId = shmget(ShmFanBdKey, sizeof(struct FanModuleData),  IPC_CREAT | 0777)) < 0) {
+        return FAIL;
+    } else if ((ShmFanModuleData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+        return FAIL;
+    }
+    memset(ShmFanModuleData, 0, sizeof(struct FanModuleData));
+
+    //creat ShmRelayModuleData
+    if ((MeterSMId = shmget(ShmRelayBdKey, sizeof(struct RelayModuleData),  IPC_CREAT | 0777)) < 0) {
+        return FAIL;
+    } else if ((ShmRelayModuleData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+        return FAIL;
+    }
+    memset(ShmRelayModuleData, 0, sizeof(struct RelayModuleData));
+
+    if ((MeterSMId = shmget(ShmLedBdKey, sizeof(struct LedModuleData), IPC_CREAT | 0777)) < 0) {
+        return FAIL;
+    } else if ((ShmLedModuleData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+        return FAIL;
+    }
+    memset(ShmLedModuleData, 0, sizeof(struct LedModuleData));
+
+    //creat ShmOCPP16Data
+    if ((MeterSMId = shmget(ShmOcppModuleKey, sizeof(struct OCPP16Data), IPC_CREAT | 0777)) < 0) {
+        return FAIL;
+    } else if ((ShmOCPP16Data = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+        return FAIL;
+    }
+    // memset(ShmOCPP16Data,0,sizeof(struct OCPP16Data));
+
+#if defined DD360 ||defined DD360Audi || defined DD360ComBox
+    //creat Audi customization info
+    if ((MeterSMId = shmget(ShmSelectGunInfoKey, sizeof(SelectGunInfo), IPC_CREAT | 0777)) < 0) {
+        return FAIL;
+    } else if ((gAudiCustInfo = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+        return FAIL;
+    }
+    memset(gAudiCustInfo, 0, sizeof(SelectGunInfo));
+#endif //defined DD360Audi
+
+    if ((MeterSMId = shmget(ShmCommonKey, sizeof(DcCommonInfo), IPC_CREAT | 0777)) < 0) {
+        return FAIL;
+    } else if ((ShmDcCommonData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+        return FAIL;
+    }
+
+    if (ShmDcCommonData->RebootCount == 1) {
+        rebootCount = ShmDcCommonData->RebootCount;
+    }
+    memset(ShmDcCommonData, 0, sizeof(DcCommonInfo));
+
+    ShmDcCommonData->RebootCount = rebootCount;
+
+    return PASS;
+}
+
+#endif //0
+
+//=================================
+// LCM Page
+//=================================
+void ChangeLcmByIndex(uint8_t page_index)
+{
+    if (pSysWarning->Level != 2 ||
+            page_index == _LCM_COMPLETE || page_index == _LCM_FIX) {
+        pSysInfo->PageIndex = page_index;
+    }
+}
+
+//======================================================
+// Peripheral initial
+//======================================================
+void InitGPIO()
+{
+    /*****************0~3, 4 bank, bank x 32+ num*********************/
+    /***************************************************************/
+    /*************** GPIO 0 ***************************************/
+    /***************************************************************/
+    /* GPMC_AD8         =>  GPIO0_22 *//*ID BD1_1*/
+    system("echo 22 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio22/direction");
+    /* GPMC_AD9         =>  GPIO0_23 *//*ID BD1_2*/
+    system("echo 23 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio23/direction");
+    /* GPMC_AD10        =>  GPIO0_26 *//*IO BD1_1*/
+    system("echo 26 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio26/direction");
+    system("echo 1 > /sys/class/gpio/gpio26/value");
+    /* GPMC_AD11        =>  GPIO0_27 *//*IO BD1_2*/
+    system("echo 27 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio27/direction");
+    /* RMII1_REF_CLK        =>  GPIO0_29 *//*USB 0 OCP detection*/
+    system("echo 29 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio29/direction");
+    /*XDMA_EVENT_INTR0  =>  GPIO0_19 *//*AM_RFID_RST*/
+    system("echo 19 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio19/direction");
+    system("echo 1 > /sys/class/gpio/gpio19/value");
+    /*XDMA_EVENT_INTR1  =>  GPIO0_20 *//*AM_RFID_ICC*/
+    system("echo 20 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio20/direction");
+    /***************************************************************/
+    /*************** GPIO 1 ***************************************/
+    /***************************************************************/
+    /* GPMC_AD12    =>  GPIO1_12 *//*ID BD2_1*/
+    system("echo 44 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio44/direction");
+    /* GPMC_AD13    =>  GPIO1_13 *//*ID BD2_2*/
+    system("echo 45 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio45/direction");
+    /* GPMC_AD14    =>  GPIO1_14 *//*IO BD2_1*/
+    system("echo 46 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio46/direction");
+    system("echo 0 > /sys/class/gpio/gpio46/value");
+    /* GPMC_AD15    =>  GPIO1_15 *//*IO BD2_2*/
+    system("echo 47 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio47/direction");
+    /***************************************************************/
+    /*************** GPIO 2 ***************************************/
+    /***************************************************************/
+    /*LCD_AC_BIAS_EN    =>  GPIO2_25*//*RS-485 for module DE control*/
+    system("echo 89 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio89/direction");
+    system("echo 1 > /sys/class/gpio/gpio89/value");
+    /*LCD_HSYNC     =>  GPIO2_23*//*RS-485 for module RE control*/
+    system("echo 87 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio87/direction");
+    system("echo 0 > /sys/class/gpio/gpio87/value");
+    /*LCD_PCLK      =>  GPIO2_24*//*CCS communication board 1 proximity*/
+    system("echo 88 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio88/direction");
+    /*LCD_VSYNC     =>  GPIO2_22*//*CCS communication board 2 proximity*/
+    system("echo 86 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio86/direction");
+    /***************************************************************/
+    /*************** GPIO 3 ***************************************/
+    /***************************************************************/
+    /*MCASP0_FSX        =>  GPIO3_15*//*Emergency Stop button detect*/
+    system("echo 111 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio111/direction");
+    /*MCASP0_ACLKR  =>  GPIO3_18*//*USB1 OCP detect*/
+    system("echo 114 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio114/direction");
+    /*MCASP0_AHCLKR =>  GPIO3_17*//*Emergency IO for AM3352 and STM32F407*/
+    system("echo 113 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio113/direction");
+    /*MCASP0_ACLKX  =>  GPIO3_14*//*Ethernet PHY reset*/
+    system("echo 110 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio110/direction");
+    system("echo 0 > /sys/class/gpio/gpio110/value");
+    /* MCASP0_FSR       =>  GPIO3_19 *//*SMR Enable control_1 for Pskill_1*/
+    system("echo 115 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio115/direction");
+    system("echo 0 > /sys/class/gpio/gpio115/value");
+    /* MCASP0_AXR0  =>  GPIO3_16 *//*CSU board function OK indicator.*/
+    system("echo 112 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio112/direction");
+    system("echo 1 > /sys/class/gpio/gpio112/value");
+    /* MCASP0_AXR1  =>  GPIO3_20 *//*SMR Enable control_2 for Pskill_2*/
+    system("echo 116 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio116/direction");
+    system("echo 0 > /sys/class/gpio/gpio116/value");
+
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+    /* (C14) EMU0.gpio3[7] */  /*CP open/short feature enable/disable, pull low for default enable*/
+    system("echo 103 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio103/direction");
+    system("echo 0 > /sys/class/gpio/gpio103/value");
+    /* (B14) EMU1.gpio3[8] */  /*4G module reset, pull high to reset when entry kernel, after Application start, it should be pull low.*/
+    system("echo 104 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio104/direction");
+    system("echo 0 > /sys/class/gpio/gpio104/value");
+#endif //!defined DD360 && !defined DD360Audi
+
+    log_info("Initial GPIO OK");
+}
+
+int LoadSysConfigAndInfo(struct SysConfigData *ptr)
+{
+    int fd, wrd;
+    uint8_t *buf;
+    unsigned int ChkSum, ChkSumOrg;
+
+    if ((buf = malloc(MtdBlockSize)) == NULL) {
+        log_error("malloc buffer NG,rebooting..\r\n");
+        if (pAlarmCode != NULL) {
+            pAlarmCode->AlarmEvents.bits.CsuInitFailed = 1;
+        }
+        sleep(5);
+        system("reboot -f");
+        sleep(5);
+        system("reboot -f");
+    }
+    memset(buf, 0, MtdBlockSize);
+
+    //================================================
+    // Load configuration from mtdblock10
+    //================================================
+    fd = open("/dev/mtdblock10", O_RDWR);
+    if (fd < 0) {
+        free(buf);
+        log_error("open mtdblock10 NG,rebooting..\r\n");
+        if (pAlarmCode != NULL) {
+            pAlarmCode->AlarmEvents.bits.CsuInitFailed = 1;
+        }
+        sleep(5);
+        system("reboot -f");
+        sleep(5);
+        system("reboot -f");
+    }
+
+    wrd = read(fd, buf, MtdBlockSize);
+    close(fd);
+    if (wrd < MtdBlockSize) {
+        free(buf);
+        log_error("read SysConfigData data NG,rebooting..\r\n");
+        if (pAlarmCode != NULL) {
+            pAlarmCode->AlarmEvents.bits.CsuInitFailed = 1;
+        }
+        sleep(5);
+        system("reboot -f");
+        sleep(5);
+        system("reboot -f");
+    }
+    ChkSum = 0;
+    for (wrd = 0; wrd < MtdBlockSize - 4; wrd++) {
+        ChkSum += buf[wrd];
+    }
+    memcpy(&ChkSumOrg, buf + (0x00600000 - 4), sizeof(ChkSumOrg));
+
+    //================================================
+    // Load configuration from mtdblock11
+    //================================================
+    if (ChkSum != ChkSumOrg) {
+        log_error("Primary SysConfigData checksum NG, read backup\r\n");
+        fd = open("/dev/mtdblock11", O_RDWR);
+        if (fd < 0) {
+            free(buf);
+            log_error("open mtdblock11 (backup) NG,rebooting..\r\n");
+            if (pAlarmCode != NULL) {
+                pAlarmCode->AlarmEvents.bits.CsuInitFailed = 1;
+            }
+            sleep(5);
+            system("reboot -f");
+            sleep(5);
+            system("reboot -f");
+        }
+
+        memset(buf, 0, MtdBlockSize);
+        wrd = read(fd, buf, MtdBlockSize);
+        close(fd);
+        if (wrd < MtdBlockSize) {
+            free(buf);
+            log_error("read backup SysConfigData data NG,rebooting..\r\n");
+            if (pAlarmCode != NULL) {
+                pAlarmCode->AlarmEvents.bits.CsuInitFailed = 1;
+            }
+            sleep(5);
+            system("reboot -f");
+            sleep(5);
+            system("reboot -f");
+        }
+        ChkSum = 0;
+        for (wrd = 0; wrd < MtdBlockSize - 4; wrd++) {
+            ChkSum += buf[wrd];
+        }
+        memcpy(&ChkSumOrg, buf + (0x00600000 - 4), sizeof(ChkSumOrg));
+
+        //================================================
+        // Load configuration from mtdblock12 (Factory default)
+        //================================================
+        if (ChkSum != ChkSumOrg) {
+            log_error("backup SysConfigData checksum NG, read Factory default\r\n");
+            fd = open("/dev/mtdblock12", O_RDWR);
+            if (fd < 0) {
+                free(buf);
+                log_error("open mtdblock12 (Factory default) NG,rebooting..\r\n");
+                if (pAlarmCode != NULL) {
+                    pAlarmCode->AlarmEvents.bits.CsuInitFailed = 1;
+                }
+                sleep(5);
+                system("reboot -f");
+                sleep(5);
+                system("reboot -f");
+            }
+            memset(buf, 0, MtdBlockSize);
+            wrd = read(fd, buf, MtdBlockSize);
+            close(fd);
+            if (wrd < MtdBlockSize) {
+                free(buf);
+                log_error("read factory default  SysConfigData data NG,rebooting..\r\n");
+                if (pAlarmCode != NULL) {
+                    pAlarmCode->AlarmEvents.bits.CsuInitFailed = 1;
+                }
+                sleep(5);
+                system("reboot -f");
+                sleep(5);
+                system("reboot -f");
+            }
+            ChkSum = 0;
+            for (wrd = 0; wrd < MtdBlockSize - 4; wrd++) {
+                ChkSum += buf[wrd];
+            }
+            memcpy(&ChkSumOrg, buf + (0x00600000 - 4), sizeof(ChkSumOrg));
+            if (ChkSum != ChkSumOrg) {
+                log_error("factory default  SysConfigData checksum NG, restore factory default\r\n");
+                free(buf);
+                system("cd /root;./FactoryConfig -m");
+                system("sync");
+                sleep(5);
+                system("reboot -f");
+                sleep(5);
+                system("reboot -f");
+
+                return FAIL;
+            }
+        }
+    }
+
+    //load OK
+    memcpy((struct SysConfigData *)ptr, buf, sizeof(struct SysConfigData));
+    free(buf);
+    //log_info("Load SysConfigData OK\n");
+    return PASS;
+}
+
+#if 0
+int isRouteFail()
+{
+    int result = YES;
+    FILE *fp;
+    char buf[512];
+
+    fp = popen("route -n", "r");
+    if (fp != NULL) {
+        while (fgets(buf, sizeof(buf), fp) != NULL) {
+            if (strstr(buf, "eth0") != NULL) {
+                result = NO;
+            }
+        }
+    }
+    pclose(fp);
+
+    return result;
+}
+
+//static void eth0Down(void)
+//{
+//    char cmdbuf[256] = {0};
+//
+//    sprintf(cmdbuf, "/sbin/ifconfig eth0 down");
+//}
+
+//static void eth0Up(void)
+//{
+//    char cmdbuf[256] = {0};
+//
+//    sprintf(cmdbuf, "/sbin/ifconfig eth0 %s up", pSysConfig->Eth0Interface.EthIpAddress);
+//}
+
+int isReachableInternet()
+{
+    int result = FAIL;
+    FILE *fp;
+    char cmd[256];
+    char buf[512];
+    char tmp[512];
+
+    strcpy(cmd, "ifconfig eth0");
+    fp = popen(cmd, "r");
+
+    if (fp != NULL) {
+        while (fgets(buf, sizeof(buf), fp) != NULL) {
+            if (strstr(buf, "inet addr:") > 0) {
+                sscanf(buf, "%*s%s", tmp);
+                substr(tmp, tmp, strspn(tmp, "addr:"), strlen(buf) - strspn(tmp, "addr:"));
+
+                if (strcmp(tmp, (char *)pSysConfig->Eth0Interface.EthIpAddress) != EQUAL) {
+                    strcpy((char *) pSysConfig->Eth0Interface.EthIpAddress, tmp);
+                }
+            }
+        }
+    }
+    pclose(fp);
+
+#if defined DD360 ||defined DD360Audi || defined DD360ComBox
+    if (pAlarmCode->AlarmEvents.bits.DisconnectedFromDo == NORMAL) {
+        result = FAIL;
+    } else {
+        result = PASS;
+    }
+#else
+    memset(buf, 0x00, sizeof(buf));
+    for (int idx = 0; idx < ARRAY_SIZE(valid_Internet); idx++) {
+        sprintf(cmd, "ping -c 1 -w 3 -I eth0 %s", valid_Internet[idx]);
+        fp = popen(cmd, "r");
+        if (fp != NULL) {
+            while (fgets(buf, sizeof(buf), fp) != NULL) {
+                if (strstr(buf, "transmitted") > 0) {
+                    //sscanf(buf, "%*s%*s%*s%*s%*s%*s%s", tmp);
+
+                    if (strstr(buf, "100%") != NULL) {
+                    } else {
+                        result = PASS;
+                    }
+                    //DEBUG_INFO("%s",buf);
+                    //DEBUG_INFO("%s\n",tmp);
+                }
+            }
+        }
+        pclose(fp);
+    }
+
+#endif //defined DD360 || defined DD360Audi
+
+    return result;
+}
+
+void InitEthernet()
+{
+    char tmpbuf[256];
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+    bool ethResult = false;
+    uint8_t cnt_pingDNS_Fail = 0;
+#endif //!defined DD360 && !defined DD360Audi
+
+    system("ifconfig eth0 down");// eth0 down
+    system("ifconfig eth1 down");// eth1 down
+    sleep(2);
+
+    // /sbin/ifconfig eth0 192.168.1.10 netmask 255.255.255.0 down
+    system("echo 1 > /sys/class/gpio/gpio110/value");//reset PHY
+    sleep(2);
+    //Init Eth0 for internet
+    memset(tmpbuf, 0, 256);
+    sprintf(tmpbuf, "/sbin/ifconfig eth0 %s netmask %s up",
+            pSysConfig->Eth0Interface.EthIpAddress,
+            pSysConfig->Eth0Interface.EthSubmaskAddress);
+    //sprintf(tmpbuf,"/sbin/ifconfig eth0 192.168.100.10 netmask 255.255.255.0 up");
+    system(tmpbuf);
+
+    memset(tmpbuf, 0, 256);
+    sprintf(tmpbuf, "route add default gw %s eth0 ",
+            pSysConfig->Eth0Interface.EthGatewayAddress);
+    //sprintf(tmpbuf,"route add default gw 192.168.100.1 eth0 ");
+    system(tmpbuf);
+    //system("ifconfig lo up");
+    //  /sbin/ifconfig eth0 192.168.1.10 netmask 255.255.255.0 up
+    //Init Eth1 for administrator tool
+    memset(tmpbuf, 0, 256);
+    sprintf(tmpbuf, "/sbin/ifconfig eth1 %s netmask %s up",
+            pSysConfig->Eth1Interface.EthIpAddress,
+            pSysConfig->Eth1Interface.EthSubmaskAddress);
+    system(tmpbuf);
+
+    //Run DHCP client if enabled
+    system("killall udhcpc");
+    system("rm -rf /etc/resolv.conf");
+    system("echo nameserver 8.8.8.8 > /etc/resolv.conf");       //Google DNS server
+    system("echo nameserver 180.76.76.76 > /etc/resolv.conf");  //Baidu DNS server
+    //system("/sbin/ifconfig eth0 down;/sbin/ifconfig eth0 up");
+
+    if (pSysConfig->Eth0Interface.EthDhcpClient == 0) {
+        sprintf(tmpbuf, "/sbin/udhcpc -i eth0 -x hostname:CSU3_%s -s /root/dhcp_script/eth0.script > /dev/null &",
+                pSysConfig->SystemId);
+        system(tmpbuf);
+    }
+
+    //Upgrade system id to /etc/hostname
+    sprintf(tmpbuf, "echo %s > /etc/hostname", pSysConfig->SystemId);
+    system(tmpbuf);
+
+    pid_t pid = fork();
+    if (pid == 0) {
+        log_info("InitEthernet = %d\r\n", pid);
+        for (;;) {
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+            if (isRouteFail()) {
+                //log_info("eth0 not in route, restart eht0. \n");
+                system("/sbin/ifconfig eth0 down;/sbin/ifconfig eth0 up");
+
+                if (pSysConfig->Eth0Interface.EthDhcpClient == 0) {
+                    InitialDHCP();
+                }
+            }
+
+            if (isReachableInternet() == PASS) {
+                pSysInfo->ethInternetConn = YES;
+                cnt_pingDNS_Fail = 0;
+            } else {
+                if (++cnt_pingDNS_Fail > 3) {
+                    pSysInfo->ethInternetConn = NO;
+                }
+            }
+
+            ethResult = pSysInfo->ethInternetConn;
+
+            if (ethResult == YES) {
+                system("/sbin/ifmetric eth0 0");
+
+                if ((pSysConfig->ModelName[10] == 'W') ||
+                        (pSysConfig->ModelName[10] == 'D')) {
+                    system("/sbin/ifmetric mlan0 1");
+                }
+
+                if ((pSysConfig->ModelName[10] == 'T') ||
+                        (pSysConfig->ModelName[10] == 'D')) {
+                    system("/sbin/ifmetric ppp0 2");
+                }
+            }
+
+            if (!ethResult &&
+                    pSysConfig->AthInterface.WifiMode != _SYS_WIFI_MODE_DISABLE &&
+                    (pSysConfig->ModelName[10] == 'W' ||
+                     pSysConfig->ModelName[10] == 'D')) {
+                //ethResult = pSysConfig->AthInterface.WifiNetworkConn;
+                ethResult = pInfoCode->InfoEvents.bits.InternetDisconnectViaWiFi == YES ? NO : YES;
+
+                if (ethResult) {
+                    if ((pSysConfig->ModelName[10] == 'W') ||
+                            (pSysConfig->ModelName[10] == 'D')) {
+                        system("/sbin/ifmetric eth0 1");
+                        system("/sbin/ifmetric mlan0 0");
+                    }
+
+
+                    if ((pSysConfig->ModelName[10] == 'T') ||
+                            (pSysConfig->ModelName[10] == 'D')) {
+                        system("/sbin/ifmetric ppp0 2");
+                    }
+                }
+            }
+
+            if (!ethResult &&
+                    pSysConfig->TelecomInterface.TelcomEnabled == YES &&
+                    (pSysConfig->ModelName[10] == 'T' ||
+                     pSysConfig->ModelName[10] == 'D')) {
+                //ethResult = pSysConfig->TelecomInterface.TelcomNetworkConn;
+                ethResult = pInfoCode->InfoEvents.bits.InternetDisconnectVia4Gi == YES ? NO : YES;
+
+                if (ethResult) {
+                    if ((pSysConfig->ModelName[10] == 'W') ||
+                            (pSysConfig->ModelName[10] == 'D')) {
+                        system("/sbin/ifmetric mlan0 2");
+                    }
+
+                    if ((pSysConfig->ModelName[10] == 'T') ||
+                            (pSysConfig->ModelName[10] == 'D')) {
+                        system("/sbin/ifmetric eth0 1");
+                        system("/sbin/ifmetric ppp0 0");
+                    }
+                }
+            }
+
+            pSysInfo->InternetConn = ethResult;
+#else
+            isReachableInternet();
+#endif //!defined DD360 && !defined DD360
+
+            sleep(5);
+        }
+    }
+
+    log_info("Initial Ethernet OK\r\n");
+}
+
+int InitialRfidPort()
+{
+    int uartO2 = open(rfidPortName, O_RDWR);
+    struct termios tios;
+
+    if (uartO2 != FAIL) {
+        ioctl (uartO2, TCGETS, &tios);
+        tios.c_cflag = B19200 | CS8 | CLOCAL | CREAD;
+        tios.c_lflag = 0;
+        tios.c_iflag = 0;
+        tios.c_oflag = 0;
+        tios.c_cc[VMIN] = 0;
+        tios.c_cc[VTIME] = (uint8_t) 1;
+        tios.c_lflag = 0;
+        tcflush(uartO2, TCIFLUSH);
+        ioctl(uartO2, TCSETS, &tios);
+    }
+
+    if (uartO2 < 0) {
+        pAlarmCode->AlarmEvents.bits.RfidModuleCommFail = 1;
+    }
+
+    return uartO2;
+}
+
+void GetMacAddress()
+{
+    for (uint8_t index = 0; index < 2; index++) {
+        int fd;
+        struct ifreq ifr;
+        char tarEth[5];
+        char Mac[18];
+
+        sprintf(tarEth, "eth%d", index);
+        fd = socket(AF_INET, SOCK_DGRAM, 0);
+
+        ifr.ifr_addr.sa_family = AF_INET;
+        strncpy(ifr.ifr_name, tarEth, IFNAMSIZ - 1);
+
+        ioctl(fd, SIOCGIFHWADDR, &ifr);
+        close(fd);
+
+        sprintf(Mac, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
+                ifr.ifr_hwaddr.sa_data[0], ifr.ifr_hwaddr.sa_data[1], ifr.ifr_hwaddr.sa_data[2],
+                ifr.ifr_hwaddr.sa_data[3], ifr.ifr_hwaddr.sa_data[4], ifr.ifr_hwaddr.sa_data[5]);
+
+        if (index == 0) {
+            strcpy((char *) pSysConfig->Eth0Interface.EthMacAddress, Mac);
+        } else {
+            strcpy((char *) pSysConfig->Eth1Interface.EthMacAddress, Mac);
+        }
+    }
+}
+
+void GetFirmwareVersion()
+{
+    // Get CSU root file system version
+    sprintf((char *)pSysInfo->CsuRootFsFwRev, fwVersion);
+
+    uint8_t count = 0, chademo = 0, ccs = 0, gb = 0;
+    for (uint8_t idx = 0; idx < 3; idx++) {
+        if (pSysConfig->ModelName[7 + idx] == 'J') {
+            chademo++;
+            count++;
+        } else if (pSysConfig->ModelName[7 + idx] == 'G') {
+            gb++;
+            count++;
+        } else if (pSysConfig->ModelName[7 + idx] == 'U' ||
+                   pSysConfig->ModelName[7 + idx] == 'V' ||
+                   pSysConfig->ModelName[7 + idx] == 'E') {
+            ccs++;
+            count++;
+        }
+    }
+
+    if (count == 1) {
+        if (chademo > 0) {
+            pSysInfo->CsuRootFsFwRev[7] = '1';
+        } else if (ccs > 0) {
+            pSysInfo->CsuRootFsFwRev[7] = '2';
+        } else if (gb > 0) {
+            pSysInfo->CsuRootFsFwRev[7] = '3';
+        }
+    } else {
+        if (chademo > 0 && ccs > 0) {
+            pSysInfo->CsuRootFsFwRev[7] = '4';
+        } else if (chademo > 0 && gb > 0) {
+            pSysInfo->CsuRootFsFwRev[7] = '5';
+        } else if (ccs > 0 && gb > 0) {
+            pSysInfo->CsuRootFsFwRev[7] = '6';
+        }
+    }
+
+    // Get network option from model name
+    switch (pSysConfig->ModelName[10]) {
+    case 'B':
+    case 'U':
+        //Blue tooth
+        pSysInfo->CsuRootFsFwRev[9] = '3';
+        break;
+    case 'W':
+        // WIFI
+        pSysInfo->CsuRootFsFwRev[9] = '1';
+        break;
+    case 'T':
+        // 3G/4G
+        pSysInfo->CsuRootFsFwRev[9] = '2';
+        break;
+    case 'D': //DS60-120 add
+        pSysInfo->CsuRootFsFwRev[9] = '5';
+        break;
+    default:
+        // LAN
+        pSysInfo->CsuRootFsFwRev[9] = '0';
+        break;
+    }
+    // Get rating power from model name
+    memcpy(&pSysInfo->CsuRootFsFwRev[10], &pSysConfig->ModelName[4], 0x03);
+
+    // Get IEC or UL
+    char _buf[3] = {0};
+    memcpy(_buf, &pSysConfig->ModelName[2], 2);
+
+    if (strcmp(_buf, "YE") == EQUAL || strcmp(_buf, "YC") == EQUAL) {
+        pSysInfo->ChargerType = _CHARGER_TYPE_IEC;
+        log_info("IEC model");
+    } else if (strcmp(_buf, "WU") == EQUAL) {
+        pSysInfo->ChargerType = _CHARGER_TYPE_UL;
+        log_info("UL model");
+    }
+}
+
+//DS60-120 add
+void InitialGunIndexToUnUse()
+{
+    for (uint8_t index = 0; index < CHAdeMO_QUANTITY; index++) {
+        pSysInfo->ChademoChargingData[index].Index = NO_DEFINE;
+    }
+
+    for (uint8_t index = 0; index < CCS_QUANTITY; index++) {
+        pSysInfo->CcsChargingData[index].Index = NO_DEFINE;
+    }
+
+    for (uint8_t index = 0; index < GB_QUANTITY; index++) {
+        pSysInfo->GbChargingData[index].Index = NO_DEFINE;
+    }
+
+    for (uint8_t index = 0; index < AC_QUANTITY; index++) {
+        pSysInfo->AcChargingData[index].Index = NO_DEFINE;
+    }
+}
+
+void InitialShareMemoryInfo()
+{
+    FILE *fp;
+    char cmd[512];
+    char buf[512];
+
+    sprintf((char *)pSysConfig->TelecomInterface.TelcomApn, "Internet");
+    sprintf((char *)pSysConfig->TelecomInterface.TelcomChapPapId, " ");
+    sprintf((char *)pSysConfig->TelecomInterface.TelcomChapPapPwd, " ");
+
+    pSysConfig->TotalConnectorCount = 0;
+    pSysConfig->AcConnectorCount = 0;
+
+    pSysInfo->FactoryConfiguration = 0;
+    pSysInfo->InputVoltageR = 0;
+    pSysInfo->InputVoltageS = 0;
+    pSysInfo->InputVoltageT = 0;
+    pSysInfo->SystemFanRotaSpeed = 0;
+    pSysInfo->PsuFanRotaSpeed = 0;
+    pSysInfo->AuxPower5V = 0;
+    pSysInfo->AuxPower12V = 0;
+    pSysInfo->AuxPower24V = 0;
+    pSysInfo->AuxPower48V = 0;
+
+    sprintf((char *)pSysInfo->CsuHwRev, "REV:5.0");
+    memcpy(pSysInfo->CsuBootLoadFwRev, pSysConfig->CsuBootLoadFwRev, ARRAY_SIZE(pSysConfig->CsuBootLoadFwRev));
+
+    sprintf(cmd, "/bin/uname -r");
+    fp = popen(cmd, "r");
+    if (fp == NULL) {
+        sprintf((char *)pSysInfo->CsuKernelFwRev, "Unknown version");
+    } else {
+        while (fgets(buf, sizeof(buf), fp) != NULL) {
+            strcpy((char *)pSysInfo->CsuKernelFwRev, buf);
+        }
+    }
+
+    // 雙槍 CCS + Chademo
+    GetFirmwareVersion();
+    //sprintf((char *) pSysInfo->CsuRootFsFwRev, fwVersion);
+    sprintf((char *) pSysInfo->CsuPrimFwRev, " ");
+
+    sprintf((char *) pSysInfo->LcmHwRev, " ");
+    sprintf((char *) pSysInfo->LcmFwRev, " ");
+    sprintf((char *) pSysInfo->PsuHwRev, " ");
+    sprintf((char *) pSysInfo->PsuPrimFwRev, " ");
+    sprintf((char *) pSysInfo->PsuSecFwRev, " ");
+    sprintf((char *) pSysInfo->AuxPwrHwRev, " ");
+    sprintf((char *) pSysInfo->AuxPwrFwRev, " ");
+    sprintf((char *) pSysInfo->FanModuleHwRev, " ");
+    sprintf((char *) pSysInfo->FanModuleFwRev, " ");
+    sprintf((char *) pSysInfo->RelayModuleHwRev, " ");
+    sprintf((char *) pSysInfo->RelayModuleFwRev, " ");
+    sprintf((char *) pSysInfo->TelcomModemFwRev, " ");
+    pSysInfo->SystemAmbientTemp = 0;
+    pSysInfo->SystemCriticalTemp = 0;
+    pSysInfo->PsuAmbientTemp = 0;
+    pSysInfo->CcsConnectorTemp = 0;
+    pSysInfo->InternetConn = 0;
+    pSysInfo->OcppConnStatus = 0;
+    pSysInfo->OrderCharging = NO_DEFINE;
+
+    strcpy((char *) pSysConfig->UserId, "");
+
+    pAlarmCode->AlarmEvents.bits.RelayboardStestFail = NO;
+    pAlarmCode->AlarmEvents.bits.FanboardStestFail = NO;
+    pAlarmCode->AlarmEvents.bits.PrimaryStestFail = NO;
+    pAlarmCode->AlarmEvents.bits.LedboardStestFail = NO; //DS60-120 Add
+    pAlarmCode->AlarmEvents.bits.ChademoboardStestFail = NO;
+    pAlarmCode->AlarmEvents.bits.CCSboardStestFail = NO;
+    pAlarmCode->AlarmEvents.bits.AcContactStestFail = NO;
+    pAlarmCode->AlarmEvents.bits.PsuModuleStestFail = NO;
+    pAlarmCode->AlarmEvents.bits.PsuDipSwitchStestFail = NO; //DS60-120 Add
+    pSysConfig->QRCodeMadeMode = NO; //DS60-120 add
+
+    memset(pSysInfo->FanModuleFwRev, 0, ARRAY_SIZE(pSysInfo->FanModuleFwRev));
+    memset(pSysInfo->RelayModuleFwRev, 0, ARRAY_SIZE(pSysInfo->RelayModuleFwRev));
+    ShmPrimaryMcuData->SelfTest_Comp = NO;
+    ShmRelayModuleData->SelfTest_Comp = NO;
+    ShmFanModuleData->SelfTest_Comp = NO;
+    ShmLedModuleData->SelfTest_Comp = NO;
+#if defined DD360Audi
+    pSysInfo->SystemPage = _LCM_SELECT_GUN;
+#else
+    pSysInfo->SystemPage = _LCM_NONE;
+#endif //defined DD360Audi
+    pSysInfo->MainChargingMode = _MAIN_CHARGING_MODE_MAX;
+    pSysInfo->ReAssignedFlag = _REASSIGNED_NONE;
+    pSysInfo->CurGunSelectedByAc = NO_DEFINE;
+    pSysInfo->BootingStatus = BOOTTING; //DS60-120 add
+
+    ShmFanModuleData->TestFanSpeed = 0;
+
+    pAlarmCode->AlarmEvents.bits.ModelNameNoneMatchStestFail = NO;
+    pAlarmCode->AlarmEvents.bits.PsuNoResource = NO;
+
+    //--- DS60-120 remove -----
+    /*char EvsePower[2];
+
+    EvsePower[2] = '\0';
+    unsigned short buf_pow = 0;
+    if (strlen((char *) pSysConfig->ModelName) >= 6) {
+        strncpy(EvsePower, (char *)(pSysConfig->ModelName + 4), 2);
+        if (strcmp(EvsePower, "15") == EQUAL) {
+            buf_pow = 150;
+        } else if (strcmp(EvsePower, "30") == EQUAL) {
+            buf_pow = 30;
+        } else if (strcmp(EvsePower, "60") == EQUAL) {
+            buf_pow = 60;
+        } else if (strcmp(EvsePower, "12") == EQUAL) {
+            buf_pow = 120;
+        } else if (strcmp(EvsePower, "18") == EQUAL) {
+            buf_pow = 180;
+        } else if (strcmp(EvsePower, "36") == EQUAL) {
+            buf_pow = 360;
+        }
+
+        pSysConfig->RatingCurrent = (buf_pow / 30) * PSU_MIN_CUR;
+
+        if (pSysConfig->MaxChargingPower == 0 ||
+                pSysConfig->MaxChargingPower > buf_pow) {
+            pSysConfig->MaxChargingPower = buf_pow;
+        }
+    }
+    */
+    //--------------------------------------------------------------------------
+
+    InitialGunIndexToUnUse();//DS60-120 add
+
+    //ShmDcCommonData->CcsVersion = _CCS_VERSION_CHECK_TAG_V015S0;
+    //ShmDcCommonData->psuKeepCommunication = NO;
+    //ShmDcCommonData->acContactSwitch = NO;
+    ShmDcCommonData->ConnectErrList[0].GunErrMessage = 0;
+    ShmDcCommonData->ConnectErrList[1].GunErrMessage = 0;
+    //ShmDcCommonData->LcmFwVersion = 0;
+
+    pSysConfig->SwitchDebugFlag = NO;
+    pSysConfig->AlwaysGfdFlag = NO;
+
+    log_info("3InitialShareMemoryInfo done...\r\n");
+}
+#endif //0
+
+int Initialization()
+{
+    // 初始化卡號驗證的 Flag
+    ClearAuthorizedFlag();
+
+    // 初始化插槍驗證的 Flag
+    ClearDetectPluginFlag();
+
+    // UART 2 for Rfid
+    //rfidFd = InitialRfidPort();
+
+    int pinOut[2] = { 116, 115 };
+    for (uint8_t count = 0; count < pSysConfig->TotalConnectorCount; count++) {
+        pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(count);
+
+        pDcChargingInfo->RemoteStartFlag = NO;
+
+        if (pDcChargingInfo->Type == _Type_Chademo) {
+            gpio_set_value(pinOut[count], 0x00);
+            ShmCHAdeMOData->evse[pDcChargingInfo->type_index].SelfTest_Comp = NO;
+        } else if (pDcChargingInfo->Type == _Type_GB) {
+            gpio_set_value(pinOut[count], 0x00);
+            ShmGBTData->evse[pDcChargingInfo->type_index].SelfTest_Comp = NO;
+        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+            //if (ShmCcsData->CommProtocol == _CCS_COMM_V2GMessage_DIN70121) { //DS60-120 remove
+            if (pSysConfig->TotalConnectorCount == 1) {
+                gpio_set_value(pinOut[1], 0x01);
+            } else {
+                gpio_set_value(pinOut[count], 0x01);
+            }
+            ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].SelfTest_Comp = NO;
+            //}
+        }
+
+        strcpy((char *)ShmOCPP16Data->StatusNotification[count].ErrorCode, "NoError");
+    }
+
+    for (uint8_t count = 0; count < pSysConfig->AcConnectorCount; count++) {
+        pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(count);
+
+        pAcChargingInfo->RemoteStartFlag = NO;
+
+        if (pAcChargingInfo->Type == _Type_AC) {
+            pAcChargingInfo->SelfTest_Comp = NO;
+            strcpy((char *)ShmOCPP16Data->StatusNotification[count + pSysConfig->TotalConnectorCount].ErrorCode, "NoError");
+        }
+    }
+
+    //log_info("Initialization OK \n");
+    return PASS;
+}
+
+bool InitialSystemDefaultConfig()
+{
+    bool result = true;
+
+    LoadSysConfigAndInfo(pSysConfig);
+    InitGPIO();
+    InitEthernet();
+    GetMacAddress();
+
+//  system("echo 1 > /sys/class/gpio/gpio110/value"); //reset PHY
+//  sleep(3);
+//  system("/sbin/ifconfig eth0 192.168.1.10 netmask 255.255.255.0 down");
+//  sleep(1);
+//  system("/sbin/ifconfig eth1 192.168.0.10 netmask 255.255.255.0 up");
+
+    return result;
+}
+
+//顯示自檢錯誤原因,觸發對應的flag
+bool DisplaySelfTestFailReason()
+{
+    bool result = false;
+    uint8_t index = 0;
+
+    // RB、FB、407、EV 小板中有些板子無回應
+    if (ShmRelayModuleData->SelfTest_Comp == NO) {
+        pAlarmCode->AlarmEvents.bits.RelayboardStestFail = true;
+    }
+
+    if (ShmFanModuleData->SelfTest_Comp == NO) {
+        pAlarmCode->AlarmEvents.bits.FanboardStestFail = true;
+    }
+
+    if (ShmPrimaryMcuData->SelfTest_Comp == NO) {
+        pAlarmCode->AlarmEvents.bits.PrimaryStestFail = true;
+    }
+
+    if (ShmLedModuleData->SelfTest_Comp == NO) {
+        pAlarmCode->AlarmEvents.bits.LedboardStestFail = true;
+    }
+
+    for (index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+        pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+        if (pDcChargingInfo->Type == _Type_Chademo) {
+            if (ShmCHAdeMOData->evse[pDcChargingInfo->type_index].SelfTest_Comp == NO) {
+                pAlarmCode->AlarmEvents.bits.ChademoboardStestFail = true;
+            }
+        } else if (pDcChargingInfo->Type == _Type_GB) {
+            if (ShmGBTData->evse[pDcChargingInfo->type_index].SelfTest_Comp == NO) {
+                pAlarmCode->AlarmEvents.bits.GbtboardStestFail = true;
+            }
+        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+            if (ShmCcsData->CommProtocol == _CCS_COMM_V2GMessage_DIN70121) {
+                if (ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].SelfTest_Comp == NO) {
+                    pAlarmCode->AlarmEvents.bits.CCSboardStestFail = true;
+                }
+            }
+        }
+    }
+
+    for (index = 0; index < pSysConfig->AcConnectorCount; index++) {
+        pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(index);
+
+        // 先借 GBT 顯示
+        if (pAcChargingInfo->SelfTest_Comp == NO) {
+            pAlarmCode->AlarmEvents.bits.AcConnectorStestFail = true;
+        }
+    }
+
+    if (pSysInfo->AcContactorStatus == NO) {
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+        // AC Contact 未搭上
+        pAlarmCode->AlarmEvents.bits.AcContactStestFail = true;
+        result = true;
+#endif //!defined DD360 && !defined DD360Audi
+    }
+    //else if (pAlarmCode->AlarmEvents.bits.PsuDipSwitchStestFail == YES) { //DS60-120 add
+    //    result = true;
+    //}
+    else if (ShmPsuData->SystemAvailablePower <= 0 &&
+             ShmPsuData->SystemAvailableCurrent <= 0) {
+        // PSU 通訊問題
+        pAlarmCode->AlarmEvents.bits.PsuModuleStestFail = true;
+        result = true;
+    }
+
+    return result;
+}
+
+#if 0
+void SelfTestRun()
+{
+    bool evInitFlag = false;
+
+    StartSystemTimeoutDet(Timeout_SelftestChk);
+    pSysInfo->SelfTestSeq = _STEST_VERSION;
+
+    while (pSysInfo->SelfTestSeq != _STEST_COMPLETE //||
+            //GetTimeoutValue(pSysInfo->SystemTimeoutTimer) / uSEC_VAL <= 20 //DS60-120 add
+          ) {
+        if (pSysInfo->SelfTestSeq == _STEST_COMPLETE) {
+            return;
+        }
+
+        ChkPrimaryStatus();
+        if (pSysWarning->Level == 2 //||
+                //pAlarmCode->AlarmEvents.bits.PsuDipSwitchStestFail == YES //DS60-120 add
+           ) {
+            pSysInfo->SelfTestSeq = _STEST_FAIL;
+            return;
+        }
+
+        if (pSysConfig->TotalConnectorCount > 0) {
+            if (ShmPsuData->Work_Step == _NO_WORKING ||
+                    pSysInfo->SelfTestSeq == _STEST_FAIL) {
+                pSysInfo->SelfTestSeq = _STEST_FAIL;
+                return;
+            }
+
+            switch (pSysInfo->SelfTestSeq) {
+            case _STEST_VERSION: {
+                if ((strlen((char *)pSysInfo->RelayModuleFwRev) != 0 ||
+                        pSysInfo->RelayModuleFwRev[0] != '\0')
+                        && (ShmRelayModuleData->SelfTest_Comp != YES)
+                   ) {
+                    log_info("Relay Board FW Rev = %s", pSysInfo->RelayModuleFwRev);
+                    ShmRelayModuleData->SelfTest_Comp = YES;
+                }
+#if !defined NO_FAN_BOARD && !defined DD360ComBox
+                if ((strlen((char *)pSysInfo->FanModuleFwRev) != 0 ||
+                        pSysInfo->FanModuleFwRev[0] != '\0')
+                        && (ShmFanModuleData->SelfTest_Comp != YES)
+                   ) {
+                    log_info("Fan Board FW Rev = %s", pSysInfo->FanModuleFwRev);
+                    ShmFanModuleData->SelfTest_Comp = YES;
+                }
+#else
+                ShmFanModuleData->SelfTest_Comp = YES;
+#endif //NO_FAN_BOARD
+
+                if ((strlen((char *)ShmPrimaryMcuData->version) != 0 ||
+                        ShmPrimaryMcuData->version[0] != '\0')
+                        && (ShmPrimaryMcuData->SelfTest_Comp != YES)
+                   ) {
+                    log_info("Primary FW Rev = %s", pSysInfo->CsuPrimFwRev);
+                    ShmPrimaryMcuData->SelfTest_Comp = YES;
+                }
+#if 0 //DS60-120 remove
+                if ((strlen((char *)pSysInfo->LedModuleFwRev) != 0 ||
+                        pSysInfo->LedModuleFwRev[0] != '\0')
+                        && (ShmLedModuleData->SelfTest_Comp != YES)
+                   ) {
+                    log_info("LED Board FW Rev = %s", pSysInfo->LedModuleFwRev);
+                    ShmLedModuleData->SelfTest_Comp = YES;
+                }
+#endif //0
+
+                // EV 小板
+                if (!evInitFlag) {
+                    evInitFlag = YES;
+                    for (uint8_t index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+                        pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+                        //log_info("index = %d, charging index = %d, type = %d\r\n",
+                        //         index,
+                        //         chargingInfo[index]->type_index,
+                        //         chargingInfo[index]->Type);
+                        if (pDcChargingInfo->Type == _Type_Chademo) {
+                            if ((strlen((char *)ShmCHAdeMOData->evse[pDcChargingInfo->type_index].version) != 0 ||
+                                    ShmCHAdeMOData->evse[pDcChargingInfo->type_index].version[0] != '\0')
+                                    //&& (ShmCHAdeMOData->evse[pDcChargingInfo->type_index].SelfTest_Comp != YES)
+                               ) {
+                                log_info("CHAdeMO[%d] FW Rev = %s", pDcChargingInfo->type_index, ShmCHAdeMOData->evse[pDcChargingInfo->type_index].version);
+                                ShmCHAdeMOData->evse[pDcChargingInfo->type_index].SelfTest_Comp = YES;
+                            } else {
+                                //log_info("chademo fw lose...... %s \n", ShmCHAdeMOData->evse[pDcChargingInfo->type_index].version);
+                                evInitFlag = NO;
+                            }
+                        } else if (pDcChargingInfo->Type == _Type_GB) {
+                            if ((strlen((char *)ShmGBTData->evse[pDcChargingInfo->type_index].version) != 0 ||
+                                    ShmGBTData->evse[pDcChargingInfo->type_index].version[0] != '\0')
+                                    //&& (ShmGBTData->evse[pDcChargingInfo->type_index].SelfTest_Comp != YES)
+                               ) {
+                                log_info("GBT[%d] FW Rev = %s", pDcChargingInfo->type_index, ShmGBTData->evse[pDcChargingInfo->type_index].version);
+                                ShmGBTData->evse[pDcChargingInfo->type_index].SelfTest_Comp = YES;
+                            } else {
+                                //log_info("GBT fw lose...... %s \n", ShmCHAdeMOData->evse[pDcChargingInfo->type_index].version);
+                                evInitFlag = NO;
+                            }
+                        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                            if (ShmCcsData->CommProtocol == _CCS_COMM_V2GMessage_DIN70121) {
+                                if ((strlen((char *)ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].version) != 0 ||
+                                        ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].version[0] != '\0')
+                                        /*&&(ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].SelfTest_Comp != YES)*/
+                                   ) {
+                                    log_info("CCS[%d] FW Rev = %s",
+                                             pDcChargingInfo->type_index,
+                                             ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].version);
+                                    ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].SelfTest_Comp = YES;
+                                } else {
+                                    //log_info("CCS[%d] ccs fw lose...... %s \n",
+                                    //         chargingInfo[index]->type_index,
+                                    //         ShmCcsData->V2GMessage_DIN70121[chargingInfo[index]->type_index].version);
+                                    evInitFlag = NO;
+                                }
+                            }
+                        }
+                    }
+
+                    for (uint8_t index = 0; index < pSysConfig->AcConnectorCount; index++) {
+                        pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(index);
+
+                        if (pAcChargingInfo->Type == _Type_AC) {
+                            if ((strlen((char *)pAcChargingInfo->version) != 0 || pAcChargingInfo->version[0] != '\0')
+                                    && (pAcChargingInfo->SelfTest_Comp != YES)
+                               ) {
+                                log_info("AC connector[%d] FW Rev = %s", index, pAcChargingInfo->version);
+                                pAcChargingInfo->SelfTest_Comp = YES;
+                            } else {
+                                evInitFlag = NO;
+                            }
+                        }
+                    }
+                }
+
+                if ( ShmFanModuleData->SelfTest_Comp &&
+                        ShmRelayModuleData->SelfTest_Comp &&
+                        ShmPrimaryMcuData->SelfTest_Comp &&
+                        //ShmLedModuleData->SelfTest_Comp &&
+                        evInitFlag
+                   ) {
+                    pSysInfo->SelfTestSeq = _STEST_AC_CONTACTOR;
+                }
+            }
+            break;
+            case _STEST_AC_CONTACTOR: {
+                //ShmPsuData->Work_Step = _TEST_COMPLETE;
+                // 因為 30KW 以下沒有 Relay feedback 功能,所以暫時先直接跳過
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                if (pSysInfo->AcContactorStatus == YES) {
+                    pSysInfo->SelfTestSeq = _STEST_PSU_DETECT;
+                    log_info("AC contactor self test OK");
+                }
+#else
+                pSysInfo->SelfTestSeq = _STEST_PSU_DETECT;
+                log_info("Waiting for DO communication");
+#endif //!defined DD360 && !defined DD360Audi
+            }
+            break;
+            case _STEST_PSU_DETECT: {
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                if (ShmPsuData->Work_Step >= GET_SYS_CAP) {
+                    pSysInfo->SelfTestSeq = _STEST_PSU_CAP;
+                }
+#else
+                pSysInfo->SelfTestSeq = _STEST_PSU_CAP;
+#endif //defined DD360 && !defined DD360Audi
+            }
+            break;
+            case _STEST_PSU_CAP: {
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                // 此測試是要確認當前總輸出能力
+                // 如果沒有 PSU 模組請 bypass
+                if (ShmPsuData->Work_Step == BOOTING_COMPLETE) {
+                    sleep(1);
+                    pSysInfo->SelfTestSeq = _STEST_COMPLETE;
+                    pSysInfo->BootingStatus = BOOT_COMPLETE;
+                }
+#else
+                //check the power limit from DO
+                pSysInfo->SelfTestSeq = _STEST_COMPLETE;
+                pSysInfo->BootingStatus = BOOT_COMPLETE;
+                log_info("Successful Self Test");
+#endif //defined DD360 && !defined DD360Audi
+            }
+            break;
+            }
+        } else {
+            break;
+        }
+
+        usleep(100000);
+    }
+}
+#endif //0
+
+int SpawnTask()
+{
+    sleep(2);
+    system("/root/Module_EventLogging &");
+    system("/root/Module_PrimaryComm &");
+    system("/root/Module_EvComm &");
+    system("/root/Module_LcmControl &");
+    system("/root/Module_InternalComm &");
+    system("/root/Module_ProduceUtils &");
+
+#if defined DD360 ||defined DD360Audi || defined DD360ComBox
+    system("/root/Module_DoComm &");
+#else
+    system("/root/Module_PsuComm &");
+
+    if (strcmp((char *)pSysConfig->OcppServerURL, "") != EQUAL &&
+            strcmp((char *)pSysConfig->ChargeBoxId, "") != EQUAL) {
+        system("/root/OcppBackend &");
+    }
+
+    if (pSysConfig->ModelName[10] == 'T') {
+        system("/root/Module_4g &");
+    }
+
+    if (pSysConfig->ModelName[10] == 'W') {
+        system("/root/Module_Wifi &");
+    }
+
+    if (pSysConfig->ModelName[10] == 'D') {
+        system("/root/Module_4g &");
+        system("/root/Module_Wifi &");
+    }
+#endif //defined DD360 || defined DD360Audi
+
+    return PASS;
+}
+
+int StoreUsrConfigData(struct SysConfigData *UsrData)
+{
+    int result = PASS;
+    int fd, wrd;
+    unsigned int i, Chk;
+    uint8_t *ptr, *BufTmp;
+
+    Chk = 0;
+    ptr = (uint8_t *)UsrData;
+    if ((BufTmp = malloc(MtdBlockSize)) != NULL) {
+        memset(BufTmp, 0, MtdBlockSize);
+        memcpy(BufTmp, ptr, sizeof(struct SysConfigData));
+        for (i = 0; i < MtdBlockSize - 4; i++) {
+            Chk += *(ptr + i);
+        }
+
+        memcpy(BufTmp + MtdBlockSize - 4, &Chk, 4);
+        fd = open("/dev/mtdblock10", O_RDWR);
+        if (fd > 0) {
+            wrd = write(fd, BufTmp, MtdBlockSize);
+            close(fd);
+            if (wrd >= MtdBlockSize) {
+                fd = open("/dev/mtdblock11", O_RDWR);
+                if (fd > 0) {
+                    wrd = write(fd, BufTmp, MtdBlockSize);
+                    close(fd);
+                    if (wrd < MtdBlockSize) {
+                        log_error("write /dev/mtdblock11(backup) NG\r\n");
+                        result = FAIL;
+                    }
+                } else {
+                    log_error("open /dev/mtdblock11(backup) NG\r\n");
+                    result = FAIL;
+                }
+            } else {
+                log_error("write /dev/mtdblock10 NG\r\n");
+                result = FAIL;
+            }
+
+        } else {
+            log_error("open /dev/mtdblock10 NG\r\n");
+            result = FAIL;
+        }
+    } else {
+        log_error("alloc BlockSize NG\r\n");
+        result = FAIL;
+    }
+
+    if (BufTmp != NULL) {
+        free(BufTmp);
+    }
+
+    return result;
+}
+
+//===============================================
+// Common Detect Chk - Stop Charging ?
+//===============================================
+int isEvBoardStopChargeFlag(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    //printf("StopChargeFlag = %d\r\n", chargingInfo[gunIndex]->StopChargeFlag);
+    return pDcChargingInfo->StopChargeFlag;
+}
+
+bool isEvBoardNormalStopChargeFlag(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    return pDcChargingInfo->NormalStopChargeFlag;
+}
+
+//===============================================
+// 掃描插槍狀況
+//===============================================
+void ClearDetectPluginFlag()
+{
+    pSysInfo->WaitForPlugit = NO;
+
+    //DS60-120 add
+    for (uint8_t gun_index = 0; gun_index < pSysConfig->TotalConnectorCount; gun_index++) {
+        pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun_index);
+
+        if (pDcChargingInfo->RemoteStartFlag == YES) {
+            pDcChargingInfo->RemoteStartFlag = NO;
+        }
+    }
+
+    if (pSysInfo->OrderCharging != NO_DEFINE) {
+        pSysInfo->OrderCharging = NO_DEFINE;
+    }
+}
+
+void DetectPluginStart()
+{
+    pSysInfo->WaitForPlugit = YES;
+}
+
+bool isDetectPlugin()
+{
+    if (pSysInfo->WaitForPlugit == YES) {
+        return YES;
+    }
+
+    return NO;
+}
+
+//===============================================
+// Common Detect Chk - Chademo
+//===============================================
+bool isEvGunLocked_chademo(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    return (DetectBitValue(pDcChargingInfo->GunLocked , 0) == 0) ? NO : YES;
+}
+
+bool isEvContactorWelding_chademo(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    return DetectBitValue(ShmCHAdeMOData->ev[pDcChargingInfo->type_index].EvDetection, 3);
+}
+
+bool isEvStopReq_chademo(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    return DetectBitValue(ShmCHAdeMOData->ev[pDcChargingInfo->type_index].EvDetection, 4);
+}
+
+bool isEvStopCharging_chademo(uint8_t gunIndex)
+{
+    if (isEvGunLocked_chademo(gunIndex) == NO) {
+        // 無鎖槍 = 停止
+        log_info("gun locked none (%d) \n", gunIndex);
+        return YES;
+    }
+
+    return NO;
+}
+
+uint8_t isPrechargeStatus_chademo(uint8_t gunIndex)
+{
+    uint8_t result = 0x00;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    result = ShmCHAdeMOData->ev[pDcChargingInfo->type_index].PresentMsgFlowStatus;
+
+    return result;
+}
+//===============================================
+// Common Detect Chk - GB
+//===============================================
+bool isEvGunLocked_gb(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    return (DetectBitValue(pDcChargingInfo->GunLocked , 0) == 0) ? NO : YES;
+}
+
+bool isEvStopCharging_gb(uint8_t gunIndex)
+{
+    if (isEvGunLocked_gb(gunIndex) == NO) {
+        // 無鎖槍 = 停止
+        log_info("gun locked none. \n");
+        return YES;
+    }
+
+    return NO;
+}
+
+uint8_t isPrechargeStatus_gb(uint8_t gunIndex)
+{
+    uint8_t result = 0x00;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    result = ShmGBTData->ev[pDcChargingInfo->type_index].PresentMsgFlowStatus;
+
+    return result;
+}
+
+//===============================================
+// Common Detect Chk - CCS
+//===============================================
+bool isEvGunLocked_ccs(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    return (DetectBitValue(pDcChargingInfo->GunLocked , 0) == 0) ? NO : YES;
+}
+
+uint8_t isPrechargeStatus_ccs(uint8_t gunIndex)
+{
+    uint8_t result = 0x00;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (ShmCcsData->CommProtocol == _CCS_COMM_V2GMessage_DIN70121) {
+        result = ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].PresentMsgFlowStatus;
+    }
+
+    return result;
+}
+
+bool isEvStopCharging_ccs(uint8_t gunIndex)
+{
+    if (isEvGunLocked_ccs(gunIndex) == NO) {
+        // 無鎖槍 = 停止
+        log_info("gun locked none. \n");
+        return YES;
+    }
+
+    return NO;
+}
+
+//===============================================
+// Callback
+//===============================================
+void DisplayChargingInfo()
+{
+    log_info("*********** DisplayChargingInfo *********** \n");
+    for (uint8_t i = 0; i < pSysConfig->TotalConnectorCount; i++) {
+        pAcChargingInfo =  (struct ChargingInfoData *)GetAcChargingInfoData(i);
+
+        if (pAcChargingInfo->SystemStatus != S_IDLE &&
+                pAcChargingInfo->SystemStatus != S_RESERVATION) {
+            ChangeGunSelectByIndex(i);
+            return;
+        }
+    }
+
+    pAcChargingInfo =  (struct ChargingInfoData *)GetAcChargingInfoData(0);
+
+    if (pSysConfig->AcConnectorCount > 0 &&
+            pSysInfo->CurGunSelectedByAc == NO_DEFINE &&
+            pAcChargingInfo->SystemStatus >= S_PREPARNING &&
+            pAcChargingInfo->SystemStatus <= S_COMPLETE) {
+        pSysInfo->CurGunSelectedByAc = DEFAULT_AC_INDEX;
+    }
+
+    usleep(50000);
+#if defined DD360Audi
+    pSysInfo->SystemPage = _LCM_SELECT_GUN;
+#else
+    pSysInfo->SystemPage = _LCM_NONE;
+#endif //defined DD360Audi
+}
+
+void _AutoReturnTimeout()
+{
+    log_info("*********** _AutoReturnTimeout %d*********** \n", pSysInfo->PageIndex);
+    if (pSysInfo->PageIndex == _LCM_WAIT_FOR_PLUG) {
+        ClearDetectPluginFlag();
+    } else if (pSysInfo->PageIndex == _LCM_AUTHORIZ_COMP) {
+        DetectPluginStart();
+    }
+    usleep(50000);
+#if defined DD360Audi
+    pSysInfo->SystemPage = _LCM_SELECT_GUN;
+#else
+    pSysInfo->SystemPage = _LCM_NONE;
+#endif //defined DD360Audi
+}
+
+void _SelfTestTimeout()
+{
+    if (pSysInfo->BootingStatus != BOOT_COMPLETE) {
+        for (uint8_t gun_index = 0; gun_index < pSysConfig->TotalConnectorCount; gun_index++) {
+            setChargerMode(gun_index, MODE_ALARM);
+        }
+    }
+    ShmPsuData->Work_Step = _NO_WORKING;
+    pSysInfo->SelfTestSeq = _STEST_FAIL;
+    log_info("Self test timeout. \n");
+}
+
+void _AuthorizedTimeout()
+{
+    if (IsAuthorizingMode()) {
+        log_info("*********** _AuthorizedTimeout *********** \n");
+        //isCardScan = false;
+        SetIsCardScan(false);
+
+        //gAudiCustInfo->PricesInfo[pSysInfo->CurGunSelected].Balance = 0.0; //Jerry add
+        pSysInfo->SystemPage = _LCM_AUTHORIZ_FAIL;
+        //ChangeLcmByIndex(_LCM_AUTHORIZ_FAIL);
+        strcpy((char *)pSysConfig->UserId, "");
+        ClearAuthorizedFlag();
+    }
+}
+
+void _DetectPlugInTimeout()
+{
+    log_info("*********** _DetectPlugInTimeout *********** \n");
+    strcpy((char *)pSysConfig->UserId, "");
+    ClearDetectPluginFlag();
+    //usleep(50000);
+    sleep(1); //Jerry add
+#if defined DD360Audi
+    pSysInfo->SystemPage = _LCM_SELECT_GUN;
+#else
+    pSysInfo->SystemPage = _LCM_NONE;
+#endif //defined DD360Audi
+}
+
+void _DetectEvChargingEnableTimeout(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (pDcChargingInfo->Type == _Type_Chademo) {
+        if (!isEvGunLocked_chademo(gunIndex)) {
+            log_info("*********** _DetectEvChargingEnableTimeout (chademo) ***********\n");
+        }
+    } else if (pDcChargingInfo->Type == _Type_GB) {
+        if (!isEvGunLocked_ccs(gunIndex)) {
+            log_info("*********** _DetectEvChargingEnableTimeout (gb) ***********\n");
+        }
+    } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+        if (!isEvGunLocked_ccs(gunIndex)) {
+            log_info("*********** _DetectEvChargingEnableTimeout (ccs) ***********\n");
+        }
+    }
+    ChargingTerminalProcess(gunIndex);
+    _AutoReturnTimeout();
+}
+
+void _DetectEvseChargingEnableTimeout(uint8_t gunIndex)
+{
+    log_info("*********** _DetectEvseChargingEnableTimeout (GFD timeout) ***********\n");
+    //if (chargingInfo[gunIndex]->GroundFaultStatus != GFD_PASS)
+    {
+        setChargerMode(gunIndex, MODE_IDLE);
+        _AutoReturnTimeout();
+    }
+}
+
+void _PrepareTimeout(uint8_t gunIndex)
+{
+    log_info("*********** _PrepareTimeout ***********\n");
+    setChargerMode(gunIndex, MODE_IDLE);
+    pAlarmCode->AlarmEvents.bits.PsuNoResource = YES;
+    _AutoReturnTimeout();
+}
+
+void _CcsPrechargeTimeout(uint8_t gunIndex)
+{
+    log_info("*********** _CcsPrechargeTimeout ***********\n");
+    setChargerMode(gunIndex, MODE_IDLE);
+}
+
+//===============================================
+// 取得卡號與卡號驗證
+//===============================================
+#if 0
+bool canStartCharging()
+{
+    char buf2[16] = "";
+    memset(buf2, 0, ARRAY_SIZE(buf2));
+
+    for (uint8_t index = 0; index < strlen((char *)ShmOCPP16Data->Authorize.ResponseIdTagInfo.Status); index++) {
+        sprintf(buf2 + (index - 1) * 2, "%02X", ShmOCPP16Data->Authorize.ResponseIdTagInfo.Status[index]);
+    }
+    sprintf(buf2, "%s", ShmOCPP16Data->Authorize.ResponseIdTagInfo.Status);
+
+    // 因為無法得知實際的長度,所以只能用搜尋的方式
+    if (strcmp(buf2, "Accepted") == EQUAL) {
+        return true;
+    } else {
+
+    }
+
+    return false;
+}
+#endif //0
+
+void AuthorizingStart()
+{
+    ShmOCPP16Data->SpMsg.bits.AuthorizeReq = YES;
+    pSysInfo->AuthorizeFlag = YES;
+}
+
+void ClearAuthorizedFlag()
+{
+    ShmOCPP16Data->SpMsg.bits.AuthorizeConf = NO;
+    pSysInfo->AuthorizeFlag = NO;
+}
+
+bool isAuthorizedComplete()
+{
+    if (pSysInfo->AuthorizeFlag == YES) {
+        return false;
+    }
+    return true;
+}
+
+bool IsAuthorizingMode()
+{
+    if (pSysInfo->AuthorizeFlag == NO) {
+        return false;
+    }
+
+    return true;
+}
+
+//===============================================
+// 紀錄 Alarm Code
+//===============================================
+void ResetChargerAlarmCode(uint8_t gunIndex, char *code)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (strcmp(code, "012229") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaConnectOTP = NO; }
+    else if (strcmp(code, "012230") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSConnectOTP = NO; }
+    else if (strcmp(code, "012231") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTConnectOTP = NO; }
+    else if (strcmp(code, "011011") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaRelayWeldingFault = NO; }
+    else if (strcmp(code, "011013") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSRelayWeldingFault = NO; }
+    else if (strcmp(code, "011015") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTRelayWeldingFault = NO; }
+    else if (strcmp(code, "011012") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaRelayDrivingFault = NO; }
+    else if (strcmp(code, "011014") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSRelayDrivingFault = NO; }
+    else if (strcmp(code, "011016") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTRelayDrivingFault = NO; }
+    else if (strcmp(code, "011018") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaConnectTempSensorFail = NO; }
+    else if (strcmp(code, "011019") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSConnectTempSensorFail = NO; }
+    else if (strcmp(code, "011020") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTConnectTempSensorFail = NO; }
+
+    if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "", 6) != EQUAL) {
+        if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012229", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012230", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012231", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "011011", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "011013", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "011015", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "011012", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "011014", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "011016", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "011018", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "011019", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "011020", 6) == EQUAL) {
+            strncpy((char *)pDcChargingInfo->ConnectorAlarmCode, "", 6);
+        }
+    }
+}
+
+void RecordAlarmCode(uint8_t gunIndex, char *code)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "", 6) == EQUAL) {
+        memcpy(pDcChargingInfo->ConnectorAlarmCode, code, 6);
+    }
+
+    //if (strcmp(code, "012234") == EQUAL) { pAlarmCode->AlarmEvents.bits.ChademoGfdTrip = YES; }
+    //if (strcmp(code, "012235") == EQUAL) { pAlarmCode->AlarmEvents.bits.CcsGfdTrip = YES; }
+    //if (strcmp(code, "012236") == EQUAL) { pAlarmCode->AlarmEvents.bits.GbGfdTrip = YES; }
+    //if (strcmp(code, "012288") == EQUAL) { pAlarmCode->AlarmEvents.bits.CcsOutputUVPFail = YES; }
+    //if (strcmp(code, "012289") == EQUAL) { pAlarmCode->AlarmEvents.bits.ChademoOutputUVPFail = YES; }
+    //if (strcmp(code, "012290") == EQUAL) { pAlarmCode->AlarmEvents.bits.GbtOutputUVPFail = YES; }
+
+    if (strcmp(code, "012234") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaGfdTrip = YES; }
+    else if (strcmp(code, "012235") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSGfdTrip = YES; }
+    else if (strcmp(code, "012236") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTGfdTrip = YES; }
+    else if (strcmp(code, "012288") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSUvpFail = YES; }
+    else if (strcmp(code, "012289") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaUvpFail = YES; }
+    else if (strcmp(code, "012290") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTUvpFail = YES; }
+
+    else if (strcmp(code, "012229") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaConnectOTP = YES; }
+    else if (strcmp(code, "012230") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSConnectOTP = YES; }
+    else if (strcmp(code, "012231") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTConnectOTP = YES; }
+    else if (strcmp(code, "012296") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaGfdWarning = YES; }
+    else if (strcmp(code, "012297") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSGfdWarning = YES; }
+    else if (strcmp(code, "012298") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTGfdWarning = YES; }
+    else if (strcmp(code, "011011") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaRelayWeldingFault = YES; }
+    else if (strcmp(code, "011013") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSRelayWeldingFault = YES; }
+    else if (strcmp(code, "011015") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTRelayWeldingFault = YES; }
+    else if (strcmp(code, "011012") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaRelayDrivingFault = YES; }
+    else if (strcmp(code, "011014") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSRelayDrivingFault = YES; }
+    else if (strcmp(code, "011016") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTRelayDrivingFault = YES; }
+    else if (strcmp(code, "011018") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaConnectTempSensorFail = YES; }
+    else if (strcmp(code, "011019") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSConnectTempSensorFail = YES; }
+    else if (strcmp(code, "011020") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTConnectTempSensorFail = YES; }
+}
+
+void RecordWarningCode(uint8_t gunIndex, char *code)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    memcpy(pDcChargingInfo->ConnectorWarningCode, code, 6);
+
+    if (strcmp(code, "012296") == EQUAL) { pAlarmCode->AlarmEvents.bits.ChademoGroundWarning = YES; }
+    if (strcmp(code, "012297") == EQUAL) { pAlarmCode->AlarmEvents.bits.CcsGroundfaultWarning = YES; }
+    if (strcmp(code, "012298") == EQUAL) { pAlarmCode->AlarmEvents.bits.GbGroundfaultWarning = YES; }
+}
+
+void ReleaseAlarmCode(uint8_t gunIndex)
+{
+#if 0
+    bool isCleanCheck = false;
+    char code[7];
+
+    if (chargingInfo[gunIndex]->Type == _Type_Chademo) {
+        if (strncmp((char *)chargingInfo[gunIndex]->ConnectorAlarmCode, "012234", 6) == EQUAL &&
+                pAlarmCode->AlarmEvents.bits.ChademoGfdTrip == YES) {
+            memcpy(code, "012234", 6);
+            memcpy(chargingInfo[gunIndex]->ConnectorAlarmCode, "", 6);
+            isCleanCheck = true;
+        } else if (strncmp((char *)chargingInfo[gunIndex]->ConnectorAlarmCode, "012289", 6) == EQUAL &&
+                   pAlarmCode->AlarmEvents.bits.ChademoOutputUVPFail == YES) {
+            memcpy(code, "012289", 6);
+            memcpy(chargingInfo[gunIndex]->ConnectorAlarmCode, "", 6);
+            isCleanCheck = true;
+        } else if (pAlarmCode->AlarmEvents.bits.ChademoGroundWarning == YES) {
+            ReleaseWarningCodeByString(gunIndex, "012296");
+        } else if (pAlarmCode->AlarmEvents.bits.SystemChademoOutputOVP == YES) {
+            memcpy(code, "012217", 6);
+            memcpy(chargingInfo[gunIndex]->ConnectorAlarmCode, "", 6);
+            isCleanCheck = true;
+        }
+    } else if (chargingInfo[gunIndex]->Type == _Type_GB) {
+        if (strncmp((char *)chargingInfo[gunIndex]->ConnectorAlarmCode, "012236", 6) == EQUAL &&
+                pAlarmCode->AlarmEvents.bits.GbGfdTrip == YES) {
+            memcpy(code, "012236", 6);
+            memcpy(chargingInfo[gunIndex]->ConnectorAlarmCode, "", 6);
+            isCleanCheck = true;
+        } else if (strncmp((char *)chargingInfo[gunIndex]->ConnectorAlarmCode, "012290", 6) == EQUAL &&
+                   pAlarmCode->AlarmEvents.bits.GbtOutputUVPFail == YES) {
+            memcpy(code, "012290", 6);
+            memcpy(chargingInfo[gunIndex]->ConnectorAlarmCode, "", 6);
+            isCleanCheck = true;
+        } else if (pAlarmCode->AlarmEvents.bits.GbGroundfaultWarning == YES) {
+            ReleaseWarningCodeByString(gunIndex, "012298");
+        } else if (pAlarmCode->AlarmEvents.bits.SystemGbOutputOVP == YES) {
+            memcpy(code, "012221", 6);
+            memcpy(chargingInfo[gunIndex]->ConnectorAlarmCode, "", 6);
+            isCleanCheck = true;
+        }
+    } else if (chargingInfo[gunIndex]->Type == _Type_CCS_2) {
+        if (strncmp((char *)chargingInfo[gunIndex]->ConnectorAlarmCode, "012235", 6) == EQUAL &&
+                pAlarmCode->AlarmEvents.bits.CcsGfdTrip == YES) {
+            memcpy(code, "012235", 6);
+            memcpy(chargingInfo[gunIndex]->ConnectorAlarmCode, "", 6);
+            isCleanCheck = true;
+        } else if (strncmp((char *)chargingInfo[gunIndex]->ConnectorAlarmCode, "012288", 6) == EQUAL &&
+                   pAlarmCode->AlarmEvents.bits.CcsOutputUVPFail == YES) {
+            memcpy(code, "012288", 6);
+            memcpy(chargingInfo[gunIndex]->ConnectorAlarmCode, "", 6);
+            isCleanCheck = true;
+        } else if (pAlarmCode->AlarmEvents.bits.CcsGroundfaultWarning == YES) {
+            ReleaseWarningCodeByString(gunIndex, "012297");
+        } else if (pAlarmCode->AlarmEvents.bits.SystemCcsOutputOVP == YES) {
+            memcpy(code, "012219", 6);
+            memcpy(chargingInfo[gunIndex]->ConnectorAlarmCode, "", 6);
+            isCleanCheck = true;
+        }
+    }
+
+    if (isCleanCheck) {
+        for (uint8_t index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+            if (index != gunIndex || pSysConfig->TotalConnectorCount == 1) {
+                if (strncmp((char *)chargingInfo[index]->ConnectorAlarmCode, code, 6) != EQUAL) {
+                    if (strncmp(code, "012234", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.ChademoGfdTrip = NO; }
+                    if (strncmp(code, "012289", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.ChademoOutputUVPFail = NO; }
+                    if (strncmp(code, "012217", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.SystemChademoOutputOVP = NO; }
+
+                    if (strncmp(code, "012236", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.GbGfdTrip = NO; }
+                    if (strncmp(code, "012290", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.GbtOutputUVPFail = NO; }
+                    if (strncmp(code, "012221", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.SystemGbOutputOVP = NO; }
+
+                    if (strncmp(code, "012235", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.CcsGfdTrip = NO; }
+                    if (strncmp(code, "012288", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.CcsOutputUVPFail = NO; }
+                    if (strncmp(code, "012219", 6) == EQUAL) {pAlarmCode->AlarmEvents.bits.SystemCcsOutputOVP = NO;}
+                }
+            }
+        }
+    }
+#endif //0
+
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    // 回 idle 後主要清除  GFD Trip、UVP、OVP、GFD Warning
+    if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "", 6) != EQUAL) {
+        if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012251", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012252", 6) == EQUAL) {
+            memcpy(pDcChargingInfo->ConnectorAlarmCode, "", 6);
+        }
+    }
+
+    if (pDcChargingInfo->Type == _Type_Chademo) {
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaGfdTrip = NO;
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaUvpFail = NO;
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaConnectOVP = NO;
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaGfdWarning = NO;
+
+        if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "", 6) != EQUAL) {
+            if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012234", 6) == EQUAL ||
+                    strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012289", 6) == EQUAL ||
+                    strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012217", 6) == EQUAL ||
+                    strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012296", 6) == EQUAL) {
+                memcpy(pDcChargingInfo->ConnectorAlarmCode, "", 6);
+            }
+        }
+    } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSGfdTrip = NO;
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSUvpFail = NO;
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSConnectOVP = NO;
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSGfdWarning = NO;
+
+        if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "", 6) != EQUAL) {
+            if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012235", 6) == EQUAL ||
+                    strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012288", 6) == EQUAL ||
+                    strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012219", 6) == EQUAL ||
+                    strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012297", 6) == EQUAL) {
+                memcpy(pDcChargingInfo->ConnectorAlarmCode, "", 6);
+            }
+        }
+    } else if (pDcChargingInfo->Type == _Type_GB) {
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTGfdTrip = NO;
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTUvpFail = NO;
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTConnectOVP = NO;
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTGfdWarning = NO;
+
+        if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "", 6) != EQUAL) {
+            if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012236", 6) == EQUAL ||
+                    strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012290", 6) == EQUAL ||
+                    strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012221", 6) == EQUAL ||
+                    strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012298", 6) == EQUAL) {
+                memcpy(pDcChargingInfo->ConnectorAlarmCode, "", 6);
+            }
+        }
+    }
+
+    if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012251", 6) == EQUAL ||
+            strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012252", 6) == EQUAL ||
+            strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012238", 6) == EQUAL ||
+            strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012304", 6) == EQUAL
+       ) {
+        memset(pDcChargingInfo->ConnectorAlarmCode, 0, sizeof(pDcChargingInfo->ConnectorAlarmCode));
+    }
+}
+
+void ReleaseWarningCodeByString(uint8_t gunIndex, char *code)
+{
+    bool isCleanCheck = false;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (strncmp((char *)pDcChargingInfo->ConnectorWarningCode, code, 6) == EQUAL &&
+            pAlarmCode->AlarmEvents.bits.ChademoGroundWarning == YES) {
+        memcpy(pDcChargingInfo->ConnectorWarningCode, "", 6);
+        isCleanCheck = true;
+    } else if (strncmp((char *)pDcChargingInfo->ConnectorWarningCode, code, 6) == EQUAL &&
+               pAlarmCode->AlarmEvents.bits.CcsGroundfaultWarning == YES) {
+        memcpy(pDcChargingInfo->ConnectorWarningCode, "", 6);
+        isCleanCheck = true;
+    } else if (strncmp((char *)pDcChargingInfo->ConnectorWarningCode, code, 6) == EQUAL &&
+               pAlarmCode->AlarmEvents.bits.GbGroundfaultWarning == YES) {
+        memcpy(pDcChargingInfo->ConnectorWarningCode, "", 6);
+        isCleanCheck = true;
+    }
+
+    if (isCleanCheck) {
+        for (uint8_t index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+            if (index != gunIndex || pSysConfig->TotalConnectorCount == 1) {
+                if (strncmp((char *)pDcChargingInfo->ConnectorWarningCode, code, 6) != EQUAL) {
+                    if (strncmp(code, "012296", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.ChademoGroundWarning = NO; }
+                    if (strncmp(code, "012297", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.CcsGroundfaultWarning = NO; }
+                    if (strncmp(code, "012298", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.GbGroundfaultWarning = NO; }
+                }
+            }
+        }
+    }
+}
+//===============================================
+// EmergencyStop and Charging Stop
+//===============================================
+void ChargingTerminalProcess(uint8_t gunIndex)
+{
+    setChargerMode(gunIndex, MODE_TERMINATING);
+}
+
+void ChargingAlarmProcess(uint8_t gunIndex)
+{
+    setChargerMode(gunIndex, MODE_ALARM);
+}
+
+void AcChargingTerminalProcess(void)
+{
+    pAcChargingInfo =  (struct ChargingInfoData *)GetAcChargingInfoData(0);
+
+    pAcChargingInfo->SystemStatus = MODE_TERMINATING;
+}
+
+void StopChargingProcessByString(uint8_t level)
+{
+    if (level > pSysWarning->Level) {
+        pSysWarning->Level = level;
+    }
+}
+
+void ReleaseChargingProcessByString(uint8_t level)
+{
+    if (level >= pSysWarning->Level) {
+        pSysWarning->Level = 0;
+    }
+}
+
+// 一般錯誤停止充電處理函式
+void BoardErrOccurByString(uint8_t index, char *code)
+{
+    uint8_t level = 1;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+    if ((pDcChargingInfo->SystemStatus > S_IDLE && pDcChargingInfo->SystemStatus < S_TERMINATING) ||
+            (pDcChargingInfo->SystemStatus >= S_CCS_PRECHARGE_ST0 && pDcChargingInfo->SystemStatus <= S_CCS_PRECHARGE_ST1)) {
+        if (strncmp(code, "023730", 6) == EQUAL && pInfoCode->InfoEvents.bits.ChademoChargerGetEmergencyStop == NO) {
+            pInfoCode->InfoEvents.bits.ChademoChargerGetEmergencyStop = YES;
+        }
+        ChargingTerminalProcess(index);
+    }
+
+    StopChargingProcessByString(level);
+}
+
+void ReleaseBoardErrOccurByString(uint8_t index, char *code)
+{
+    bool isTrigger = false;
+    uint8_t level = 1;
+
+    if (strncmp(code, "023730", 6) == 0 && pInfoCode->InfoEvents.bits.ChademoChargerGetEmergencyStop == YES) {
+        isTrigger = true;
+        pInfoCode->InfoEvents.bits.ChademoChargerGetEmergencyStop = NO;
+    }
+
+    if (isTrigger) {
+        ReleaseChargingProcessByString(level);
+    }
+}
+
+// 急停狀況的停止充電處理函式
+void EmcOccureByString(char *code)
+{
+    uint8_t level = 2;
+    // 嚴重的急停有以下幾種 : EMC 按鈕、Mainbreak、Dooropen
+    // 其錯誤等級為 2
+
+#if defined DD360 ||defined DD360Audi || defined DD360ComBox
+    //DS60-120 remove
+    if (strncmp(code, "012251", 6) == EQUAL ||
+            strncmp(code, "012252", 6) == EQUAL ||
+            strncmp(code, "012238", 6) == EQUAL ||
+            strncmp(code, "042251", 6) == EQUAL ||
+            strncmp(code, "042252", 6) == EQUAL ||
+            strncmp(code, "012304", 6) == EQUAL ||
+            strncmp(code, "042200", 6) == EQUAL ||
+            strncmp(code, "042201", 6) == EQUAL ||
+            strncmp(code, "042202", 6) == EQUAL ||
+            strncmp(code, "042267", 6) == EQUAL)
+#endif //defined DD360 || defined DD360Audi
+    {
+        for (uint8_t gun = 0; gun < pSysConfig->TotalConnectorCount; gun++) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun);
+
+            //strncpy((char *)ShmOCPP16Data->StatusNotification[gun].VendorErrorCode, code, 6);
+
+            if ((pDcChargingInfo->SystemStatus > S_IDLE &&
+                    pDcChargingInfo->SystemStatus < S_TERMINATING) ||
+                    (pDcChargingInfo->SystemStatus >= S_CCS_PRECHARGE_ST0 &&
+                     pDcChargingInfo->SystemStatus <= S_CCS_PRECHARGE_ST1)) {
+                //ChargingTerminalProcess(gun);
+                ChargingAlarmProcess(gun);
+            }
+        }
+#if defined DD360 ||defined DD360Audi || defined DD360ComBox
+        StopChargingProcessByString(level);
+        InformOcppErrOccur(4);
+#endif //defined DD360 || defined DD360Audi
+    }
+}
+
+void ReleaseEmsOccureByString(uint8_t index, char *code)
+{
+    bool isTrigger = false;
+    uint8_t level = 2;
+
+    if (strncmp(code, "042251", 6) == 0 ) {
+        isTrigger = true;
+    } else if (strncmp(code, "012251", 6) == 0 &&
+               pAlarmCode->AlarmEvents.bits.EmergencyStopTrip == YES) {
+        isTrigger = true;
+        pAlarmCode->AlarmEvents.bits.EmergencyStopTrip = NO;
+    } else if (strncmp(code, "012252", 6) == 0 &&
+               pAlarmCode->AlarmEvents.bits.DoorOpen == YES) {
+        isTrigger = true;
+        pAlarmCode->AlarmEvents.bits.DoorOpen = NO;
+    } else if (strncmp(code, "012237", 6) == 0 &&
+               pAlarmCode->AlarmEvents.bits.SpdTrip == YES) {
+        isTrigger = true;
+        pAlarmCode->AlarmEvents.bits.SpdTrip = NO;
+    } else if (strncmp(code, "012238", 6) == 0 &&
+               pAlarmCode->AlarmEvents.bits.MainPowerBreakerTrip == YES) {
+        isTrigger = true;
+        pAlarmCode->AlarmEvents.bits.MainPowerBreakerTrip = NO;
+    }
+
+    if (isTrigger) {
+        ReleaseChargingProcessByString(level);
+        InformOcppErrOccur(6);
+    }
+}
+
+#if 0
+//===============================================
+// 確認硬體 (按鈕) 狀態
+//===============================================
+bool leftBtnPush = false;
+bool rightBtnPush = false;
+
+void ChkPrimaryStatus()
+{
+    uint8_t Rtn;
+
+    if (pSysWarning->WarningCount > 0) {
+        Rtn = 0;
+        for (uint8_t i = 0; i < pSysWarning->WarningCount; i++) {
+            if (memcmp(&pSysWarning->WarningCode[i][0], "042251", 6) == 0) {
+                EmcOccureByString("042251");
+                Rtn = 1;
+            } else if (memcmp(&pSysWarning->WarningCode[i][0], "042252", 6) == 0) {
+                EmcOccureByString("042252");
+                Rtn = 1;
+            } else if (memcmp(&pSysWarning->WarningCode[i][0], "042200", 6) == 0) {
+                EmcOccureByString("042200");
+                Rtn = 1;
+            } else if (memcmp(&pSysWarning->WarningCode[i][0], "042201", 6) == 0) {
+                EmcOccureByString("042201");
+                Rtn = 1;
+            } else if (memcmp(&pSysWarning->WarningCode[i][0], "042202", 6) == 0) {
+                EmcOccureByString("042202");
+                Rtn = 1;
+            } else if (memcmp(&pSysWarning->WarningCode[i][0], "012304", 6) == 0) {
+                EmcOccureByString("012304");
+                Rtn = 1;
+            }
+        }
+        if (Rtn == 0) {
+            ReleaseEmsOccureByString(0, "042251");
+            ReleaseEmsOccureByString(0, "042252");
+            ReleaseEmsOccureByString(0, "042200");
+            ReleaseEmsOccureByString(0, "042201");
+            ReleaseEmsOccureByString(0, "042202");
+            ReleaseEmsOccureByString(0, "012304");
+        }
+    } else {
+        ReleaseEmsOccureByString(0, "042251");
+        ReleaseEmsOccureByString(0, "042252");
+        ReleaseEmsOccureByString(0, "042200");
+        ReleaseEmsOccureByString(0, "042201");
+        ReleaseEmsOccureByString(0, "042202");
+        ReleaseEmsOccureByString(0, "012304");
+    }
+
+    if (ShmPrimaryMcuData->InputDet.bits.EmergencyButton == ABNORMAL) {
+        pAlarmCode->AlarmEvents.bits.EmergencyStopTrip = YES;
+        EmcOccureByString("012251");
+    } else {
+        ReleaseEmsOccureByString(0, "012251");
+    }
+
+    if (ShmPrimaryMcuData->InputDet.bits.AcMainBreakerDetec == ABNORMAL) {
+        pAlarmCode->AlarmEvents.bits.MainPowerBreakerTrip = YES;
+        EmcOccureByString("012238");
+    } else {
+        ReleaseEmsOccureByString(0, "012238");
+    }
+
+    if (ShmPrimaryMcuData->InputDet.bits.SpdDetec == ABNORMAL) {
+        pAlarmCode->AlarmEvents.bits.SpdTrip = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.SpdTrip = NO;
+    }
+
+    if (ShmPrimaryMcuData->InputDet.bits.DoorOpen == ABNORMAL) {
+        pAlarmCode->AlarmEvents.bits.DoorOpen = YES;
+        EmcOccureByString("012252");
+    } else {
+        ReleaseEmsOccureByString(0, "012252");
+    }
+
+    //DS60-120 add
+    //if (ShmPrimaryMcuData->InputDet.bits.Button1 == BTN_PRESS &&
+    //        ShmPrimaryMcuData->InputDet.bits.Button2 == BTN_PRESS) {
+    //    pSysConfig->ShowInformation = YES;
+    //} else {
+    //    pSysConfig->ShowInformation = NO;
+    //}
+
+    if (ShmPrimaryMcuData->InputDet.bits.Button1 == BTN_PRESS &&
+            !leftBtnPush
+#if defined DD360Audi
+            &&
+            getCurLcmPage() != _LCM_AUTHORIZING &&
+            getCurLcmPage() != _LCM_AUTHORIZ_COMP &&
+            getCurLcmPage() != _LCM_AUTHORIZ_FAIL
+#endif //defined DD360Audi
+       ) {
+        pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(pSysInfo->CurGunSelected);
+
+        if (!leftBtnPush) {
+            leftBtnPush = true;
+            log_info("left btn down...............................%x\n",
+                     pDcChargingInfo->SystemStatus);
+            if (pSysInfo->CurGunSelectedByAc != NO_DEFINE) {
+                pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(0);
+
+                switch (pAcChargingInfo->SystemStatus) {
+                case S_IDLE: {
+                    if (isDetectPlugin()) {
+                        _DetectPlugInTimeout();
+                        StopSystemTimeoutDet();
+                    }
+                }
+                break;
+                case S_REASSIGN_CHECK:
+                case S_REASSIGN:
+                case S_PREPARNING:
+                case S_PREPARING_FOR_EV:
+                case S_PREPARING_FOR_EVSE:
+                case S_CCS_PRECHARGE_ST0:
+                case S_CCS_PRECHARGE_ST1: {
+                    // 取消充電
+                    AcChargingTerminalProcess();
+                }
+                break;
+                case S_CHARGING: {
+                    if (pSysConfig->AuthorisationMode == AUTH_MODE_DISABLE) {
+                        // 停止充電
+                        AcChargingTerminalProcess();
+                    }
+                }
+                break;
+                case S_COMPLETE:
+                {}
+                break;
+                }
+            }
+
+            switch (pDcChargingInfo->SystemStatus) {
+            case S_IDLE: {
+                if (isDetectPlugin()) {
+                    _DetectPlugInTimeout();
+                    StopSystemTimeoutDet();
+                    destroySelGun(pSysInfo->CurGunSelected);
+                }
+#if defined DD360Audi
+                else {
+                    if (getConfirmSelectedGun(pSysInfo->CurGunSelected) == PASS) {
+                        //printf("destroy gun = %d\r\n", pSysInfo->CurGunSelected);
+                        destroySelGun(pSysInfo->CurGunSelected);
+                    } else {
+                        confirmSelGun(pSysInfo->CurGunSelected);
+                        log_info("confirm select gun ............................... %d \n",
+                                 pSysInfo->CurGunSelected);
+                    }
+                }
+#endif //defined DD360Audi
+            }
+            break;
+            case S_REASSIGN_CHECK:
+            case S_REASSIGN:
+            case S_PREPARNING:
+            case S_PREPARING_FOR_EV:
+            case S_PREPARING_FOR_EVSE:
+            case S_CCS_PRECHARGE_ST0:
+            case S_CCS_PRECHARGE_ST1: {
+                // 取消充電
+                if (pSysInfo->CurGunSelectedByAc != NO_DEFINE) {
+                    AcChargingTerminalProcess();
+                } else {
+                    ChargingTerminalProcess(pSysInfo->CurGunSelected);
+                }
+            }
+            break;
+            case S_CHARGING: {
+                if (pSysConfig->StopChargingByButton == YES ||
+                        pSysConfig->AuthorisationMode == AUTH_MODE_DISABLE) {
+                    // 停止充電
+                    ChargingTerminalProcess(pSysInfo->CurGunSelected);
+                }
+            }
+            break;
+            case S_COMPLETE: {
+                // 回 IDLE
+                //log_info("right btn down.................S_COMPLETE \n");
+                //pDcChargingInfo->SystemStatus = S_IDLE;
+            }
+            break;
+            }
+        }
+    } else if (ShmPrimaryMcuData->InputDet.bits.Button1 == BTN_RELEASE) {
+        if (leftBtnPush) {
+            leftBtnPush = false;
+            //log_info("left btn up............................... \n");
+        }
+    }
+
+    if (ShmPrimaryMcuData->InputDet.bits.Button2 == BTN_PRESS &&
+            !rightBtnPush
+#if defined DD360Audi
+            &&
+            getCurLcmPage() != _LCM_IDLE &&
+            getCurLcmPage() != _LCM_AUTHORIZING &&
+            getCurLcmPage() != _LCM_AUTHORIZ_COMP &&
+            getCurLcmPage() != _LCM_AUTHORIZ_FAIL &&
+            getCurLcmPage() != _LCM_WAIT_FOR_PLUG
+#endif //defined DD360Audi
+       ) {
+        if (!rightBtnPush) {
+            rightBtnPush = true;
+            //log_info("right btn down............................... %d \n", pSysInfo->CurGunSelected);
+            if (pSysInfo->CurGunSelected + 1 < pSysConfig->TotalConnectorCount &&
+                    pSysInfo->IsAlternatvieConf == NO) {
+                pSysInfo->CurGunSelected++;
+                ChangeGunSelectByIndex(pSysInfo->CurGunSelected);
+            } else if (pSysConfig->AcConnectorCount > 0 &&
+                       pSysInfo->CurGunSelectedByAc == NO_DEFINE) {
+                pSysInfo->CurGunSelectedByAc = DEFAULT_AC_INDEX;
+            } else if (pSysInfo->IsAlternatvieConf == YES) {
+                for (uint8_t _index = 0; _index < pSysConfig->TotalConnectorCount; _index++) {
+                    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_index);
+
+                    if (pDcChargingInfo->SystemStatus != S_BOOTING &&
+                            pDcChargingInfo->SystemStatus != S_IDLE &&
+                            pDcChargingInfo->SystemStatus != S_RESERVATION) {
+                        pSysInfo->CurGunSelected = _index;
+                        ChangeGunSelectByIndex(pSysInfo->CurGunSelected);
+                        return;
+                    }
+                }
+                pSysInfo->CurGunSelected = 0;
+                ChangeGunSelectByIndex(pSysInfo->CurGunSelected);
+            } else {
+                pSysInfo->CurGunSelected = 0;
+                ChangeGunSelectByIndex(pSysInfo->CurGunSelected);
+            }
+        }
+        log_info("current select gun ............................... %d \n",
+                 pSysInfo->CurGunSelected);
+    } else if (ShmPrimaryMcuData->InputDet.bits.Button2 == BTN_RELEASE) {
+        if (rightBtnPush) {
+            rightBtnPush = false;
+            //log_info("right btn up............................... \n");
+        }
+    }
+}
+#endif //0
+
+//===============================================
+// 確認各小板偵測的錯誤狀況
+//===============================================
+void CheckErrorOccurStatus(uint8_t index)
+{
+#if 0
+    // 小板
+    if (chargingInfo[index]->Type == _Type_Chademo) {
+        if (pFaultCode->FaultEvents.bits.ChademoOutputRelayDrivingFault == YES) {
+            BoardErrOccurByString(index, "011012");
+        }
+//      else if (pAlarmCode->AlarmEvents.bits.ChademoGfdTrip == YES)
+//          BoardErrOccurByString(index, "012234");
+    } else if (chargingInfo[index]->Type == _Type_GB) {
+        if (pFaultCode->FaultEvents.bits.GbOutputRelayDrivingFault == YES) {
+            BoardErrOccurByString(index, "011016");
+        }
+//      else if (pAlarmCode->AlarmEvents.bits.GbGfdTrip == YES)
+//          BoardErrOccurByString(index, "012236");
+    } else if (chargingInfo[index]->Type == _Type_CCS_2) {
+        if (pFaultCode->FaultEvents.bits.CcsOutputRelayDrivingFault == YES) {
+            BoardErrOccurByString(index, "011014");
+        }
+//      else if (pAlarmCode->AlarmEvents.bits.CcsGfdTrip == YES)
+//          BoardErrOccurByString(index, "012235");
+    }
+#endif //0
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+    // RB
+    if (pSysConfig->PhaseLossPolicy == YES) {
+        if (pAlarmCode->AlarmEvents.bits.SystemL1InputUVP == YES ||
+                pAlarmCode->AlarmEvents.bits.SystemL2InputUVP == YES ||
+                pAlarmCode->AlarmEvents.bits.SystemL3InputUVP == YES) {
+            if (pSysWarning->ExtraErrProcess == _EXTRA_ERR_PROCESS_NONE) {
+                pSysWarning->ExtraErrProcess = _EXTRA_ERR_PROCESS_INUVP;
+                StopChargingProcessByString(2);
+                InformOcppErrOccur(13);
+            }
+
+            //DS60-120 add -----
+            if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "", 6) == EQUAL) {
+                if (pAlarmCode->AlarmEvents.bits.SystemL1InputUVP == YES) {
+                    memcpy(pDcChargingInfo->ConnectorAlarmCode, "012203", 6);
+                } else if (pAlarmCode->AlarmEvents.bits.SystemL2InputUVP == YES) {
+                    memcpy(pDcChargingInfo->ConnectorAlarmCode, "012204", 6);
+                } else if (pAlarmCode->AlarmEvents.bits.SystemL3InputUVP == YES) {
+                    memcpy(pDcChargingInfo->ConnectorAlarmCode, "012205", 6);
+                }
+            }
+            //log_info("1 CheckErrorOccurStatus\r\n");
+            pDcChargingInfo->StopChargeFlag = YES;
+            //------------------------------------------------------------------
+        } else {
+            if (pSysWarning->ExtraErrProcess == _EXTRA_ERR_PROCESS_INUVP) {
+                pSysWarning->ExtraErrProcess = _EXTRA_ERR_PROCESS_NONE;
+                ReleaseChargingProcessByString(2);
+                InformOcppErrOccur(6);
+            }
+        }
+    } else {
+        if (pSysWarning->ExtraErrProcess == _EXTRA_ERR_PROCESS_INUVP) {
+            pSysWarning->ExtraErrProcess = _EXTRA_ERR_PROCESS_NONE;
+            ReleaseChargingProcessByString(2);
+            InformOcppErrOccur(6);
+        }
+    }
+
+    if (pAlarmCode->AlarmEvents.bits.SystemL1InputOVP == YES ||
+            pAlarmCode->AlarmEvents.bits.SystemL2InputOVP == YES ||
+            pAlarmCode->AlarmEvents.bits.SystemL3InputOVP == YES) {
+        if (pSysWarning->ExtraErrProcess == _EXTRA_ERR_PROCESS_NONE) {
+            pSysWarning->ExtraErrProcess = _EXTRA_ERR_PROCESS_INOVP;
+            StopChargingProcessByString(2);
+            InformOcppErrOccur(14);
+        }
+
+        //DS60-120 -----
+        if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "", 6) == EQUAL) {
+            if (pAlarmCode->AlarmEvents.bits.SystemL1InputOVP == YES) {
+                memcpy(pDcChargingInfo->ConnectorAlarmCode, "012200", 6);
+            } else if (pAlarmCode->AlarmEvents.bits.SystemL2InputOVP == YES) {
+                memcpy(pDcChargingInfo->ConnectorAlarmCode, "012201", 6);
+            } else if (pAlarmCode->AlarmEvents.bits.SystemL3InputOVP == YES) {
+                memcpy(pDcChargingInfo->ConnectorAlarmCode, "012202", 6);
+            }
+        }
+        //log_info("2 CheckErrorOccurStatus\r\n");
+        pDcChargingInfo->StopChargeFlag = YES;
+        //----------------------------------------------------------------------
+    } else {
+        if (pSysWarning->ExtraErrProcess == _EXTRA_ERR_PROCESS_INOVP) {
+            pSysWarning->ExtraErrProcess = _EXTRA_ERR_PROCESS_NONE;
+            ReleaseChargingProcessByString(2);
+            InformOcppErrOccur(6);
+        }
+    }
+
+    //DS60-120 ----
+    //if (chargingInfo[index]->Type == _Type_Chademo) {
+    //    if (pFaultCode->FaultEvents.bits.ChademoOutputRelayWelding == YES) {
+    //        memcpy(chargingInfo[index]->ConnectorAlarmCode, "011011", 6);
+    //    } else if (pFaultCode->FaultEvents.bits.ChademoOutputRelayDrivingFault == YES) {
+    //        memcpy(chargingInfo[index]->ConnectorAlarmCode, "011012", 6);
+    //    } else if (pAlarmCode->AlarmEvents.bits.SystemChademoOutputOVP == YES) {
+    //        memcpy(chargingInfo[index]->ConnectorAlarmCode, "012217", 6);
+    //    }
+    //} else if (chargingInfo[index]->Type == _Type_GB) {
+    //    if (pFaultCode->FaultEvents.bits.GbOutputRelayWelding == YES) {
+    //        memcpy(chargingInfo[index]->ConnectorAlarmCode, "011015", 6);
+    //    } else if (pFaultCode->FaultEvents.bits.GbOutputRelayDrivingFault == YES) {
+    //        memcpy(chargingInfo[index]->ConnectorAlarmCode, "011016", 6);
+    //    } else if (pAlarmCode->AlarmEvents.bits.SystemGbOutputOVP == YES) {
+    //        memcpy(chargingInfo[index]->ConnectorAlarmCode, "012221", 6);
+    //    }
+    //} else if (chargingInfo[index]->Type == _Type_CCS_2) {
+    //    if (pFaultCode->FaultEvents.bits.CcsOutputRelayWelding == YES) {
+    //        memcpy(chargingInfo[index]->ConnectorAlarmCode, "011013", 6);
+    //    } else if (pFaultCode->FaultEvents.bits.CcsOutputRelayDrivingFault == YES) {
+    //        memcpy(chargingInfo[index]->ConnectorAlarmCode, "011014", 6);
+    //    } else if (pAlarmCode->AlarmEvents.bits.SystemCcsOutputOVP == YES) {
+    //        memcpy(chargingInfo[index]->ConnectorAlarmCode, "012219", 6);
+    //    }
+    //}
+
+    //--------------------------------------------------------------------------
+    if (strlen((char *)pDcChargingInfo->ConnectorAlarmCode) == 0) {
+        //Primary
+        if (pAlarmCode->AlarmEvents.bits.EmergencyStopTrip == YES) {
+            memcpy(pDcChargingInfo->ConnectorAlarmCode, "012251", 6);
+        } else if (pAlarmCode->AlarmEvents.bits.DoorOpen == YES) {
+            memcpy(pDcChargingInfo->ConnectorAlarmCode, "012252", 6);
+        } else if (pAlarmCode->AlarmEvents.bits.MainPowerBreakerTrip == YES) {
+            memcpy(pDcChargingInfo->ConnectorAlarmCode, "012238", 6);
+        } else if (pAlarmCode->AlarmEvents.bits.DisconnectedFromDo == YES) {
+            memcpy(pDcChargingInfo->ConnectorAlarmCode, "012304", 6);
+        }
+    }
+}
+
+//===============================================
+// 確認 GPIO 狀態
+//===============================================
+void gpio_set_value(unsigned int gpio, unsigned int value)
+{
+    int fd;
+    char buf[MAX_BUF];
+
+    snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);
+    fd = open(buf, O_WRONLY);
+    if (fd < 0) {
+        perror("gpio/set-value");
+        return;
+    }
+
+    if (value) {
+        write(fd, "1", 2);
+    } else {
+        write(fd, "0", 2);
+    }
+
+    close(fd);
+}
+
+int gpio_get_value(unsigned int gpio, unsigned int *value)
+{
+    int fd;
+    char buf[MAX_BUF];
+    char ch;
+
+    snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);
+
+    fd = open(buf, O_RDONLY);
+    if (fd < 0) {
+        perror("gpio/get-value");
+        return fd;
+    }
+
+    read(fd, &ch, 1);
+
+    if (ch != '0') {
+        *value = 1;
+    } else {
+        *value = 0;
+    }
+
+    close(fd);
+    return 0;
+}
+
+void CheckGunTypeFromHw()
+{
+    uint8_t i = 0;
+    int pinIn[4] = {22, 23, 44, 45};
+    unsigned int gpioValue = 0;
+    uint8_t tmp[2] = {0};
+
+    log_info("ModelName = %s", pSysConfig->ModelName);
+    for (i = 0; i < ARRAY_SIZE(pinIn); i++) {
+        gpio_get_value(pinIn[i], &gpioValue);
+        switch (pinIn[i]) {
+        //right slot
+        case 22:
+            bd1_1_status = gpioValue;
+            break;
+        case 23:
+            bd1_2_status = gpioValue;
+            break;
+
+        //left slot
+        case 44:
+            bd0_1_status = gpioValue;
+            break;
+        case 45:
+            bd0_2_status = gpioValue;
+            break;
+        }
+    }
+
+#if 1 //DS60-120 remove
+    //BD1(Left-CCS-CND1-SMR2-左槍), BD2(Right-CHADEMO-CND2-SMR1-右槍), CCS: 10 , CHAdeMO: 01 , GBT: 11
+    //CcsChargingData [0至1] 分別為 Right至Left
+    //model name 槍順序左至右分別為Right至Left
+    tmp[1] = (bd0_1_status << 4 | bd0_2_status);
+    tmp[0] = (bd1_1_status << 4 | bd1_2_status);
+    for (i = 0; i < 2; i++) {
+        switch (tmp[i]) {
+        case 0x01:
+            log_info("BD%d(%s) = %s ", i + 1, i == 0 ? "Left" : "Right", "CHAdeMO");
+            break;
+
+        case 0x10:
+            log_info("BD%d(%s) = %s ", i + 1, i == 0 ? "Left" : "Right", "CCS");
+            break;
+
+        case 0x11:
+            log_info("BD%d(%s) = %s ", i + 1, i == 0 ? "Left" : "Right", "GBT");
+            break;
+
+        case 0x00:
+            log_info("BD%d(%s) = %s ", i + 1, i == 0 ? "Left" : "Right", "None");
+            break;
+        }
+    }
+#endif //0
+}
+
+void CheckGpioInStatus()
+{
+    int pinIn[2] = { 27, 47 };//{IO BD1_2, IO BD2_2}
+    unsigned int gpioValue = 0;
+
+    for (int i = 0; i < ARRAY_SIZE(pinIn); i++) {
+        gpio_get_value(pinIn[i], &gpioValue);
+        if (gpioValue == 0x01) {
+            switch (pinIn[i]) {
+            // 小板緊急停止
+            case 47: {
+                for (int i = 0; i < pSysConfig->TotalConnectorCount; i++) {
+                    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(i);
+
+                    if (pDcChargingInfo->slotsIndex == 1) {
+                        if (pDcChargingInfo->Type == _Type_Chademo) {
+                            BoardErrOccurByString(i, "023730");
+                        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                            BoardErrOccurByString(i, "013627");
+                        }
+                        break;
+                    }
+                }
+            }
+            break;
+            case 27: {
+                for (int i = 0; i < pSysConfig->TotalConnectorCount; i++) {
+                    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(i);
+
+                    if (pDcChargingInfo->slotsIndex == 3) {
+                        if (pDcChargingInfo->Type == _Type_Chademo) {
+                            BoardErrOccurByString(i, "023730");
+                        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                            BoardErrOccurByString(i, "013627");
+                        }
+                        break;
+                    }
+                }
+            }
+            break;
+            }
+        } else {
+            switch (pinIn[i]) {
+            // 小板解除緊急停止
+            case 47: {
+                for (int i = 0; i < pSysConfig->TotalConnectorCount; i++) {
+                    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(i);
+
+                    if (pDcChargingInfo->slotsIndex == 1) {
+                        if (pDcChargingInfo->Type == _Type_Chademo) {
+                            ReleaseBoardErrOccurByString(i, "023730");
+                        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                            ReleaseBoardErrOccurByString(i, "013627");
+                        }
+                        break;
+                    }
+                }
+            }
+            break;
+            case 27: {
+                for (int i = 0; i < pSysConfig->TotalConnectorCount; i++) {
+                    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(i);
+
+                    if (pDcChargingInfo->slotsIndex == 3) {
+                        if (pDcChargingInfo->Type == _Type_Chademo) {
+                            ReleaseBoardErrOccurByString(i, "023730");
+                        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                            ReleaseBoardErrOccurByString(i, "013627");
+                        }
+                        break;
+                    }
+                }
+            }
+            break;
+            }
+        }
+    }
+}
+
+//===============================================
+// Main process
+//===============================================
+// 檢查 uint8_t 中某個 Bit 的值
+// _byte : 欲改變的 byte
+// _bit : 該 byte 的第幾個 bit
+uint8_t DetectBitValue(uint8_t _byte, uint8_t _bit)
+{
+    return ( _byte & mask_table[_bit] ) != 0x00;
+}
+
+// 設定 Byte 中某個 Bit的值
+// _byte : 欲改變的 byte
+// _bit : 該 byte 的第幾個 bit
+// value : 修改的值為 0 or 1
+void SetBitValue(uint8_t *_byte, uint8_t _bit, uint8_t value)
+{
+    if (value == 1) {
+        *_byte |= (1 << _bit);
+    } else if (value == 0) {
+        *_byte ^= (1 << _bit);
+    }
+}
+
+#if 0
+void UserScanFunction()
+{
+    bool idleReq = false;
+    uint8_t stopReq = 255;
+    pAcChargingInfo =  (struct ChargingInfoData *)GetAcChargingInfoData(0);
+
+    // 當前非驗證的狀態
+    if (!IsAuthorizingMode()) {
+#if defined DD360Audi
+        //當前沒有選槍
+        if (getConfirmSelectedGun(pSysInfo->CurGunSelected) == FAIL) { //Jerry add
+            strcpy((char *)pSysConfig->UserId, "");
+            return;
+        }
+#endif //defined DD360Audi
+
+        // 先判斷現在是否可以提供刷卡
+        // 1. 如果當前沒有槍是閒置狀態,則無提供刷卡功能
+        // 2. 停止充電
+        if (pSysInfo->PageIndex == _LCM_FIX) {
+            strcpy((char *)pSysConfig->UserId, "");
+            return;
+        }
+
+        for (uint8_t i = 0; i < pSysConfig->TotalConnectorCount; i++) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(i);
+
+            if (pDcChargingInfo->SystemStatus == S_CHARGING) {
+                stopReq = i;
+            }
+            if ((pDcChargingInfo->SystemStatus == S_IDLE &&
+                    pDcChargingInfo->IsAvailable) == YES ||
+                    (_acgunIndex > 0 && pAcChargingInfo->SystemStatus ==
+                     S_IDLE && pAcChargingInfo->IsAvailable)
+               ) {
+                idleReq = true;
+            }
+        }
+
+        if (_acgunIndex > 0 && pSysInfo->CurGunSelectedByAc == DEFAULT_AC_INDEX &&
+                pAcChargingInfo->SystemStatus == S_CHARGING) {
+            stopReq = DEFAULT_AC_INDEX;
+        }
+
+        if (strlen((char *)pSysConfig->UserId) > 0) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(pSysInfo->CurGunSelected);
+
+            if (_acgunIndex > 0 && stopReq == DEFAULT_AC_INDEX &&
+                    pSysInfo->CurGunSelectedByAc == DEFAULT_AC_INDEX) {
+                char value[32];
+
+                log_info("ac stop charging \n");
+                log_info("index = %d, card number = %s, UserId = %s \n", pSysInfo->CurGunSelectedByAc,
+                         pAcChargingInfo->StartUserId, pSysConfig->UserId);
+                memcpy(value, (uint8_t *)pAcChargingInfo->StartUserId,
+                       ARRAY_SIZE(pAcChargingInfo->StartUserId));
+                if (strcmp((char *)pSysConfig->UserId, value) == EQUAL) {
+                    AcChargingTerminalProcess();
+                }
+                strcpy((char *)pSysConfig->UserId, "");
+            } else if (stopReq < pSysConfig->TotalConnectorCount &&
+                       pDcChargingInfo->SystemStatus == S_CHARGING &&
+                       (_acgunIndex <= 0 || (_acgunIndex > 0 && pSysInfo->CurGunSelectedByAc == NO_DEFINE))) {
+                char value[32];
+
+                log_info("stop charging \n");
+                log_info("index = %d, card number = %s, UserId = %s \n",
+                         pSysInfo->CurGunSelected,
+                         pDcChargingInfo->StartUserId,
+                         pSysConfig->UserId);
+                memcpy(value, (uint8_t *)pDcChargingInfo->StartUserId,
+                       ARRAY_SIZE(pDcChargingInfo->StartUserId));
+
+                // 同一張卡直接停掉
+                if (strcmp((char *)pSysConfig->UserId, value) == EQUAL) {
+                    ChargingTerminalProcess(pSysInfo->CurGunSelected);
+                    strcpy((char *)pSysConfig->UserId, "");
+                } else {
+                    // 進驗證
+                    if (_acgunIndex > 0 && pSysInfo->CurGunSelectedByAc == DEFAULT_AC_INDEX) {
+                        _authorizeIndex = pSysInfo->CurGunSelectedByAc;
+                    } else {
+                        _authorizeIndex = pSysInfo->CurGunSelected;
+                    }
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                    StartSystemTimeoutDet(Timeout_AuthorizingForStop);
+                    AuthorizingStart();
+#else
+                    strcpy((char *)pSysConfig->UserId, "");
+#endif //!defined DD360 && !defined DD360Audi
+                }
+            } else if (idleReq) {
+                if (pSysConfig->TotalConnectorCount > 1 &&
+                        stopReq != 255 &&
+                        pSysInfo->IsAlternatvieConf == YES) {
+                    idleReq = false;
+                    strcpy((char *)pSysConfig->UserId, "");
+                } else if ((_acgunIndex > 0 && pSysInfo->CurGunSelectedByAc == DEFAULT_AC_INDEX) ||
+                           pDcChargingInfo->SystemStatus == S_IDLE) {
+                    log_info("// LCM => Authorizing \n");
+#if defined DD360Audi
+                    setSelGunWaitToAuthor(pSysInfo->CurGunSelected); //Jerry add
+#endif //defined DD360Audi
+                    // LCM => Authorizing
+                    pSysInfo->SystemPage = _LCM_AUTHORIZING;
+                    // 進入確認卡號狀態
+                    AuthorizingStart();
+                } else {
+                    strcpy((char *)pSysConfig->UserId, "");
+                }
+            } else {
+                strcpy((char *)pSysConfig->UserId, "");
+            }
+        }
+    } else {
+        // 透過後臺停止充電的判斷
+        if (isAuthorizedComplete()
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                || (pSysInfo->OcppConnStatus == NO &&
+                    pSysConfig->OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING)
+#endif //!defined DD360 && !defined DD360Audi
+           ) {
+            // 判斷後台回覆狀態
+            if (canStartCharging()
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                    || (pSysInfo->OcppConnStatus == NO &&
+                        pSysConfig->OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING)
+#endif //!defined DD360 && !defined DD360Audi
+               ) {
+                if (_authorizeIndex != NO_DEFINE) {
+                    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_authorizeIndex);
+
+                    // 先找 AC
+                    if (_authorizeIndex == DEFAULT_AC_INDEX) {
+                        if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST &&
+                                strcmp((char *)pDcChargingInfo->StartUserId, "") != EQUAL) {
+                            AcChargingTerminalProcess();
+                        }
+                    } else {
+                        if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST &&
+                                strcmp((char *)pDcChargingInfo->StartUserId, "") != EQUAL) {
+                            ChargingTerminalProcess(_authorizeIndex);
+                        }
+                    }
+                    strcpy((char *)pSysConfig->UserId, "");
+                    _authorizeIndex = NO_DEFINE;
+                }
+            } else {
+                strcpy((char *)pSysConfig->UserId, "");
+            }
+            ClearAuthorizedFlag();
+        } else if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST) {
+            // 白名單驗證
+            for (int i = 0; i < 10; i++) {
+                if (strcmp((char *)pSysConfig->LocalWhiteCard[i], "") != EQUAL) {
+                    if (strcmp((char *)pSysConfig->LocalWhiteCard[i], (char *)pSysConfig->UserId) == EQUAL) {
+                        ChargingTerminalProcess(_authorizeIndex);
+                        strcpy((char *)pSysConfig->UserId, "");
+                        ClearAuthorizedFlag();
+                        break;
+                    }
+                }
+            }
+        }
+    }
+}
+#endif //0
+
+uint8_t isModeChange(uint8_t gun_index)
+{
+    uint8_t result = NO;
+
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun_index);
+
+    if (pDcChargingInfo->SystemStatus != pDcChargingInfo->PreviousSystemStatus) {
+        result = YES;
+        pDcChargingInfo->PreviousSystemStatus = pDcChargingInfo->SystemStatus;
+        ShmDcCommonData->SystemModeChange = YES;
+    }
+
+    return result;
+}
+
+#if 0
+void ScannerCardProcess()
+{
+    if (!isDetectPlugin() && !isCardScan && pSysWarning->Level != 2 &&
+            pSysConfig->AuthorisationMode == AUTH_MODE_ENABLE) {
+        isCardScan = true;
+        // 處理刷卡及驗證卡號的動作
+        UserScanFunction();
+    }
+
+    if (pSysInfo->PageIndex == _LCM_AUTHORIZING) {
+        StartSystemTimeoutDet(Timeout_Authorizing);
+
+        // 確認驗證卡號完成沒
+        if (isAuthorizedComplete()
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                || pSysConfig->OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING
+#else
+                && gAudiCustInfo->PricesInfo[pSysInfo->CurGunSelected].Balance != FAIL_BALANCE_PRICES
+#endif //!defined DD360 && !defined DD360Audi
+           ) {
+            StopSystemTimeoutDet();
+            // 判斷後台回覆狀態
+            if (canStartCharging()
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                    || pSysConfig->OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING
+#endif //!defined DD360 && !defined DD360Audi
+               ) {
+                // LCM => Authorize complete
+                pSysInfo->SystemPage = _LCM_AUTHORIZ_COMP;
+            } else {
+                // LCM => Authorize fail
+                pSysInfo->SystemPage = _LCM_AUTHORIZ_FAIL;
+                strcpy((char *)pSysConfig->UserId, "");
+            }
+            ClearAuthorizedFlag();
+        } else if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST) {
+            // 白名單驗證
+            for (int i = 0; i < 10; i++) {
+                if (strcmp((char *)pSysConfig->LocalWhiteCard[i], "") != EQUAL) {
+                    if (strcmp((char *)pSysConfig->LocalWhiteCard[i], (char *)pSysConfig->UserId) == EQUAL) {
+                        pSysInfo->SystemPage = _LCM_AUTHORIZ_COMP;
+                        ClearAuthorizedFlag();
+                        break;
+                    }
+                }
+            }
+        }
+    } else if (pSysInfo->PageIndex == _LCM_AUTHORIZ_FAIL) {
+        StartSystemTimeoutDet(Timeout_VerifyFail);
+        isCardScan = false;
+    } else if (pSysInfo->PageIndex == _LCM_AUTHORIZ_COMP) {
+        StartSystemTimeoutDet(Timeout_VerifyComp);
+    } else if (pSysInfo->PageIndex == _LCM_WAIT_FOR_PLUG) {
+        StartSystemTimeoutDet(Timeout_WaitPlug);
+    } else {
+        isCardScan = false;
+    }
+}
+
+bool AddGunInfoByConnector(uint8_t typeValue, uint8_t slots)
+{
+    bool result = true;
+
+    switch (typeValue) {
+    case '0': // none
+        break;
+    case '1': // IEC 62196-2 Type 1/SAE J1772 Plug
+        break;
+    case '2': // IEC 62196-2 Type 1/SAE J1772 Socket
+        break;
+    case '3': // IEC 62196-2 Type 2 Plug
+    case '4': // IEC 62196-2 Type 2 Socket
+        if (AC_QUANTITY > _ac_Index) {
+            pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(_acgunIndex);
+
+            pAcChargingInfo = &pSysInfo->AcChargingData[_ac_Index];
+
+            // AC 固定 index
+            pAcChargingInfo->Index = 0;
+            pAcChargingInfo->ReservationId = -1;
+            pAcChargingInfo->SystemStatus = S_IDLE;
+            pAcChargingInfo->Type = _Type_AC;
+            pAcChargingInfo->IsAvailable = YES;
+            pAcChargingInfo->schedule.isTriggerStart = NO; //DS60-120 add
+            pAcChargingInfo->schedule.isTriggerStop = NO;  //DS60-120 add
+            _ac_Index++;
+            _acgunIndex++;
+        } else {
+            result = false;
+        }
+        break;
+    case '5': // GB/T AC Plug
+        break;
+    case '6': // GB/T AC Socket
+        break;
+    case 'J':
+    case 'K': { // CHAdeMO
+        if (CHAdeMO_QUANTITY > _chademoIndex) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_gunIndex);
+
+            pDcChargingInfo = &pSysInfo->ChademoChargingData[_chademoIndex];
+            pDcChargingInfo->Index = _gunIndex;
+            pDcChargingInfo->ReservationId = -1;
+            pDcChargingInfo->slotsIndex = slots;
+            pDcChargingInfo->SystemStatus = S_BOOTING;
+            pDcChargingInfo->Type = _Type_Chademo;
+            pDcChargingInfo->type_index = _chademoIndex;
+            pDcChargingInfo->IsAvailable = YES;
+
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_acgunIndex);
+            pDcChargingInfo->schedule.isTriggerStart = NO; //DS60-120 add
+            pDcChargingInfo->schedule.isTriggerStop = NO;  //DS60-120 add
+            _chademoIndex++;
+            _gunIndex++;
+        } else {
+            result = false;
+        }
+    }
+    break;
+
+    case 'T': //Rema CCS1
+    case 'D': //Rema CCS2
+    case 'U': // CCS1 combo
+    case 'E': // CCS2 combo
+    case 'V': // Liquid CCS1 combo
+    case 'F': { // Liquid CCS2 combo
+        if (CCS_QUANTITY > _ccsIndex) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_gunIndex);
+
+            pDcChargingInfo = &pSysInfo->CcsChargingData[_ccsIndex];
+
+            pDcChargingInfo->Index = _gunIndex;
+            pDcChargingInfo->ReservationId = -1;
+            pDcChargingInfo->slotsIndex = slots;
+            pDcChargingInfo->SystemStatus = S_BOOTING;
+            pDcChargingInfo->Type = _Type_CCS_2;
+            pDcChargingInfo->type_index = _ccsIndex;
+            pDcChargingInfo->IsAvailable = YES;
+
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_acgunIndex);
+            pDcChargingInfo->schedule.isTriggerStart = NO;//DS60-120 add
+            pDcChargingInfo->schedule.isTriggerStop = NO; //DS60-120 add
+            // 現階段預設為走 DIN70121
+            ShmCcsData->CommProtocol = _CCS_COMM_V2GMessage_DIN70121;
+            _ccsIndex++;
+            _gunIndex++;
+        } else {
+            result = false;
+        }
+    }
+    break;
+    case 'G': { // GBT DC
+        if (GB_QUANTITY > _gb_Index) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_gunIndex);
+
+            pDcChargingInfo = &pSysInfo->GbChargingData[_gb_Index];
+
+            pDcChargingInfo->Index = _gunIndex;
+            pDcChargingInfo->ReservationId = -1;
+            pDcChargingInfo->slotsIndex = slots;
+            pDcChargingInfo->SystemStatus = S_BOOTING;
+            pDcChargingInfo->Type = _Type_GB;
+            pDcChargingInfo->type_index = _gb_Index;
+            pDcChargingInfo->IsAvailable = YES;
+
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_acgunIndex);
+            pDcChargingInfo->schedule.isTriggerStart = NO;//DS60-120 add
+            pDcChargingInfo->schedule.isTriggerStop = NO; //DS60-120 add
+            _gb_Index++;
+            _gunIndex++;
+        } else {
+            result = false;
+        }
+    }
+    break;
+
+        //case 'D': // GBT DC x 2
+        //    break;
+    }
+    return result;
+}
+#endif //0
+
+static int checkSlotGpioMappingGunType(uint8_t gunIndex, uint8_t gunType)
+{
+    uint8_t slot1 = 0, slot2 = 0;
+
+    if (gunIndex == 0) {
+        slot1 = bd0_1_status;
+        slot2 = bd0_2_status;
+    } else if (gunIndex == 1) {
+        slot1 = bd1_1_status;
+        slot2 = bd1_2_status;
+    }
+
+    log_info("slot %d gpio1 = %d, gpio2 = %d, type = %d\r\n", gunIndex, slot1, slot2, gunType);
+    switch (gunType) {
+    case _Type_Chademo:
+        if (slot1 != NO && slot2 != YES) {
+            return FAIL;
+        }
+        break;
+
+    case _Type_CCS_2:
+        if (slot1 != YES && slot2 != NO) {
+            return FAIL;
+        }
+        break;
+
+    case _Type_GB:
+        if (slot1 != YES && slot2 != YES) {
+            return FAIL;
+        }
+        break;
+    }
+
+    return PASS;
+}
+
+bool CheckConnectorTypeStatus()
+{
+    bool result = true;
+
+    uint8_t gunIndex = 0;
+    struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
+    struct ChargingInfoData *pDcChargingInfo = NULL;
+
+    if (!MappingGunChargingInfo("CSU Task")) {
+        log_error("CheckConnectorTypeStatus MappingGunChargingInfo failed\r\n");
+        return false;
+    }
+
+    // 偵測槍屬於哪個 slot : 可知道插在板上的Slot 0 或 1 是 Chademo 還是 CCS
+    for (gunIndex = 0; gunIndex < pSysConfig->TotalConnectorCount; gunIndex++) {
+        pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+        if (checkSlotGpioMappingGunType(gunIndex, pDcChargingInfo->Type) == FAIL) {
+            return false;
+        }
+
+        switch (gunIndex) {
+        case 0:
+            if (pSysConfig->TotalConnectorCount == 1) {
+                if ((bd0_1_status == YES || bd0_2_status == YES) &&
+                        (bd1_1_status == NO && bd1_2_status == NO)) {
+                    pDcChargingInfo->Evboard_id = 0x01;
+                }
+
+                if ((bd0_1_status == NO && bd0_2_status == NO) &&
+                        (bd1_1_status == YES || bd1_2_status == YES)
+                   ) {
+                    pDcChargingInfo->Evboard_id = 0x02;
+                }
+                break;
+            }
+
+            pDcChargingInfo->Evboard_id = 0x01;
+            break;
+
+        case 1:
+            pDcChargingInfo->Evboard_id = 0x02;
+            break;
+        }
+
+        CheckHwSlotStatusLog(gunIndex);
+
+        if (pDcChargingInfo->Evboard_id == 0x00) {
+            return false;
+        }
+    }
+
+    AdjustChargerCurrent();
+
+#if 0
+    //log_info("bd0_1_status = %d, bd0_2_status = %d, bd1_1_status = %d, bd1_2_status = %d \n",
+    //            bd0_1_status,
+    //            bd0_2_status,
+    //            bd1_1_status,
+    //            bd1_2_status);
+
+    if (strlen((char *) pSysConfig->ModelName) >= 9) {
+        //printf("1 CheckConnectorTypeStatus\r\n");
+        uint8_t slots = 1;
+        for (uint8_t typeIndex = 7; typeIndex <= 9; typeIndex++) {
+            if (!AddGunInfoByConnector(pSysConfig->ModelName[typeIndex], slots)) {
+                return false;
+            }
+
+            slots++;
+        }
+
+        // AC index 接在 DC 後面
+        //if (AC_QUANTITY > 0) {
+        if (_ac_Index > 0) { //DS60-120 add
+            ac_chargingInfo[0]->Index += _gunIndex;
+        }
+
+        pSysConfig->TotalConnectorCount = _gunIndex;
+        pSysConfig->AcConnectorCount = _acgunIndex;
+        log_info("DC connector Quality = %d, AC connector Quality = %d",
+                 pSysConfig->TotalConnectorCount,
+                 pSysConfig->AcConnectorCount);
+        log_info("Type 0~3 = CHAdeMO, CCS, GB, AC");
+        if (pSysConfig->TotalConnectorCount == 0 &&
+                pSysConfig->AcConnectorCount == 0) {
+            result = false;
+        }
+
+        if (pSysConfig->TotalConnectorCount == 1) {
+            //DS60-120 add
+            bool isFind = false;
+            if (chargingInfo[0]->Type == _Type_Chademo) {
+                if ((bd0_1_status == 0 && bd0_2_status == 1) ||
+                        (bd1_1_status == 0 && bd1_2_status == 1)) {
+                    isFind = true;
+                }
+            } else if (chargingInfo[0]->Type == _Type_CCS_2) {
+                if ((bd0_1_status == 1 && bd0_2_status == 0) ||
+                        (bd1_1_status == 1 && bd1_2_status == 0)) {
+                    isFind = true;
+                }
+            } else if (chargingInfo[0]->Type == _Type_GB) {
+                if ((bd0_1_status == 1 && bd0_2_status == 1) ||
+                        (bd1_1_status == 1 && bd1_2_status == 1)) {
+                    isFind = true;
+                }
+            }
+
+            if (isFind) {
+                //if (strncmp((char *)&pSysConfig->ModelName[7], "0", 1) != 0) {
+                //    if (bd0_1_status == 1 || bd0_2_status == 1) {
+                //        chargingInfo[0]->Evboard_id = 0x01;
+                //    } else if (bd1_1_status == 1 || bd1_2_status == 1) {
+                //        chargingInfo[0]->Evboard_id = 0x02;
+                //    }
+                //} else if (strncmp((char *)&pSysConfig->ModelName[9], "0", 1) != 0) {
+                //    if (bd0_1_status == 1 || bd0_2_status == 1) {
+                //        chargingInfo[0]->Evboard_id = 0x01;
+                //    } else if (bd1_1_status == 1 || bd1_2_status == 1) {
+                //        chargingInfo[0]->Evboard_id = 0x02;
+                //    }
+                //} else {
+                //    chargingInfo[0]->Evboard_id = 0x01;
+                //}
+
+                if (bd0_1_status == 1 || bd0_2_status == 1) {
+                    chargingInfo[0]->Evboard_id = 0x01;
+                }
+
+                if (bd1_1_status == 1 || bd1_2_status == 1) {
+                    chargingInfo[0]->Evboard_id = 0x02;
+                }
+                CheckHwSlotStatusLog(0);
+            } else {
+                result = false;
+            }
+            //chargingInfo[0]->Evboard_id = 0x01;
+            log_info("index = %d, Type = %d, Evboard_id = %d", 0, chargingInfo[0]->Type, chargingInfo[0]->Evboard_id);
+        } else {
+            char type = NO_DEFINE; //DS60-120 add
+
+            // 偵測槍屬於哪個 slot : 可知道插在板上的Slot 0 或 1 是 Chademo 還是 CCS
+            for (uint8_t gunIndex = 0; gunIndex < pSysConfig->TotalConnectorCount; gunIndex++) {
+                if (gunIndex == 0 && bd0_1_status == 0 && bd0_2_status == 1) {
+                    // 與硬體相同 type : Chademo
+                    if (chargingInfo[gunIndex]->Type == _Type_Chademo) {
+                        chargingInfo[gunIndex]->Evboard_id = 0x01;
+                    }
+                } else if (gunIndex == 0 && bd0_1_status == 1 && bd0_2_status == 0) {
+                    // 與硬體相同 type : CCS
+                    if (chargingInfo[gunIndex]->Type == _Type_CCS_2) {
+                        chargingInfo[gunIndex]->Evboard_id = 0x01;
+                    }
+                } else if (gunIndex == 0 && bd0_1_status == 1 && bd0_2_status == 1) {
+                    // 與硬體相同 type : GB
+                    if (chargingInfo[gunIndex]->Type == _Type_GB) {
+                        chargingInfo[gunIndex]->Evboard_id = 0x01;
+                    }
+                }
+
+                if (gunIndex == 1 && bd1_1_status == 0 && bd1_2_status == 1) {
+                    // 與硬體相同 type : Chademo
+                    if (chargingInfo[gunIndex]->Type == _Type_Chademo) {
+                        chargingInfo[gunIndex]->Evboard_id = 0x02;
+                    }
+
+                    if (pSysConfig->TotalConnectorCount == 1) {
+                        chargingInfo[gunIndex]->Evboard_id = 0x01;
+                    }
+                } else if (gunIndex == 1 && bd1_1_status == 1 && bd1_2_status == 0) {
+                    // 與硬體相同 type : CCS
+                    if (chargingInfo[gunIndex]->Type == _Type_CCS_2) {
+                        chargingInfo[gunIndex]->Evboard_id = 0x02;
+                    }
+
+                    if (pSysConfig->TotalConnectorCount == 1) {
+                        chargingInfo[gunIndex]->Evboard_id = 0x01;
+                    }
+                } else if (gunIndex == 1 && bd1_1_status == 1 && bd1_2_status == 1) {
+                    // 與硬體相同 type : GB
+                    if (chargingInfo[gunIndex]->Type == _Type_GB) {
+                        chargingInfo[gunIndex]->Evboard_id = 0x02;
+                    }
+
+                    if (pSysConfig->TotalConnectorCount == 1) {
+                        chargingInfo[gunIndex]->Evboard_id = 0x01;
+                    }
+                }
+
+                log_info("index = %d, Type = %d, Evboard_id = %d",
+                         gunIndex,
+                         chargingInfo[gunIndex]->Type,
+                         chargingInfo[gunIndex]->Evboard_id);
+                CheckHwSlotStatusLog(gunIndex);
+
+                if (type == NO_DEFINE) {
+                    type = chargingInfo[gunIndex]->Type;
+                }
+
+                if (chargingInfo[gunIndex]->Evboard_id == 0x00) {
+                    result = false;
+                }
+            }
+        }
+    } else {
+        // Module Name 不正確 - 告警
+        result = false;
+    }
+#endif //0
+    return result;
+}
+
+void KillTask()
+{
+    ChangeLcmByIndex(_LCM_FIX);
+    system("killall Module_EventLogging");
+    system("killall Module_PrimaryComm");
+    system("killall Module_EvComm");
+    system("killall Module_LcmControl");
+    system("killall Module_InternalComm");
+    //system("killall Module_DoComm");
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+    system("killall Module_PsuComm");
+    system("killall OcppBackend &");
+    system("killall Module_4g &");
+    system("killall Module_Wifi &");
+#endif //!defined DD360 && !defined DD360Audi
+}
+
+void KillTaskExceptPrimary()
+{
+    ChangeLcmByIndex(_LCM_FIX);
+    system("killall Module_EvComm");
+    system("killall Module_InternalComm");
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+    system("killall Module_PsuComm");
+    system("killall Module_4g &");
+    system("killall Module_Wifi &");
+#endif //!defined DD360 && !defined DD360Audi
+}
+
+void KillAllTask()
+{
+    ChangeLcmByIndex(_LCM_FIX);
+    system("killall Module_EventLogging");
+    system("killall Module_PrimaryComm");
+    system("killall Module_EvComm");
+    system("killall Module_LcmControl");
+    system("killall Module_InternalComm");
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+    system("killall Module_PsuComm");
+    system("killall OcppBackend &");
+    system("killall Module_4g &");
+    system("killall Module_Wifi &");
+#else
+    system("killall Module_DoComm");
+#endif //!defined DD360 && !defined DD360Audi
+}
+
+#if 0
+int CheckUpdateProcess(void)
+{
+    //bool isPass = true;
+    uint8_t retSucc = 0;
+    uint8_t retFail = 0;
+    uint8_t index = 0;
+    uint8_t target = 0;
+    char Buf[256];
+    char *new_str = NULL;
+    uint8_t *ptr = NULL;
+    int fd = 0;
+    int CanFd = 0;
+    int uartFd = 0;
+    unsigned int Type = 0;
+    long int MaxLen = 48 * 1024 * 1024, ImageLen = 0;
+    DIR *d;
+    struct dirent *dir;
+
+    d = opendir("/mnt/");
+    if (d) {
+        while ((dir = readdir(d)) != NULL) {
+            if (strcmp(dir->d_name, ".") == 0 || strcmp(dir->d_name, "..") == 0) {
+                continue;
+            }
+
+            new_str = calloc(strlen("/mnt/") + strlen(dir->d_name) + 1, sizeof(char));
+            //new_str[0] = '\0';
+            strcat(new_str, "/mnt/");
+            strcat(new_str, dir->d_name);
+            log_info("%s%s\r\n", "/mnt/", dir->d_name);
+            fd = open(new_str, O_RDONLY);
+            if (fd < 0) {
+                return FAIL;
+            }
+
+            ptr = calloc(MaxLen, sizeof(char)); //-48 is take out the header
+            //memset(ptr, 0xFF, MaxLen);  //-48 is take out the header
+
+            //get the image length
+            ImageLen = read(fd, ptr, MaxLen);
+            for (uint8_t i = 0; i < 16; i++) {
+                if (pSysConfig->ModelName[i] != ptr[i]) {
+                    return FAIL;
+                }
+            }
+
+            log_info("model name check pass. \n");
+            if (ImageLen > 20) {
+                Type = (((unsigned int)ptr[16]) << 24 |
+                        ((unsigned int)ptr[17]) << 16 |
+                        ((unsigned int)ptr[18]) << 8  |
+                        ((unsigned int)ptr[19]));
+                log_info("Typed...%x \r\n", Type);
+
+                switch (Type) {
+                case 0x10000001:
+                case 0x10000002:
+                case 0x10000003:
+                case 0x10000004:
+                case 0x10000005:
+                    if (Upgrade_Flash(Type, new_str, (char *)pSysConfig->ModelName) == PASS) {
+                        //return PASS;
+                        retSucc++;
+                    } else {
+                        log_info("Upgrade %x Failed\r\n", Type);
+                        //return FAIL;
+                        retFail++;
+                    }
+                    break;
+
+                case 0x10000007:
+                case 0x10000008:
+                case 0x10000009:
+                case 0x1000000A:
+                    CanFd = InitCanBus();
+                    if (CanFd > 0) {
+                        for (index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+                            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+                            if (pDcChargingInfo->Type == _Type_CCS_2) {
+                                uint8_t targetID = pDcChargingInfo->Evboard_id;
+
+                                if (pSysConfig->TotalConnectorCount == 1 &&
+                                        ShmDcCommonData->CcsVersion == _CCS_VERSION_CHECK_TAG_V015S0) {
+                                    targetID += 1;
+                                }
+
+                                system("echo 3 > /proc/sys/vm/drop_caches");
+                                sleep(2);
+                                log_info("Upgrade CCS Processing..target id = %d \n", targetID);
+                                if (Upgrade_CCS(CanFd, Type, targetID, new_str, (char *)pSysConfig->ModelName) == FAIL) {
+                                    log_info("Upgrade CCS Failed \n");
+                                    retFail++;
+                                } else {
+                                    retSucc++;
+                                }
+                            }
+                        }
+                        close(CanFd);
+                    }
+                    memset(Buf, 0, sizeof(Buf));
+                    sprintf(Buf, "rm -rvf /mnt/%s", new_str);
+                    system(Buf);
+                    //isPass = true;
+#if 0
+                    CanFd = InitCanBus();
+                    if (CanFd > 0) {
+                        for (index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+                            //if (!isPass) {
+                            //    break;
+                            //}
+                            if (chargingInfo[index]->Type == _Type_CCS_2) {
+                                if (Upgrade_CCS(CanFd, Type, chargingInfo[index]->Evboard_id, new_str, (char *)pSysConfig->ModelName) == FAIL) {
+                                    //isPass = false;
+                                    log_info("Upgrade %x Failed\r\n", Type);
+                                    retFail++;
+                                }
+                            }
+                        }
+                    } else {
+                        log_error("Upgrade CCS open CAN FD fail.\n");
+                        //isPass = false;
+                        return FAIL;
+                    }
+
+                    if (retFail != 0) {
+                        break;
+                    } else {
+                        retSucc++;
+                    }
+                    //return isPass;
+#endif //0
+                    break;
+
+                case 0x10000006:
+                case 0x1000000D:
+                case 0x1000000E:
+                case 0x20000002:
+                case 0x10000014:
+                    // CSU_PRIMARY_CONTROLLER : 0x10000006
+                    target = 0x00;
+
+                    if (Type == 0x10000006) {
+                        target = UPGRADE_PRI;
+                    } else if (Type == 0x1000000D) {
+                        target = UPGRADE_RB;
+                    } else if (Type == 0x1000000E) {
+                        target = UPGRADE_FAN;
+                    } else if (Type == 0x20000002) {
+                        target = UPGRADE_AC;
+                    } else if (Type == 0x10000014) {
+                        target = UPGRADE_LED;
+                    }
+
+                    uartFd = InitComPort(target);
+
+                    if (Upgrade_UART(uartFd, Type, target, new_str, (char *)pSysConfig->ModelName) == PASS) {
+                        //return PASS;
+                        retSucc++;
+                    } else {
+                        log_info("Upgrade %x Failed\r\n", Type);
+                        //return FAIL;
+                        return FAIL;
+                    }
+
+                    if (uartFd > 0) {
+                        close(uartFd);
+                    }
+                    break;
+
+                case 0x1000000B:
+                case 0x1000000C:
+                    // CHAdeMO_BOARD : 0x1000000B, GBT : 0x1000000C
+                    //bool isPass = true;
+                    CanFd = InitCanBus();
+                    if (CanFd > 0) {
+                        for (index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+                            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+                            //if (!isPass) {
+                            //    break;
+                            //}
+
+                            if ((Type == 0x1000000B && pDcChargingInfo->Type == _Type_Chademo) ||
+                                    (Type == 0x1000000C && pDcChargingInfo->Type == _Type_GB)) {
+                                if (Upgrade_CAN(CanFd, Type, pDcChargingInfo->Evboard_id, new_str, (char *)pSysConfig->ModelName) == PASS) {
+                                    //isPass = PASS;
+                                    retSucc++;
+                                } else {
+                                    log_info("Upgrade %x Failed\r\n", Type);
+                                    //isPass = FAIL;
+                                    retFail++;
+                                }
+                            }
+                        }
+                    } else {
+                        log_info("Upgrad FD fail. \n");
+                        //isPass = false;
+                        return FAIL;
+                    }
+
+                    //return isPass;
+                    break;
+                }
+            }
+            free(new_str);
+            free(ptr);
+        }
+    }
+    free(dir);
+    closedir(d);
+
+    if (retFail != 0) {
+        return FAIL;
+    }
+
+    return PASS;
+}
+
+void CreateRfidFork()
+{
+    pid_t rfidRecPid;
+
+    rfidRecPid = fork();
+    log_info("CreateRfidFork = %d\r\n", rfidRecPid);
+    if (rfidRecPid == 0) {
+        while (true) {
+            // 刷卡判斷
+            RFID rfid;
+            if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_NO_CHARGING ||
+                    !pSysConfig->isRFID)
+            {}
+            else if (getRequestCardSN(rfidFd, 0, &rfid)) {
+                //log_info("Get Card..-%s- \n", pSysConfig->UserId);
+                if (strlen((char *)pSysConfig->UserId) == 0) {
+                    if (pSysConfig->RfidCardNumEndian == RFID_ENDIAN_LITTLE) {
+                        switch (rfid.snType) {
+                        case RFID_SN_TYPE_6BYTE:
+                            sprintf((char *) pSysConfig->UserId,
+                                    "%02X%02X%02X%02X%02X%02X",
+                                    rfid.currentCard[0], rfid.currentCard[1],
+                                    rfid.currentCard[2], rfid.currentCard[3],
+                                    rfid.currentCard[4], rfid.currentCard[5]);
+                            break;
+                        case RFID_SN_TYPE_7BYTE:
+                            sprintf((char *) pSysConfig->UserId,
+                                    "%02X%02X%02X%02X%02X%02X%02X",
+                                    rfid.currentCard[0], rfid.currentCard[1],
+                                    rfid.currentCard[2], rfid.currentCard[3],
+                                    rfid.currentCard[4], rfid.currentCard[5],
+                                    rfid.currentCard[6]);
+                            break;
+                        case RFID_SN_TYPE_10BYTE:
+                            sprintf((char *) pSysConfig->UserId,
+                                    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
+                                    rfid.currentCard[0], rfid.currentCard[1],
+                                    rfid.currentCard[2], rfid.currentCard[3],
+                                    rfid.currentCard[4], rfid.currentCard[5],
+                                    rfid.currentCard[6], rfid.currentCard[7],
+                                    rfid.currentCard[8], rfid.currentCard[9]);
+                            break;
+                        case RFID_SN_TYPE_4BYTE:
+                            sprintf((char *) pSysConfig->UserId,
+                                    "%02X%02X%02X%02X",
+                                    rfid.currentCard[0], rfid.currentCard[1],
+                                    rfid.currentCard[2], rfid.currentCard[3]);
+                            break;
+                        }
+                    } else if (pSysConfig->RfidCardNumEndian == RFID_ENDIAN_BIG) {
+                        switch (rfid.snType) {
+                        case RFID_SN_TYPE_6BYTE:
+                            sprintf((char *) pSysConfig->UserId,
+                                    "%02X%02X%02X%02X%02X%02X",
+                                    rfid.currentCard[5], rfid.currentCard[4],
+                                    rfid.currentCard[3], rfid.currentCard[2],
+                                    rfid.currentCard[1], rfid.currentCard[0]);
+                            break;
+                        case RFID_SN_TYPE_7BYTE:
+                            sprintf((char *) pSysConfig->UserId,
+                                    "%02X%02X%02X%02X%02X%02X%02X",
+                                    rfid.currentCard[6], rfid.currentCard[5],
+                                    rfid.currentCard[4], rfid.currentCard[3],
+                                    rfid.currentCard[2], rfid.currentCard[1],
+                                    rfid.currentCard[0]);
+                            break;
+                        case RFID_SN_TYPE_10BYTE:
+                            sprintf((char *) pSysConfig->UserId,
+                                    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
+                                    rfid.currentCard[9], rfid.currentCard[8],
+                                    rfid.currentCard[7], rfid.currentCard[6],
+                                    rfid.currentCard[5], rfid.currentCard[4],
+                                    rfid.currentCard[3], rfid.currentCard[2],
+                                    rfid.currentCard[1], rfid.currentCard[0]);
+                            break;
+                        case RFID_SN_TYPE_4BYTE:
+                            sprintf((char *) pSysConfig->UserId,
+                                    "%02X%02X%02X%02X",
+                                    rfid.currentCard[3], rfid.currentCard[2],
+                                    rfid.currentCard[1], rfid.currentCard[0]);
+                            break;
+                        }
+                    }
+                    log_info("card number = %s\n", pSysConfig->UserId);
+                }
+            }
+            usleep(500000);
+        }
+    }
+}
+#endif //0
+
+void StartSystemTimeoutDet(uint8_t flag)
+{
+    if (pSysInfo->SystemTimeoutFlag != flag) {
+        gettimeofday(&pSysInfo->SystemTimeoutTimer, NULL);
+    }
+    pSysInfo->SystemTimeoutFlag = flag;
+}
+
+void StopSystemTimeoutDet()
+{
+    gettimeofday(&pSysInfo->SystemTimeoutTimer, NULL);
+    pSysInfo->SystemTimeoutFlag = Timeout_None;
+}
+
+void StartGunInfoTimeoutDet(uint8_t gunIndex, uint8_t flag)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (gunIndex < pSysConfig->TotalConnectorCount) {
+        if (pDcChargingInfo->TimeoutFlag != flag) {
+            gettimeofday(&pDcChargingInfo->TimeoutTimer, NULL);
+        }
+        pDcChargingInfo->TimeoutFlag = flag;
+    }
+}
+
+void StopGunInfoTimeoutDet(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (gunIndex < pSysConfig->TotalConnectorCount) {
+        pDcChargingInfo->TimeoutFlag = Timeout_None;
+    }
+}
+
+void CheckConnectionTimeout(void)
+{
+#if defined DD360 || defined DD360Audi || defined DD360ComBox
+    if (gAudiCustInfo->RemoteSetup.ConnectionTimeout != 0) { //Jerry add
+        _connectionTimeout = gAudiCustInfo->RemoteSetup.ConnectionTimeout;
+    } else {
+        _connectionTimeout = CONN_PLUG_TIME_OUT;
+    }
+
+    return;
+#endif //defined DD360 || defined DD360Audi || defined DD360ComBox
+
+    if (system("pidof -s OcppBackend > /dev/null") != 0) {
+        _connectionTimeout = CONN_PLUG_TIME_OUT;
+    } else {
+        if (strcmp((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[ConnectionTimeOut].ItemData, "") != 0) {
+            _connectionTimeout = atoi((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[ConnectionTimeOut].ItemData);
+            if (_connectionTimeout <= 0) {
+                _connectionTimeout = CONN_PLUG_TIME_OUT;
+            }
+        } else {
+            _connectionTimeout = CONN_PLUG_TIME_OUT;
+        }
+    }
+}
+
+void CreateTimeoutFork()
+{
+    pid_t timeoutPid;
+
+    timeoutPid = fork();
+    log_info("CreateTimeoutFork = %d\r\n", timeoutPid);
+    if (timeoutPid == 0) {
+        gettimeofday(&_cmdSubPriority_time, NULL);
+        CheckConnectionTimeout();
+
+        while (1) {
+            if ((GetTimeoutValue(_cmdSubPriority_time) / 1000) > 5000) {
+                CheckConnectionTimeout();
+                gettimeofday(&_cmdSubPriority_time, NULL);
+            }
+
+            //printf("Timeout ***********SystemTimeoutFlag = %d, ********\n", pSysInfo->SystemTimeoutFlag);
+            // 系統
+            switch (pSysInfo->SystemTimeoutFlag) {
+            case Timeout_SelftestChk:
+                if (GetTimeoutValue(pSysInfo->SystemTimeoutTimer) / uSEC_VAL >= SELFTEST_TIMEOUT) {
+                    _SelfTestTimeout();
+                    StopSystemTimeoutDet();
+                    destroySelGun(DESTROY_ALL_SEL); //jerry add
+                }
+                break;
+
+            case Timeout_Authorizing:
+                if (GetTimeoutValue(pSysInfo->SystemTimeoutTimer) / uSEC_VAL >= AUTHORIZE_TIMEOUT) {
+                    _AuthorizedTimeout();
+                    StopSystemTimeoutDet();
+                    destroySelGun(pSysInfo->CurGunSelected);
+                    if (gAudiCustInfo->AuthorStateFromCabinet[pSysInfo->CurGunSelected] == YES) { //DoComm no ask cabinet balance
+                        gAudiCustInfo->AuthorStateFromCabinet[pSysInfo->CurGunSelected] = NO;
+                        pAlarmCode->AlarmEvents.bits.DisconnectedFromDo = ABNORMAL;
+                        log_error("Author timeout restart DoComm\r\n");
+                        system("killall Module_DoComm");
+                        sleep(1);
+                        system("/root/Module_DoComm &");
+                    }
+                }
+                break;
+
+            case Timeout_VerifyFail:
+                if (GetTimeoutValue(pSysInfo->SystemTimeoutTimer) / uSEC_VAL >= AUTHORIZE_FAIL_TIMEOUT) {
+                    _AutoReturnTimeout();
+                    StopSystemTimeoutDet();
+                    destroySelGun(pSysInfo->CurGunSelected);
+                    if (gAudiCustInfo->AuthorStateFromCabinet[pSysInfo->CurGunSelected] == YES) { //DoComm no ask cabinet balance
+                        gAudiCustInfo->AuthorStateFromCabinet[pSysInfo->CurGunSelected] = NO;
+                        pAlarmCode->AlarmEvents.bits.DisconnectedFromDo = ABNORMAL;
+                        log_error("Author timeout restart DoComm\r\n");
+                        system("killall Module_DoComm");
+                        sleep(1);
+                        system("/root/Module_DoComm &");
+                    }
+                }
+                break;
+
+            case Timeout_VerifyComp:
+                if (GetTimeoutValue(pSysInfo->SystemTimeoutTimer) / uSEC_VAL >= AUTHORIZE_COMP_TIMEOUT) {
+                    _AutoReturnTimeout();
+                    StopSystemTimeoutDet();
+                }
+                break;
+
+            case Timeout_WaitPlug:
+                if (GetTimeoutValue(pSysInfo->SystemTimeoutTimer) / uSEC_VAL >= _connectionTimeout) {
+                    _DetectPlugInTimeout();
+                    StopSystemTimeoutDet();
+                    destroySelGun(pSysInfo->CurGunSelected);
+                }
+                break;
+
+            case Timeout_ReturnToChargingGunDet:
+                if (GetTimeoutValue(pSysInfo->SystemTimeoutTimer) / uSEC_VAL >= RETURN_TO_CHARGING_PAGE) {
+#if defined DD360Audi
+                    if (getCurLcmPage() != _LCM_PRE_CHARGE &&
+                            getCurLcmPage() != _LCM_CHARGING &&
+                            getCurLcmPage() != _LCM_COMPLETE) {
+                        destroySelGun(pSysInfo->CurGunSelected); //jerry add
+
+                    }
+#endif //defined DD360Audi
+                    DisplayChargingInfo();
+                    StopSystemTimeoutDet();
+                }
+                break;
+
+            case Timeout_AuthorizingForStop:
+                if (GetTimeoutValue(pSysInfo->SystemTimeoutTimer) / uSEC_VAL >= AUTHORIZE_STOP_TIMEOUT) {
+                    strcpy((char *)pSysConfig->UserId, "");
+                    ClearAuthorizedFlag();
+                    StopSystemTimeoutDet();
+                }
+                break;
+
+            }
+            // 各槍
+            for (uint8_t gun_index = 0; gun_index < pSysConfig->TotalConnectorCount; gun_index++) {
+                pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun_index);
+
+                //printf("Timeout ***********TimeoutFlag = %d, ********\n", chargingInfo[gun_index]->TimeoutFlag);
+                switch (pDcChargingInfo->TimeoutFlag) {
+                case Timeout_Preparing:
+                    if (GetTimeoutValue(pDcChargingInfo->TimeoutTimer) / uSEC_VAL >= GUN_PREPARE_TIMEOUT) {
+                        _PrepareTimeout(gun_index);
+                        StopGunInfoTimeoutDet(gun_index);
+                        destroySelGun(gun_index); //jerry add
+                    }
+                    break;
+
+                case Timeout_EvChargingDet:
+                    if (GetTimeoutValue(pDcChargingInfo->TimeoutTimer) / uSEC_VAL >= GUN_EV_WAIT_TIMEOUT) {
+                        _DetectEvChargingEnableTimeout(gun_index);
+                        StopGunInfoTimeoutDet(gun_index);
+                        destroySelGun(gun_index); //jerry add
+                    }
+                    break;
+
+                case Timeout_EvseChargingDet:
+                    if (GetTimeoutValue(pDcChargingInfo->TimeoutTimer) / uSEC_VAL >= GUN_EVSE_WAIT_TIMEOUT) {
+                        _DetectEvseChargingEnableTimeout(gun_index);
+                        StopGunInfoTimeoutDet(gun_index);
+                        destroySelGun(gun_index); //jerry add
+                    }
+                    break;
+
+                case Timeout_EvseCompleteDet:
+                    if (GetTimeoutValue(pDcChargingInfo->TimeoutTimer) / uSEC_VAL >= GUN_COMP_WAIT_TIMEOUT) {
+                        StopGunInfoTimeoutDet(gun_index);
+                        destroySelGun(gun_index); //jerry add
+                    }
+                    break;
+
+                case Timeout_ForCcsPrechargeDet:
+                    if (GetTimeoutValue(pDcChargingInfo->TimeoutTimer) / uSEC_VAL >= GUN_PRECHARGING_TIMEOUT) {
+                        _CcsPrechargeTimeout(gun_index);
+                        StopGunInfoTimeoutDet(gun_index);
+                        destroySelGun(gun_index); //jerry add
+                    }
+                    break;
+
+                case Timeout_SelectGun: //Jerry add
+                    if (GetTimeoutValue(pDcChargingInfo->TimeoutTimer) / uSEC_VAL >= SEL_GUN_TIMEOUT) {
+                        log_info("Timeout_SelectGun\r\n");
+                        StopGunInfoTimeoutDet(gun_index);
+                        destroySelGun(gun_index); //jerry add
+                    }
+                    break;
+                }
+            }
+            sleep(1);
+        }
+    }
+}
+
+#if 0
+void GetSystemTime()
+{
+    struct timeb csuTime;
+    struct tm *tmCSU;
+
+    ftime(&csuTime);
+    tmCSU = localtime(&csuTime.time);
+    log_info("Time : %04d-%02d-%02d %02d:%02d:%02d \n", tmCSU->tm_year + 1900,
+             tmCSU->tm_mon + 1, tmCSU->tm_mday, tmCSU->tm_hour, tmCSU->tm_min,
+             tmCSU->tm_sec);
+
+//  uint8_t date[14];
+//
+//
+//       //sprintf(&date, "%d", );
+//
+//       date[0] = '0' + ((tmCSU->tm_year + 1900) / 1000 % 10);
+
+//  date[0] = (tmCSU->tm_year + 1900) / 1000 % 10;
+//  date[1] = (tmCSU->tm_year + 1900) / 100 % 10;
+//  date[2] = (tmCSU->tm_year + 1900) / 10 % 10;
+//  date[3] = (tmCSU->tm_year + 1900) / 1 % 10;
+//
+//  date[4] = (tmCSU->tm_mon + 1) / 10 % 10;
+//  date[5] = (tmCSU->tm_mon + 1) / 1 % 10;
+//
+//  date[6] = (tmCSU->tm_mday) / 10 % 10;
+//  date[7] = (tmCSU->tm_mday) / 1 % 10;
+//
+//  date[8] = (tmCSU->tm_hour) / 10 % 10;
+//  date[9] = (tmCSU->tm_hour) / 1 % 10;
+//
+//  date[10] = (tmCSU->tm_min) / 10 % 10;
+//  date[11] = (tmCSU->tm_min) / 1 % 10;
+//
+//  date[12] = (tmCSU->tm_sec) / 10 % 10;
+//  date[13] = (tmCSU->tm_sec) / 1 % 10;
+
+//  log_info("%x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x \n", date[0], date[1], date[2], date[3],
+//          date[4], date[5], date[6], date[7],
+//          date[8], date[9], date[10], date[11],
+//          date[12], date[13]);
+}
+#endif //0
+
+void CheckFactoryConfigFunction(void)
+{
+    char Buf[256] = {0};
+
+    if (pSysInfo->FactoryConfiguration) {
+        sprintf(Buf, "cd /root;./FactoryConfig -m %s %s",
+                pSysConfig->ModelName,
+                pSysConfig->SerialNumber);
+        system(Buf);
+
+        system("rm -f /Storage/OCPP/OCPPConfiguration");
+        system("sync");
+        sleep(5);
+        system("reboot -f");
+        sleep(5);
+        system("reboot -f");
+    }
+}
+
+#if 0
+void CheckFwUpdateFunction()
+{
+    //log_info("pSysInfo->FirmwareUpdate = %d \n", pSysInfo->FirmwareUpdate);
+    if (pSysInfo->FirmwareUpdate == YES) {
+        log_info("ftp : update start. \n");
+        for (uint8_t gun_index = 0; gun_index < pSysConfig->TotalConnectorCount; gun_index++) {
+            setChargerMode(gun_index, MODE_UPDATE);
+        }
+
+        uint8_t updateResult = CheckUpdateProcess();
+
+        if (updateResult == PASS) {
+            log_info("ftp : update complete. \n");
+        } else if (updateResult == MODELNAME_FAIL) {
+            log_info("ftp : model name is none match. \n");
+            KillAllTask();
+            pSysInfo->FirmwareUpdate = NO;
+            sleep(5);
+            system("/usr/bin/run_evse_restart.sh");
+            return;
+        } else {
+            log_info("ftp : update fail. \n");
+        }
+
+        pSysInfo->FirmwareUpdate = NO;
+        sleep(5);
+        system("reboot -f");
+    } else if (ShmOCPP16Data->MsMsg.bits.UpdateFirmwareReq == YES) {
+        ShmOCPP16Data->MsMsg.bits.UpdateFirmwareReq = NO;
+
+        if (strcmp((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "Downloaded") == EQUAL) {
+            log_info("Backend : update start. \n");
+            strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "");
+            strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "Installing");
+            ShmOCPP16Data->SpMsg.bits.FirmwareStatusNotificationReq = YES;
+            KillTask();
+
+            for (uint8_t _index = 0; _index < pSysConfig->TotalConnectorCount; _index++) {
+                setChargerMode(_index, MODE_UPDATE);
+            }
+
+            for (uint8_t _index = 0; _index < pSysConfig->AcConnectorCount; _index++) {
+                pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(_index);
+
+                pAcChargingInfo->SystemStatus = MODE_UPDATE;
+            }
+
+            uint8_t updateResult = CheckUpdateProcess();
+
+            if (updateResult == PASS) {
+                log_info("Backend : update complete. \n");
+                strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "Installed");
+            } else if (updateResult == MODELNAME_FAIL) {
+                log_info("Backend : model name is none match. \n");
+                KillAllTask();
+                strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "InstallationFailed");
+                ShmOCPP16Data->SpMsg.bits.FirmwareStatusNotificationReq = YES;
+                sleep(5);
+                system("/usr/bin/run_evse_restart.sh");
+                return;
+            } else {
+                log_info("Backend : update fail. \n");
+                strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "InstallationFailed");
+            }
+
+            strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "Installed");
+            ShmOCPP16Data->SpMsg.bits.FirmwareStatusNotificationReq = YES;
+            sleep(5);
+            system("reboot -f");
+        }
+    }
+}
+#endif //0
+
+//===============================================
+// Check reservation date is expired
+//===============================================
+int isReservationExpired(uint8_t gun_index)
+{
+    int result = NO;
+    struct tm expiredDate;
+    struct timeb expiredTime;
+
+    if (sscanf((char *) ShmOCPP16Data->ReserveNow[gun_index].ExpiryDate,
+               "%4d-%2d-%2dT%2d:%2d:%2d", &expiredDate.tm_year,
+               &expiredDate.tm_mon, &expiredDate.tm_mday, &expiredDate.tm_hour,
+               &expiredDate.tm_min, &expiredDate.tm_sec) == 6) {
+        expiredDate.tm_year -= 1900;
+        expiredDate.tm_mon -= 1;
+
+        expiredTime.time = mktime(&expiredDate);
+        if (!CheckTimeOut(expiredTime)) {
+            result = YES;
+        }
+    }
+
+    return result;
+}
+
+//===============================================
+// OCPP
+//===============================================
+void CheckOcppStatus(void)
+{
+    bool canReset = true;
+    //bool canHardReset = true; //DS60-120 add
+
+    if (ShmOCPP16Data->SpMsg.bits.BootNotificationConf == YES) {
+        ShmOCPP16Data->SpMsg.bits.BootNotificationConf = NO;
+    }
+
+    if (ShmOCPP16Data->MsMsg.bits.ResetReq == YES) {
+        if (pSysWarning->Level != 2) {
+            for (uint8_t _index = 0; _index < pSysConfig->TotalConnectorCount; _index++) {
+                pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_index);
+
+                if (pDcChargingInfo->SystemStatus != S_IDLE &&
+                        pDcChargingInfo->SystemStatus != S_RESERVATION &&
+                        pDcChargingInfo->SystemStatus != S_MAINTAIN) {
+                    canReset = false;
+                    if (pDcChargingInfo->SystemStatus >= S_REASSIGN &&
+                            pDcChargingInfo->SystemStatus < S_TERMINATING) {
+                        //canHardReset = false;
+                        ChargingTerminalProcess(_index);
+                        //restartFlag = 1;
+                    }
+                }
+            }
+        }
+
+        if (canReset) {
+            ShmOCPP16Data->MsMsg.bits.ResetReq = NO;
+            sprintf((char *)ShmOCPP16Data->Reset.ResponseStatus, "Accepted");
+            if (strcmp((char *)ShmOCPP16Data->Reset.Type, "Hard") == EQUAL) {
+                log_error("****** Hard Reboot ****** \n");
+                ShmOCPP16Data->MsMsg.bits.ResetConf = YES;
+                sleep(3);
+                system("reboot -f");
+            } else if (strcmp((char *)ShmOCPP16Data->Reset.Type, "Soft") == EQUAL) {
+                log_error("****** Soft Reboot ****** \n");
+                ShmOCPP16Data->MsMsg.bits.ResetConf = YES;
+                sleep(3);
+                system("killall OcppBackend &");
+                KillAllTask();
+                system("/usr/bin/run_evse_restart.sh");
+            }
+        }
+    }
+}
+
+void OcppStartTransation(uint8_t gunIndex)
+{
+    uint8_t _OcppGunIndex = gunIndex;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    // 如果有 AC 槍,而現在是 DC 第二把槍進入充電
+    if (pSysConfig->AcConnectorCount == 1 && gunIndex == 1) {
+        _OcppGunIndex = 2;
+    }
+
+    if (strcmp((char *)pDcChargingInfo->StartUserId, "") == EQUAL) {
+        strcpy((char *)ShmOCPP16Data->StartTransaction[_OcppGunIndex].IdTag, (char *)ShmOCPP16Data->StartTransaction[_OcppGunIndex].IdTag);
+    } else {
+        strcpy((char *)ShmOCPP16Data->StartTransaction[_OcppGunIndex].IdTag, (char *)pDcChargingInfo->StartUserId);
+    }
+
+    log_info("IdTag = %s \n", ShmOCPP16Data->StartTransaction[_OcppGunIndex].IdTag);
+    ShmOCPP16Data->CpMsg.bits[_OcppGunIndex].StartTransactionReq = YES;
+}
+
+void OcppStopTransation(uint8_t gunIndex)
+{
+    uint8_t _OcppGunIndex = gunIndex;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    // 如果有 AC 槍,而現在是 DC 第二把槍進入充電
+    if (pSysConfig->AcConnectorCount == 1 && gunIndex == 1) {
+        _OcppGunIndex = 2;
+    }
+
+    if (strcmp((char *)pDcChargingInfo->StartUserId, "") == EQUAL) {
+        strcpy((char *)ShmOCPP16Data->StopTransaction[_OcppGunIndex].IdTag, (char *)ShmOCPP16Data->StopTransaction[_OcppGunIndex].IdTag);
+    } else {
+        strcpy((char *)ShmOCPP16Data->StopTransaction[_OcppGunIndex].IdTag, (char *)pDcChargingInfo->StartUserId);
+    }
+
+    log_info("IdTag = %s \n", ShmOCPP16Data->StopTransaction[_OcppGunIndex].IdTag);
+    ShmOCPP16Data->CpMsg.bits[_OcppGunIndex].StopTransactionReq = YES;
+}
+
+bool OcppRemoteStop(uint8_t gunIndex)
+{
+    uint8_t acDirIndex = pSysConfig->AcConnectorCount;
+
+    // 有 AC 槍的話
+    if (acDirIndex > 0 && gunIndex > 0) {
+        gunIndex += acDirIndex;
+    }
+
+    bool result = ShmOCPP16Data->CsMsg.bits[gunIndex].RemoteStopTransactionReq;
+
+    if (ShmOCPP16Data->CsMsg.bits[gunIndex].RemoteStopTransactionReq == YES) {
+        strcpy((char *)ShmOCPP16Data->StopTransaction[gunIndex].StopReason, "Remote");
+        ShmOCPP16Data->CsMsg.bits[gunIndex].RemoteStopTransactionReq = NO;
+    }
+
+    return result;
+}
+
+bool WifiScheduleStop(uint8_t gunIndex)
+{
+    bool result = false;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    result = pDcChargingInfo->schedule.isTriggerStop;
+    pDcChargingInfo->schedule.isTriggerStop = NO;
+
+    return result;
+}
+
+void OcppRemoteStartChk()
+{
+    if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_NO_CHARGING)
+    {}
+    else if (!isDetectPlugin()) {
+        // 如果有 AC 槍,則固定是第 2 把槍,所以索引固定為 1
+        uint8_t acDirIndex = pSysConfig->AcConnectorCount;
+
+        for (uint8_t ac_index = 0; ac_index < pSysConfig->AcConnectorCount; ac_index++) {
+            pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(ac_index);
+
+            if (ShmOCPP16Data->CsMsg.bits[acDirIndex].RemoteStartTransactionReq == YES) {
+                if (pAcChargingInfo->SystemStatus == S_IDLE ||
+                        pAcChargingInfo->SystemStatus == S_RESERVATION) {
+                    ShmOCPP16Data->CsMsg.bits[acDirIndex].RemoteStartTransactionReq = NO;
+                    pAcChargingInfo->RemoteStartFlag = YES;
+                    pSysInfo->OrderCharging = YES;
+                    //pSysInfo->OrderCharging = DEFAULT_AC_INDEX;
+                    ShmOCPP16Data->CsMsg.bits[pSysConfig->TotalConnectorCount + ac_index].RemoteStartTransactionReq = NO;
+                    DetectPluginStart();
+                    return;
+                }
+                ShmOCPP16Data->CsMsg.bits[acDirIndex].RemoteStartTransactionReq = NO;
+            }
+        }
+
+        uint8_t threeGunIndex = 0;
+        uint8_t dcIndex = 0;
+        bool isGunUsingStatus = false;
+
+        for (uint8_t _index = 0; _index < pSysConfig->TotalConnectorCount; _index++) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_index);
+
+            // 如果有 AC 槍,且 DC 槍也有兩把
+            if (acDirIndex == 1 && _index == 1) {
+                threeGunIndex = 1;
+            }
+
+            if (ShmOCPP16Data->CsMsg.bits[_index + threeGunIndex].RemoteStartTransactionReq == YES) {
+                dcIndex = _index;
+            }
+
+            if (pDcChargingInfo->SystemStatus != S_IDLE) {
+                isGunUsingStatus = true;
+            }
+        }
+
+        // 如果是雙槍單模,只認閒置狀態的槍,如果有預約~ 則預約也算被使用
+        if (isGunUsingStatus && pSysInfo->IsAlternatvieConf) {
+            if (dcIndex == 0) {
+                threeGunIndex = 0;
+            }
+
+            ShmOCPP16Data->CsMsg.bits[dcIndex + threeGunIndex].RemoteStartTransactionReq = NO;
+            return;
+        }
+
+        if (dcIndex == 0) {
+            threeGunIndex = 0;
+        }
+
+        pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(dcIndex);
+
+        if (ShmOCPP16Data->CsMsg.bits[dcIndex + threeGunIndex].RemoteStartTransactionReq == YES) {
+            if (pDcChargingInfo->SystemStatus == S_IDLE ||
+                    pDcChargingInfo->SystemStatus == S_RESERVATION) {
+                pDcChargingInfo->RemoteStartFlag = YES;
+                pSysInfo->OrderCharging = YES;
+                //pSysInfo->OrderCharging = gun_index;
+                ShmOCPP16Data->CsMsg.bits[dcIndex + threeGunIndex].RemoteStartTransactionReq = NO;
+                DetectPluginStart();
+#if defined DD360Audi
+                setSelGunWaitToAuthor(dcIndex); //Jerry add
+#endif //defined DD360Audi
+            }
+            ShmOCPP16Data->CsMsg.bits[dcIndex + threeGunIndex].RemoteStartTransactionReq = NO;
+        }
+    }
+}
+
+void ChkOcppStatus(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (pDcChargingInfo->SystemStatus == S_IDLE &&
+            ShmOCPP16Data->CsMsg.bits[gunIndex].ReserveNowReq == YES) {
+        ShmOCPP16Data->CsMsg.bits[gunIndex].ReserveNowReq = NO;
+        if (isReservationExpired(gunIndex)) {
+            log_info("***************ChkOcppStatus : OcppReservedStatus******************** \n");
+            log_error("***************ChkOcppStatus : OcppReservedStatus******************** \n");
+            pDcChargingInfo->ReservationId = ShmOCPP16Data->ReserveNow[gunIndex].ReservationId;
+            pDcChargingInfo->SystemStatus = S_RESERVATION;
+        }
+        ShmOCPP16Data->CsMsg.bits[gunIndex].ReserveNowConf = YES;
+    }
+
+    if (pDcChargingInfo->SystemStatus == S_RESERVATION &&
+            ShmOCPP16Data->CsMsg.bits[gunIndex].CancelReservationReq == YES) {
+        ShmOCPP16Data->CsMsg.bits[gunIndex].CancelReservationReq = NO;
+        if (isReservationExpired(gunIndex)) {
+            log_info("***************ChkOcppStatus : Cancel OcppReservedStatus******************** \n");
+            log_error("***************ChkOcppStatus : Cancel OcppReservedStatus******************** \n");
+            pDcChargingInfo->ReservationId = 0;
+            pDcChargingInfo->SystemStatus = S_IDLE;
+        }
+        ShmOCPP16Data->CsMsg.bits[gunIndex].CancelReservationConf = YES;
+    }
+
+    if (ShmOCPP16Data->CsMsg.bits[gunIndex].ChangeAvailabilityReq == YES) {
+        log_info("***************ChkOcppStatus : OcppChangeAvailability******************** \n");
+        log_error("***************ChkOcppStatus : OcppChangeAvailability******************** \n");
+        ShmOCPP16Data->CsMsg.bits[gunIndex].ChangeAvailabilityReq = NO;
+        if (strcmp((char *)ShmOCPP16Data->ChangeAvailability[gunIndex].Type, "Operative") == EQUAL) {
+            if (isDb_ready) {
+                DB_Update_Operactive(gunIndex, true);
+            }
+
+            pDcChargingInfo->IsAvailable = YES;
+            if (pDcChargingInfo->SystemStatus == S_IDLE ||
+                    pDcChargingInfo->SystemStatus == S_RESERVATION ||
+                    pDcChargingInfo->SystemStatus == S_MAINTAIN) {
+                setChargerMode(gunIndex, MODE_IDLE);
+            }
+        } else if (strcmp((char *)ShmOCPP16Data->ChangeAvailability[gunIndex].Type, "Inoperative") == EQUAL) {
+            if (isDb_ready) {
+                DB_Update_Operactive(gunIndex, false);
+            }
+
+            pDcChargingInfo->IsAvailable = NO;
+            if (pDcChargingInfo->SystemStatus == S_IDLE ||
+                    pDcChargingInfo->SystemStatus == S_RESERVATION ||
+                    pDcChargingInfo->SystemStatus == S_MAINTAIN) {
+                setChargerMode(gunIndex, MODE_MAINTAIN);
+            }
+        }
+    }
+
+    if (ShmOCPP16Data->CsMsg.bits[gunIndex].UnlockConnectorReq == YES) {
+        ShmOCPP16Data->CsMsg.bits[gunIndex].UnlockConnectorReq = NO;
+        if (pDcChargingInfo->SystemStatus >= S_REASSIGN_CHECK && // DS60-120 add ||
+                pDcChargingInfo->SystemStatus <= S_CHARGING) {
+            // 充電中,需停止充電
+            strcpy((char *)ShmOCPP16Data->StopTransaction[gunIndex].StopReason, "UnlockCommand");
+            ChargingTerminalProcess(gunIndex);
+        }
+        strcpy((char *)ShmOCPP16Data->UnlockConnector[gunIndex].ResponseStatus, "Unlocked");
+        ShmOCPP16Data->CsMsg.bits[gunIndex].UnlockConnectorConf = YES;
+    }
+}
+
+bool CheckBackendChargingTimeout(uint8_t gunIndex)
+{
+    bool result = false;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (pSysConfig->AuthorisationMode == AUTH_MODE_ENABLE) {
+        if (pSysConfig->MaxChargingDuration > 0) {
+            if (pDcChargingInfo->PresentChargedDuration > (pSysConfig->MaxChargingDuration * 60)) {
+                result = true;
+            }
+        }
+    } else if (pSysConfig->AuthorisationMode == AUTH_MODE_DISABLE) {
+        // 隨插即充電的要看 offline
+        if (pSysConfig->OfflineMaxChargeDuration > 0) {
+            if (pDcChargingInfo->PresentChargedDuration > (pSysConfig->OfflineMaxChargeDuration * 60)) {
+                result = true;
+            }
+        }
+    }
+
+    return result;
+}
+
+bool CheckBackendChargingEnergy(uint8_t gunIndex)
+{
+    bool result = false;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (pSysConfig->AuthorisationMode == AUTH_MODE_ENABLE) {
+        if (pSysConfig->MaxChargingEnergy > 0) {
+            if (pDcChargingInfo->PresentChargedEnergy > pSysConfig->MaxChargingEnergy) {
+                result = true;
+            }
+        }
+    } else if (pSysConfig->AuthorisationMode == AUTH_MODE_DISABLE) {
+        // 隨插即充電的要看 offline
+        if (pSysConfig->OfflineMaxChargeEnergy > 0) {
+            if (pDcChargingInfo->PresentChargedEnergy > (pSysConfig->OfflineMaxChargeEnergy)) {
+                result = true;
+            }
+        }
+    }
+
+    return result;
+}
+
+void InformOcppErrOccur(uint8_t codeType)
+{
+    char _error[25];
+
+    switch (codeType) {
+    case 4: strcpy(_error, "InternalError"); break;
+    case 6: strcpy(_error, "NoError"); break;
+    case 7: strcpy(_error, "OtherError"); break;
+    case 13: strcpy(_error, "UnderVoltage"); break;
+    case 14: strcpy(_error, "OverVoltage"); break;
+    }
+
+    for (uint8_t gun_index = 0; gun_index < pSysConfig->TotalConnectorCount; gun_index++) {
+        strcpy((char *)ShmOCPP16Data->StatusNotification[gun_index].ErrorCode, _error);
+    }
+}
+
+#if 0
+//===============================================
+// SQLite3 related routine
+//===============================================
+int DB_Open(sqlite3 *db)
+{
+    int result = PASS;
+    char *errMsg = NULL;
+    char *createRecordSql = "CREATE TABLE IF NOT EXISTS charging_record("
+                            "idx integer primary key AUTOINCREMENT, "
+                            "reservationId text, "
+                            "transactionId text, "
+                            "startMethod text, "
+                            "userId text, "
+                            "dateTimeStart text, "
+                            "dateTimeStop text,"
+                            "socStart text, "
+                            "socStop text, "
+                            "chargeEnergy text, "
+                            "stopReason text"
+                            ");";
+
+    /*char *createCfgSql = "CREATE TABLE IF NOT EXISTS `config` ( "
+                         "`idx` INTEGER PRIMARY KEY AUTOINCREMENT, "
+                         "`IsAvailable` TEXT NOT NULL, "
+                         "`connector` INTEGER NOT NULL, "
+                         "`val` TEXT NOT NULL, unique(IsAvailable,connector) on conflict replace);";
+    */
+    //DS60-120 add
+    char *createCfgSql = "CREATE TABLE IF NOT EXISTS `config` ( "
+                         "`idx` INTEGER PRIMARY KEY AUTOINCREMENT, "
+                         "`item` TEXT NOT NULL, "
+                         "`connector` INTEGER NOT NULL, "
+                         "`val` TEXT NOT NULL, unique(item,connector) on conflict replace);";
+
+    char *createrecordSql = "CREATE TABLE IF NOT EXISTS `event_record` ( "
+                            "`idx` INTEGER PRIMARY KEY AUTOINCREMENT, "
+                            "`occurDatetime` TEXT NOT NULL, "
+                            "`statusCode` TEXT NOT NULL, unique(occurDatetime,statusCode) on conflict replace);";
+
+    char *createrebootSql = "CREATE TABLE IF NOT EXISTS `reboot_record` ( "
+                            "`idx` INTEGER PRIMARY KEY AUTOINCREMENT, "
+                            "`rebootDatetime` TEXT NOT NULL, unique(rebootDatetime) on conflict replace);";
+
+    if (sqlite3_open(DB_FILE, &db)) {
+        result = FAIL;
+        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(db));
+        sqlite3_close(db);
+    } else {
+        log_info( "Local charging record database open successfully.\r\n");
+
+        if (sqlite3_exec(db, createRecordSql, 0, 0, &errMsg) != SQLITE_OK) {
+            result = FAIL;
+            log_info( "Create local charging record table error message: %s\n", errMsg);
+        } else {
+            log_info( "Opened local charging record table successfully\n");
+        }
+
+        if (sqlite3_exec(db, createCfgSql, 0, 0, &errMsg) != SQLITE_OK) {
+            result = FAIL;
+            log_info( "Create local config table error message: %s\n", errMsg);
+        } else {
+            log_info( "Opened local config table successfully\n");
+        }
+
+        //DS60-120
+        if (sqlite3_exec(db, createrecordSql, 0, 0, &errMsg) != SQLITE_OK) {
+            result = FAIL;
+            log_info( "Create local record table error message: %s\n", errMsg);
+        } else {
+            log_info( "Opened local record table successfully\n");
+        }
+
+        if (sqlite3_exec(db, createrebootSql, 0, 0, &errMsg) != SQLITE_OK) {
+            result = FAIL;
+            log_info( "Create reboot record table error message: %s\n", errMsg);
+        } else {
+            log_info( "Opened reboot record table successfully\n");
+        }
+        //-----
+
+        sqlite3_close(db);
+    }
+
+    return result;
+}
+
+int DB_Insert_Record(sqlite3 *db, int gun_index)
+{
+    int result = PASS;
+    char *errMsg = NULL;
+    char insertSql[1024];
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun_index);
+
+    sprintf(insertSql, "insert into charging_record(reservationId, transactionId, startMethod, userId, dateTimeStart, dateTimeStop, socStart, socStop, chargeEnergy, stopReason) "
+            "values('%d', '%d', '%d', '%s', '%s', '%s', '%d', '%d', '%f', '%s');",
+            pDcChargingInfo->ReservationId, //DS60-120 add
+            ShmOCPP16Data->StartTransaction[gun_index].ResponseTransactionId,
+            pDcChargingInfo->StartMethod,
+            pDcChargingInfo->StartUserId,
+            pDcChargingInfo->StartDateTime,
+            pDcChargingInfo->StopDateTime,
+            pDcChargingInfo->EvBatteryStartSoc,
+            pDcChargingInfo->EvBatterySoc,
+            pDcChargingInfo->PresentChargedEnergy,
+            //DS60-120 remove
+            //pSysInfo->AcChargingData[gun_index].ReservationId,
+            //ShmOCPP16Data->StartTransaction[gun_index].ResponseTransactionId,
+            //pSysInfo->AcChargingData[gun_index].StartMethod,
+            //pSysInfo->AcChargingData[gun_index].StartUserId,
+            //pSysInfo->AcChargingData[gun_index].StartDateTime,
+            //pSysInfo->AcChargingData[gun_index].StopDateTime,
+            //pSysInfo->AcChargingData[gun_index].EvBatterySoc,
+            //pSysInfo->AcChargingData[gun_index].EvBatterySoc,
+            //pSysInfo->AcChargingData[gun_index].PresentChargedEnergy,
+            ShmOCPP16Data->StopTransaction[gun_index].StopReason);
+
+    //if (sqlite3_open("/Storage/ChargeLog/localCgargingRecord.db", &db)) {
+    if (sqlite3_open(DB_FILE, &db)) { //DS60-120 add
+        result = FAIL;
+        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(db));
+        sqlite3_close(db);
+    } else {
+        log_info( "Local charging record database open successfully.\r\n");
+        if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
+            result = FAIL;
+            log_info( "Insert local charging record error message: %s\n", errMsg);
+        } else {
+            log_info( "Insert local charging record successfully\n");
+        }
+
+        //DS60-120 add
+        sprintf(insertSql, "delete from charging_record where idx < (select idx from charging_record order by idx desc limit 1)-2000;");
+        if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
+            result = FAIL;
+            log_info( "delete local charging error message: %s\n", errMsg);
+        } else {
+            log_info( "delete local charging record successfully\n");
+        }
+
+        sqlite3_close(db);
+    }
+
+    return result;
+}
+
+int DB_Update_Operactive(sqlite3 *db, uint8_t gun_index, uint8_t IsAvailable)
+{
+    uint8_t result = false;
+    char *errMsg = NULL;
+    char sqlStr[1024];
+    srand(time(NULL));
+
+    if (sqlite3_open(DB_FILE, &db)) {
+        result = FAIL;
+        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(db));
+        sqlite3_close(db);
+    } else {
+        log_info( "Local charging record database open successfully (%d).\r\n", IsAvailable);
+
+        //sprintf(sqlStr, "insert or replace into config (IsAvailable, connector, val) values('IsAvailable', %d, %d);", gun_index, IsAvailable);
+        sprintf(sqlStr, "insert or replace into config (item, connector, val) values('IsAvailable', %d, %d);", gun_index, IsAvailable); //DS60-120 add
+        log_info("sqlStr= %s\r\n", sqlStr);
+        if (sqlite3_exec(db, sqlStr, 0, 0, &errMsg) != SQLITE_OK) {
+            result = FAIL;
+            log_info( "update config error message: %s\n", errMsg);
+        } else {
+            log_info("update connector-%d config item isOperactive to %d\r\n", gun_index, IsAvailable);
+        }
+
+        sqlite3_close(db);
+    }
+
+    return result;
+}
+
+int DB_Get_Operactive(sqlite3 *db, uint8_t gun_index)
+{
+    uint8_t result = true;
+    char *errMsg = NULL;
+    char sqlStr[1024];
+    char **rs;
+    int  rows, cols;
+
+    //sprintf(sqlStr, "select * from config where IsAvailable='IsAvailable' and connector=%d;", gun_index);
+    sprintf(sqlStr, "select * from config where item='IsAvailable' and connector=%d;", gun_index); //DS60-120 add
+    //DEBUG_INFO("sqlStr= %s\r\n", sqlStr);
+
+    if (sqlite3_open(DB_FILE, &db)) {
+        result = FAIL;
+        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(db));
+        sqlite3_close(db);
+    } else {
+        log_info( "Local config query database open successfully.\r\n");
+        sqlite3_get_table(db, sqlStr, &rs, &rows, &cols, &errMsg);
+        if (rows > 0) {
+            for (int idxRow = 1; idxRow <= rows; idxRow++) {
+                if (strcmp(rs[(idxRow * cols) + 3], "0") == 0) {
+                    result = false;
+                }
+                log_info("Query connector-%d isOperactive: %s\r\n", gun_index, rs[(idxRow * cols) + 3]);
+            }
+        } else {
+            log_info("Query connector-%d fail, set default value to operactive.\r\n", gun_index);
+        }
+
+        sqlite3_free_table(rs);
+        sqlite3_close(db);
+    }
+
+    return result;
+}
+
+int DB_Reboot_Record(sqlite3 *db)
+{
+    int result = PASS;
+    char *errMsg = NULL;
+    char insertSql[256];
+
+    sprintf(insertSql, "insert into reboot_record(rebootDatetime) values(CURRENT_TIMESTAMP);");
+
+    if (sqlite3_open(DB_FILE, &db)) {
+        result = FAIL;
+        log_info( "Can't open database: %s\n", sqlite3_errmsg(db));
+        sqlite3_close(db);
+    } else {
+        log_info( "Local charging record database open successfully.\n");
+        if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
+            result = FAIL;
+            log_info( "Insert reboot record error message: %s\n", errMsg);
+        } else {
+            log_info( "Insert reboot record successfully\n");
+        }
+
+        sprintf(insertSql, "delete from reboot_record where idx < (select idx from charging_record order by idx desc limit 1)-2000;");
+        if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
+            result = FAIL;
+            log_info( "delete reboot record error message: %s\n", errMsg);
+        } else {
+            log_info( "delete reboot record successfully\n");
+        }
+
+        sqlite3_close(db);
+    }
+
+    return result;
+}
+#endif //0
+
+//===============================================
+// Config process
+//===============================================
+void AddPlugInTimes(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (pDcChargingInfo->Type == _Type_Chademo) {
+        pSysConfig->ChademoPlugInTimes += 1;
+    } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+        pSysConfig->Ccs2PlugInTimes += 1;
+    } else if (pDcChargingInfo->Type == _Type_GB) {
+        pSysConfig->GbPlugInTimes += 1;
+    }
+}
+
+void ChangeStartOrStopDateTime(uint8_t isStart, uint8_t gunIndex)
+{
+    char cmdBuf[32];
+    struct timeb csuTime;
+    struct tm *tmCSU;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    ftime(&csuTime);
+    tmCSU = localtime(&csuTime.time);
+
+    sprintf(cmdBuf, "%04d-%02d-%02d %02d:%02d:%02d", tmCSU->tm_year + 1900,
+            tmCSU->tm_mon + 1, tmCSU->tm_mday, tmCSU->tm_hour, tmCSU->tm_min,
+            tmCSU->tm_sec);
+    if (isStart) {
+        strcpy((char *)pDcChargingInfo->StartDateTime, cmdBuf);
+    } else {
+        strcpy((char *)pDcChargingInfo->StopDateTime, cmdBuf);
+    }
+}
+
+#if 0
+void zipLogFiles()
+{
+    const char *logPath = "/Storage/SystemLog";
+    // 獲取目錄
+    DIR *pDir = opendir(logPath);
+    if (pDir != NULL) {
+        struct timeb csuTime;
+        struct tm *tmCSU;
+
+        ftime(&csuTime);
+        tmCSU = localtime(&csuTime.time);
+//      log_info("Time : %04d-%02d-%02d %02d:%02d:%02d \n", tmCSU->tm_year + 1900,
+//          tmCSU->tm_mon + 1, tmCSU->tm_mday, tmCSU->tm_hour, tmCSU->tm_min,
+//          tmCSU->tm_sec);
+
+        // Read items inside the folder
+        struct dirent *pEntry = NULL;
+        while ((pEntry = readdir(pDir)) != NULL) {
+            if (strcmp(pEntry->d_name, ".") != 0 &&
+                    strcmp(pEntry->d_name, "..") != 0 &&
+                    strncmp(pEntry->d_name, "[", 1) == 0 &&
+                    strstr(pEntry->d_name, "tar") < 0) {
+                char yearC[5];
+                unsigned short year = 0;
+                char monthC[3];
+                unsigned short month = 0;
+
+                yearC[4] = '\0';
+                strncpy(yearC, pEntry->d_name + 1, 4);
+                monthC[2] = '\0';
+                strncpy(monthC, pEntry->d_name + 6, 2);
+
+                year = atoi(yearC);
+                month = atoi(monthC);
+
+                if (year != 0) {
+                    if (year < tmCSU->tm_year + 1900 ||
+                            (year >= tmCSU->tm_year + 1900 && month < tmCSU->tm_mon + 1)) {
+                        log_info("tar file name : %s \n", pEntry->d_name);
+                        char file[256];
+
+                        memset(file, 0x00, sizeof(file));
+                        strcat(file, "tar zcvf ");
+                        strcat(file, logPath);
+                        strncat(file, "/", 1);
+                        strcat(file, pEntry->d_name);
+                        strcat(file, ".tar");
+                        strncat(file, " ", 1);
+                        strcat(file, logPath);
+                        strncat(file, "/", 1);
+                        strcat(file, pEntry->d_name);
+                        log_info("zip = %s \n", file);
+                        system(file);
+                    }
+                }
+            }
+        }
+    }
+    // Close folder
+    closedir(pDir);
+}
+#endif //0
+
+void ChangeGunSelectByIndex(uint8_t sel)
+{
+    pSysInfo->CurGunSelected = sel;
+    pSysInfo->CurGunSelectedByAc = NO_DEFINE;
+}
+
+void CheckIsAlternatvieByModelName()
+{
+    // 黑白機 ?
+    /*if (strcmp((char *)pSysConfig->ModelName, "DWWU301J0UT1PH") == EQUAL ||
+            strcmp((char *)pSysConfig->ModelName, "DWYE301J0ET1PH") == EQUAL ||
+            strcmp((char *)pSysConfig->ModelName, "DSYE301J3EW2PH") == EQUAL ||
+            strcmp((char *)pSysConfig->ModelName, "DWYC301J0UW1PH") == EQUAL) {
+      */
+    if (pSysConfig->ModelName[1] == 'W') { //DS60-120
+        // 壁掛
+        pSysInfo->IsAlternatvieConf = YES;
+    } else {
+        pSysInfo->IsAlternatvieConf = NO;
+    }
+}
+
+void StopProcessingLoop()
+{
+    for (;;) {
+        CheckFactoryConfigFunction();
+        CheckFwUpdateFunction();
+        if (pSysWarning->Level == 2) {
+            ChkPrimaryStatus();
+            if (pSysWarning->Level == 0) {
+                log_info("Soft reboot for retry self-tets (Primary). \n");
+                KillAllTask();
+                sleep(3);
+                system("/usr/bin/run_evse_restart.sh");
+                return;
+            }
+        }
+        sleep(1);
+    }
+}
+
+#if 0
+int InitWatchDog(void)
+{
+    int fd;
+    system("/usr/bin/fuser -k /dev/watchdog");
+    sleep(1);
+    system("echo V > /dev/watchdog");
+    sleep(1);
+    fd = open("/dev/watchdog", O_RDWR);
+
+    if (fd <= 0) {
+        log_error("System watch dog initial fail.\r\n");
+    }
+    return fd;
+}
+
+void CreateWatchdog(void)
+{
+    if (pSysConfig->SwitchDebugFlag == NO) {
+        wtdFd = InitWatchDog();
+
+        if (wtdFd < 0) {
+            pAlarmCode->AlarmEvents.bits.CsuInitFailed = 1;
+        }
+    }
+}
+#endif //0
+
+bool IsConnectorWholeIdle()
+{
+    bool result = true;
+
+    for (uint8_t count = 0; count < pSysConfig->TotalConnectorCount; count++) {
+        pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(count);
+
+        if (pDcChargingInfo->SystemStatus != S_IDLE &&
+                pDcChargingInfo->SystemStatus != S_RESERVATION) {
+            result = false;
+            break;
+        }
+    }
+
+    for (uint8_t count = 0; count < pSysConfig->AcConnectorCount; count++) {
+        pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(count);
+
+        if (pAcChargingInfo->SystemStatus != S_IDLE &&
+                pAcChargingInfo->IsErrorOccur == NO) {
+            result = false;
+            break;
+        }
+    }
+
+    return result;
+}
+
+void ClearAlarmCodeWhenAcOff()
+{
+    if (!pSysInfo->AcContactorStatus) {
+        pAlarmCode->AlarmEvents.bits.PsuNoResource = NO;
+    }
+}
+
+//==========================================
+// Check task processing
+//==========================================
+void CheckTask()
+{
+    /*+++ 20200908, vern, disable it for DD360 +++*/
+#if 0
+    if (pSysConfig->ModelName[10] == 'T') {
+        if (system("pidof -s Module_4g > /dev/null") != 0) {
+            log_error("Module_4g not running, restart it.\r\n");
+            system("/root/Module_4g &");
+        }
+    } else if (pSysConfig->ModelName[10] == 'W') {
+        if (system("pidof -s Module_Wifi > /dev/null") != 0) {
+            log_error("Module_Wifi not running, restart it.\r\n");
+            system("/root/Module_Wifi &");
+        }
+    }
+
+    if (strcmp((char *)pSysConfig->OcppServerURL, "") != EQUAL &&
+            strcmp((char *)pSysConfig->ChargeBoxId, "") != EQUAL) {
+        if (system("pidof -s OcppBackend > /dev/null") != 0) {
+            log_error("OcppBackend not running, restart it.\r\n");
+            system("/root/OcppBackend &");
+        }
+    }
+#endif
+    /*--- 20200908, vern, disable it for DD360 ---*/
+    if (system("pidof -s Module_ProduceUtils > /dev/null") != 0) {
+        log_error("Module_ProduceUtils not running, restart it.\r\n");
+        system ("/root/Module_ProduceUtils &");
+    }
+}
+
+void InitialDHCP()
+{
+    char tmpbuf[256] = {0};
+
+    system("pgrep -f \"udhcpc -i eth0\" | xargs kill");
+    sprintf(tmpbuf, "/sbin/udhcpc -i eth0 -x hostname:CSU3_%s -s /root/dhcp_script/eth0.script > /dev/null &",
+            pSysConfig->SystemId);
+    system(tmpbuf);
+}
+
+//==========================================
+// Check Smart Charging Profile
+//==========================================
+int GetStartScheduleTime(uint8_t *time)
+{
+    int result = -1;
+    struct tm tmScheduleStart;
+    struct timeb tbScheduleStart;
+
+    if ((sscanf((char *)time, "%4d-%2d-%2dT%2d:%2d:%2d", &tmScheduleStart.tm_year, &tmScheduleStart.tm_mon, &tmScheduleStart.tm_mday, &tmScheduleStart.tm_hour, &tmScheduleStart.tm_min, &tmScheduleStart.tm_sec) == 6)) {
+        tmScheduleStart.tm_year -= 1900;
+        tmScheduleStart.tm_mon -= 1;
+        tbScheduleStart.time = mktime(&tmScheduleStart);
+        tbScheduleStart.millitm = 0;
+
+        result = DiffTimebWithNow(tbScheduleStart) / 1000;
+    }
+
+    return result;
+}
+
+void CheckSmartChargeProfile(uint8_t _index)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_index);
+
+    if (ShmOCPP16Data->CSUMsg.bits[_index].ChargingProfileConf == YES) {
+        // Get Charging Profile
+        ShmOCPP16Data->CSUMsg.bits[_index].ChargingProfileConf = NO;
+        if (strcmp((char *)ShmOCPP16Data->SmartChargingProfile[_index].ChargingProfileKind, "Absolute") == EQUAL &&
+                ShmOCPP16Data->SmartChargingProfile[_index].ChargingProfileId == YES //DS60-120 add
+           ) {
+            int _time = GetStartScheduleTime(ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.StartSchedule);
+            uint8_t _startCount = NO_DEFINE;
+            uint8_t _maxCount = ARRAY_SIZE(ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod);
+
+            for (uint8_t _count = 0; _count < _maxCount; _count++) {
+                // 預設最小輸出電流 (MIN_OUTPUT_CUR) A
+                if (_time >= ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_count].StartPeriod) {
+                    if ((_count == 0 && ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_count].Limit >= MIN_OUTPUT_CUR) ||
+                            ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_count].Limit > MIN_OUTPUT_CUR) {
+                        _startCount = _count;
+                    }
+                }
+            }
+
+            log_info("_startCount = %d \n", _startCount);
+            if (_startCount < _maxCount) {
+                //DS60-120 add
+                log_info("Profile Limit = %f \n", ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_startCount].Limit);
+                pDcChargingInfo->ChargingProfilePower = ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_startCount].Limit * AC_OUTPUT_VOL;
+                if (pDcChargingInfo->EvBatterytargetVoltage > 0 && pDcChargingInfo->PresentChargingVoltage > 0) {
+                    pDcChargingInfo->ChargingProfileCurrent = (pDcChargingInfo->ChargingProfilePower / pDcChargingInfo->PresentChargingVoltage) * 10;
+                } else {
+                    pDcChargingInfo->ChargingProfileCurrent = 0;
+                }
+
+                //DS60-120 remove
+                //log_info("*********Limit = %f \n", ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_startCount].Limit);
+                //pDcChargingInfo->ChargingProfileCurrent = ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_startCount].Limit * 10;
+                //pDcChargingInfo->ChargingProfilePower = ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_startCount].Limit * pDcChargingInfo->EvBatterytargetVoltage / 100;
+
+                //pDcChargingInfo->ChargingProfilePower = ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_startCount].Limit * AC_OUTPUT_VOL;
+//              if ((pDcChargingInfo->EvBatterytargetVoltage * 10) > 0)
+//              {
+//                  pDcChargingInfo->ChargingProfileCurrent = pDcChargingInfo->ChargingProfilePower / (pDcChargingInfo->EvBatterytargetVoltage * 10);
+//              }
+            } else {
+                pDcChargingInfo->ChargingProfilePower = -1;
+                pDcChargingInfo->ChargingProfileCurrent = -1;
+            }
+        } else {
+            pDcChargingInfo->ChargingProfilePower = -1;
+            pDcChargingInfo->ChargingProfileCurrent = -1;
+        }
+
+        log_info("ChargingProfilePower = %f \n", pDcChargingInfo->ChargingProfilePower);
+        log_info("ChargingProfileCurrent = %f \n", pDcChargingInfo->ChargingProfileCurrent);
+    }
+//
+//      printf("-------------Schedule------------\n");
+//      printf("index = %d \n", _index);
+//      printf("StartSchedule = %s \n", ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.StartSchedule);
+//      printf("ChargingRateUnit = %s \n", ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingRateUnit);
+//      printf("----------SchedulePeriod---------\n");
+//      for (int v = 0; v < 10; v++)
+//      {
+//          printf("StartPeriod = %d \n", ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[v].StartPeriod);
+//          printf("Limit = %f \n", ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[v].Limit);
+//      }
+//      printf("---------------------------------\n");
+}
+
+void ChargingProfileFlat(uint8_t _index)
+{
+    if (ShmOCPP16Data->CSUMsg.bits[_index].ChargingProfileConf == NO) {
+        if (ShmOCPP16Data->CSUMsg.bits[_index].ChargingProfileReq == NO) {
+            ShmOCPP16Data->CSUMsg.bits[_index].ChargingProfileReq = YES;
+        }
+    }
+}
+
+void CheckReturnToChargingConn()
+{
+    if ((pSysConfig->TotalConnectorCount + pSysConfig->AcConnectorCount) > 1 &&
+            pSysInfo->PageIndex != _LCM_AUTHORIZING &&
+            pSysInfo->PageIndex != _LCM_AUTHORIZ_FAIL &&
+            pSysInfo->PageIndex != _LCM_AUTHORIZ_COMP &&
+            pSysInfo->PageIndex != _LCM_WAIT_FOR_PLUG) {
+        bool isReturnTimeout = false;
+
+        for (uint8_t count = 0; count < pSysConfig->TotalConnectorCount; count++) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(count);
+
+            // 如果選的 DC 槍在充電~ 則 DC 槍不改變
+            if (count == pSysInfo->CurGunSelected) {
+                if ((pDcChargingInfo->SystemStatus >= S_REASSIGN_CHECK && pDcChargingInfo->SystemStatus <= S_COMPLETE) ||
+                        (pDcChargingInfo->SystemStatus >= S_CCS_PRECHARGE_ST0 && pDcChargingInfo->SystemStatus <= S_CCS_PRECHARGE_ST1)) {
+                    isReturnTimeout = false;
+                    break;
+                }
+            } else if (count != pSysInfo->CurGunSelected) {
+                if ((pDcChargingInfo->SystemStatus >= S_REASSIGN_CHECK && pDcChargingInfo->SystemStatus <= S_COMPLETE) ||
+                        (pDcChargingInfo->SystemStatus >= S_CCS_PRECHARGE_ST0 && pDcChargingInfo->SystemStatus <= S_CCS_PRECHARGE_ST1)) {
+                    isReturnTimeout = true;
+                    StartSystemTimeoutDet(Timeout_ReturnToChargingGunDet);
+                }
+            }
+        }
+
+        // AC 槍
+        if (!isReturnTimeout && pSysConfig->AcConnectorCount > 0) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(pSysInfo->CurGunSelected);
+            pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(0);
+
+            // 沒有選中 AC,且 AC 在充電中
+            if (pSysInfo->CurGunSelectedByAc == NO_DEFINE &&
+                    (pAcChargingInfo->SystemStatus >= S_PREPARNING &&
+                     pAcChargingInfo->SystemStatus <= S_COMPLETE)) {
+                // 當前 DC 充電槍在 idle 狀態
+                if (pDcChargingInfo->SystemStatus == S_IDLE ||
+                        pDcChargingInfo->SystemStatus == S_RESERVATION) {
+                    isReturnTimeout = true;
+                    StartSystemTimeoutDet(Timeout_ReturnToChargingGunDet);
+                }
+            } else if (pSysInfo->CurGunSelectedByAc == DEFAULT_AC_INDEX &&
+                       ((pDcChargingInfo->SystemStatus >= S_REASSIGN_CHECK &&
+                         pDcChargingInfo->SystemStatus <= S_COMPLETE) ||
+                        (pDcChargingInfo->SystemStatus >= S_CCS_PRECHARGE_ST0 &&
+                         pDcChargingInfo->SystemStatus <= S_CCS_PRECHARGE_ST1))) {
+                // 當前 DC 充電槍在 idle 狀態
+                if (pAcChargingInfo->SystemStatus == S_IDLE ||
+                        pAcChargingInfo->SystemStatus == S_RESERVATION) {
+                    isReturnTimeout = true;
+                    StartSystemTimeoutDet(Timeout_ReturnToChargingGunDet);
+                }
+            }
+        }
+
+        if (!isReturnTimeout) {
+            StopSystemTimeoutDet();
+        }
+    }
+}
+
+bool GetStartChargingByAlterMode(uint8_t _gun)
+{
+    bool result = true;
+
+    if (pSysConfig->TotalConnectorCount == 2 &&
+            pSysInfo->IsAlternatvieConf == YES) {
+        for (uint8_t _select = 0; _select < pSysConfig->TotalConnectorCount; _select++) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_select);
+
+            if (_select != _gun) {
+                if (pDcChargingInfo->SystemStatus != S_IDLE &&
+                        pDcChargingInfo->SystemStatus != S_RESERVATION) {
+                    result = false;
+                    break;
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+void TheEndCharging(uint8_t gun_index)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun_index);
+
+    ftime(&endChargingTime[gun_index]);
+
+    if (pDcChargingInfo->PresentChargedDuration != 0) {
+        pDcChargingInfo->PresentChargedDuration = DiffTimeb(startChargingTime[gun_index], endChargingTime[gun_index]);
+    }
+
+    pDcChargingInfo->isRemoteStart = NO;
+
+    StopGunInfoTimeoutDet(gun_index);
+    StartGunInfoTimeoutDet(gun_index, Timeout_EvseCompleteDet);
+    ChangeStartOrStopDateTime(NO, gun_index);
+    DB_Insert_Record(gun_index);
+}
+
+void UpdateErrorCodeToOcpp(uint8_t index)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+    //log_info("%d = ConnectorAlarmCode = %s\r\n", index, (char *)chargingInfo[index]->ConnectorAlarmCode);
+    //log_info("%d = EvConnAlarmCode = %s\r\n", index, (char *)chargingInfo[index]->EvConnAlarmCode);
+    if (strcmp((char *)pDcChargingInfo->ConnectorAlarmCode, "") != EQUAL) {
+        //if (strlen((char *)pDcChargingInfo->ConnectorAlarmCode) == EQUAL) {
+        strcpy((char *)ShmOCPP16Data->StatusNotification[index].ErrorCode, "InternalError");
+        strcpy((char *)ShmOCPP16Data->StatusNotification[index].VendorErrorCode, (char *)pDcChargingInfo->ConnectorAlarmCode);
+    } else if (strcmp((char *)pDcChargingInfo->EvConnAlarmCode, "") != EQUAL) {
+        //} else if (strlen((char *)pDcChargingInfo->EvConnAlarmCode) == EQUAL) {
+        strcpy((char *)ShmOCPP16Data->StatusNotification[index].ErrorCode, "OtherError");
+        strcpy((char *)ShmOCPP16Data->StatusNotification[index].VendorErrorCode, (char *)pDcChargingInfo->EvConnAlarmCode);
+    }
+
+    //log_info("2 %d = VendorErrorCode = %s\r\n", index, (char *)ShmOCPP16Data->StatusNotification[index].VendorErrorCode);
+}
+
+void AdjustChargerCurrent()
+{
+    pSysConfig->RatingCurrent = ShmPsuData->SystemAvailableCurrent / 10;
+
+    // 設定的電流~ 如超過可輸出的電流,則 bypass
+    if (pSysConfig->RatingCurrent < pSysConfig->MaxChargingCurrent ||
+            pSysConfig->RatingCurrent == 0) {
+        pSysConfig->MaxChargingCurrent = 0;
+    }
+
+    log_info ("PSU : MaxChargingPower = %d, MaxChargingCurrent = %d",
+              ShmPsuData->SystemAvailablePower / 10,
+              ShmPsuData->SystemAvailableCurrent / 10
+             );
+
+    log_info ("Config : ChargingPower = %d, ChargingCurrent = %d",
+              pSysConfig->MaxChargingPower,
+              pSysConfig->MaxChargingCurrent
+             );
+}
+
+void ResetDetAlarmStatus(uint8_t gun)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun);
+
+    if (pDcChargingInfo->Type == _Type_Chademo) {
+        if (pAlarmCode->AlarmEvents.bits.SystemChademoOutputOVP == YES) {
+            pAlarmCode->AlarmEvents.bits.SystemChademoOutputOVP = NO;
+        }
+    } else if (pDcChargingInfo->Type == _Type_GB) {
+        if (pAlarmCode->AlarmEvents.bits.SystemGbOutputOVP == YES) {
+            pAlarmCode->AlarmEvents.bits.SystemGbOutputOVP = NO;
+        }
+    } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+        if (pAlarmCode->AlarmEvents.bits.SystemCcsOutputOVP == YES) {
+            pAlarmCode->AlarmEvents.bits.SystemCcsOutputOVP = NO;
+        }
+    }
+}
+
+static void powerCabinetPsuAlarmStatus(void)
+{
+    uint8_t i = 0;
+
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+    return;
+#endif //!defined DD360 && !defined DD360Audi && !defined DD360ComBox
+
+    for (i = 0; i < pSysWarning->WarningCount; i++) {
+        if (memcmp(&pSysWarning->WarningCode[i][0], "042267", 6) == 0) {
+            EmcOccureByString("042267");
+        }
+    }
+}
+
+static void autoStartChargingForComBox(uint8_t gunIndex)
+{
+#if !defined DD360ComBox
+    return ;
+#endif //!defined DD360ComBox
+
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if ((pDcChargingInfo->ConnectorPlugIn == YES) &&
+            (pDcChargingInfo->SystemStatus == S_IDLE)
+       ) {
+        pSysInfo->CurGunSelected = gunIndex;
+        strcpy((char *)&pSysConfig->UserId, "AutoStartCharging");
+    }
+}
+
+static bool PrecheckIsPass(uint8_t gun_index)
+{
+    bool result = true;
+
+    // relay welding or driving 是反向
+    result = !ShmDcCommonData->GunRelayWeldingOccur[gun_index];
+
+    return result;
+}
+
+static void ReviewCriticalAlarm(void)
+{
+    if (ShmDcCommonData->GunRelayDrivingOccur[0] == YES ||
+            ShmDcCommonData->GunRelayDrivingOccur[1] == YES ||
+            ShmDcCommonData->GunRelayWeldingOccur[0] == YES ||
+            ShmDcCommonData->GunRelayWeldingOccur[1] == YES ||
+            pAlarmCode->AlarmEvents.bits.EmergencyStopTrip ||
+            pAlarmCode->AlarmEvents.bits.MainPowerBreakerTrip ||
+            pAlarmCode->AlarmEvents.bits.DoorOpen ||
+            pSysWarning->ExtraErrProcess != _EXTRA_ERR_PROCESS_NONE ||
+            pAlarmCode->AlarmEvents.bits.PsuFailureAlarm ||
+            pAlarmCode->AlarmEvents.bits.DisconnectedFromDo
+       ) {
+        pSysWarning->Level = 2;
+    } else {
+        pSysWarning->Level = 0;
+    }
+}
+
+static void CheckRelayWeldingOrDrivingFault(uint8_t gun_index)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun_index);
+
+    // relay welding fault then stop the charging process.
+    uint8_t faultCode = RELAY_STATUS_ERROR_NONE;
+
+    if (gun_index == 0) {
+        if (ShmDcCommonData->CheckRelayStatus[RELAY_SMR1_P_STATUS] == RELAY_STATUS_ERROR_WELDING ||
+                ShmDcCommonData->CheckRelayStatus[RELAY_SMR1_N_STATUS] == RELAY_STATUS_ERROR_WELDING) {
+            faultCode = RELAY_STATUS_ERROR_WELDING;
+        } else if (ShmDcCommonData->CheckRelayStatus[RELAY_SMR1_P_STATUS] == RELAY_STATUS_ERROR_DRIVING ||
+                   ShmDcCommonData->CheckRelayStatus[RELAY_SMR1_N_STATUS] == RELAY_STATUS_ERROR_DRIVING) {
+            faultCode = RELAY_STATUS_ERROR_DRIVING;
+        }
+    } else if (gun_index == 1) {
+        if (ShmDcCommonData->CheckRelayStatus[RELAY_SMR2_P_STATUS] == RELAY_STATUS_ERROR_WELDING ||
+                ShmDcCommonData->CheckRelayStatus[RELAY_SMR2_N_STATUS] == RELAY_STATUS_ERROR_WELDING) {
+            faultCode = RELAY_STATUS_ERROR_WELDING;
+        } else if (ShmDcCommonData->CheckRelayStatus[RELAY_SMR2_P_STATUS] == RELAY_STATUS_ERROR_DRIVING ||
+                   ShmDcCommonData->CheckRelayStatus[RELAY_SMR2_N_STATUS] == RELAY_STATUS_ERROR_DRIVING) {
+            faultCode = RELAY_STATUS_ERROR_DRIVING;
+        }
+    }
+
+    if (pSysConfig->TotalConnectorCount >= 2 &&
+            !pSysInfo->IsAlternatvieConf) {
+        // 橋接
+        if (ShmDcCommonData->CheckRelayStatus[RELAY_PARA_P_STATUS] == RELAY_STATUS_ERROR_WELDING ||
+                ShmDcCommonData->CheckRelayStatus[RELAY_PARA_N_STATUS] == RELAY_STATUS_ERROR_WELDING) {
+            faultCode = RELAY_STATUS_ERROR_WELDING;
+        } else if (ShmDcCommonData->CheckRelayStatus[RELAY_PARA_P_STATUS] == RELAY_STATUS_ERROR_DRIVING ||
+                   ShmDcCommonData->CheckRelayStatus[RELAY_PARA_N_STATUS] == RELAY_STATUS_ERROR_DRIVING) {
+            faultCode = RELAY_STATUS_ERROR_DRIVING;
+        }
+    }
+
+    if (faultCode == RELAY_STATUS_ERROR_WELDING) {
+        // welding
+        if (pDcChargingInfo->Type == _Type_Chademo) {
+            RecordAlarmCode(gun_index, "011011");
+        } else if (pDcChargingInfo->Type == _Type_GB) {
+            RecordAlarmCode(gun_index, "011015");
+        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+            RecordAlarmCode(gun_index, "011013");
+        }
+
+        ShmDcCommonData->GunRelayWeldingOccur[gun_index] = YES;
+        EmcOccureByString("");
+    } else if (faultCode == RELAY_STATUS_ERROR_DRIVING) {
+        // driving
+        if (pDcChargingInfo->Type == _Type_Chademo) {
+            RecordAlarmCode(gun_index, "011012");
+        } else if (pDcChargingInfo->Type == _Type_GB) {
+            RecordAlarmCode(gun_index, "011016");
+        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+            RecordAlarmCode(gun_index, "011014");
+        }
+
+        ShmDcCommonData->GunRelayDrivingOccur[gun_index] = YES;
+        EmcOccureByString("");
+    } else {
+        ShmDcCommonData->GunRelayWeldingOccur[gun_index] = NO;
+        ShmDcCommonData->GunRelayDrivingOccur[gun_index] = NO;
+
+        if (pDcChargingInfo->Type == _Type_Chademo) {
+            ResetChargerAlarmCode(gun_index, "011012");
+            ResetChargerAlarmCode(gun_index, "011011");
+        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+            ResetChargerAlarmCode(gun_index, "011014");
+            ResetChargerAlarmCode(gun_index, "011013");
+        } else if (pDcChargingInfo->Type == _Type_GB) {
+            ResetChargerAlarmCode(gun_index, "011016");
+            ResetChargerAlarmCode(gun_index, "011015");
+        }
+    }
+}
+
+int main(void)
+{
+    bool isModelNameMatch = true;
+    uint8_t evBoardStopState = 0;
+    uint8_t _ocppProfileChkFlag;
+
+    if (CreateAllCsuShareMemory() == FAIL) {
+        log_error("create share memory error\r\n");
+        return FAIL;
+    }
+    ClearAllShmMemParameter();
+
+    pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
+    pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
+    pSysWarning = (struct WARNING_CODE_INFO *)GetShmSysWarningInfo();
+
+    pAlarmCode = (struct AlarmCodeData *)GetShmAlarmCodeData();
+    pFaultCode = (struct FaultCodeData *)GetShmFaultCodeData();
+    pInfoCode = (struct InfoCodeData *)GetShmInfoCodeData();
+
+    ShmPsuData = (struct PsuData *)GetShmPsuData();
+
+    ShmCHAdeMOData = (struct CHAdeMOData *)GetShmCHAdeMOData();
+    ShmGBTData = (struct GBTData *)GetShmGBTData();
+    ShmCcsData = (struct CcsData *)GetShmCcsData();
+
+    ShmPrimaryMcuData = (struct PrimaryMcuData *)GetShmPrimaryMcuData();
+    ShmFanModuleData = (struct FanModuleData *)GetShmFanModuleData();
+    ShmRelayModuleData = (struct RelayModuleData *)GetShmRelayModuleData();
+    ShmLedModuleData = (struct LedModuleData *)GetShmLedModuleData();
+    ShmOCPP16Data = (struct OCPP16Data *)GetShmOCPP16Data();
+    ShmDcCommonData = (DcCommonInfo *)GetShmDcCommonData();
+    gAudiCustInfo = (SelectGunInfo *)GetShmSelectGunInfo();
+
+    log_info(" ****************  FileSystem Boot up ***************\n");
+    if (!InitialSystemDefaultConfig()) {
+        log_error("InitialSystemDefaultConfig NG \n");
+        //StopProcessingLoop();
+        sleep(5);
+        system("reboot -f");
+    }
+    CheckGunTypeFromHw();
+    CheckIsAlternatvieByModelName();
+    InitialShareMemoryInfo();
+
+    ChangeLcmByIndex(_LCM_INIT);
+    if (!CheckConnectorTypeStatus()) {
+        isModelNameMatch = false;
+    }
+
+    Initialization();
+    SpawnTask();
+    log_info("Spawned all Task");
+    if (!isModelNameMatch) {
+        pAlarmCode->AlarmEvents.bits.ModelNameNoneMatchStestFail = YES;
+        ChangeLcmByIndex(_LCM_FIX);
+        // Module Name 與硬體對應不正確
+        log_error("Module Name & HW info none match. \n");
+        sleep(3);
+        KillAllTask();
+        StopProcessingLoop();
+    }
+    CreateTimeoutFork();
+    log_info("Start self test... \n");
+    PrimaryLedIndicatorCtrlFork();
+    SelfTestRun();
+    StopSystemTimeoutDet();
+    log_info("Self test finished : SelfTestSeq = %d, Work_Step = %d ",
+             pSysInfo->SelfTestSeq,
+             ShmPsuData->Work_Step);
+
+    if (pSysInfo->SelfTestSeq == _STEST_FAIL ||
+            ShmPsuData->Work_Step == _NO_WORKING ||
+            pInfoCode->InfoEvents.bits.CcsSeccTimeoutQCA7000Comm == YES //DS60-120 add
+       ) {
+        if (pSysWarning->Level != 2) {
+            if (!DisplaySelfTestFailReason()) { //DS60-120 add
+                log_info("Soft reboot for retry self-tets. \n");
+
+                sleep(3);
+                system("killall OcppBackend &");
+                KillAllTask();
+                system("/usr/bin/run_evse_restart.sh");
+            }
+        }
+
+        for (uint8_t gun_index = 0; gun_index < pSysConfig->TotalConnectorCount; gun_index++) {
+            setChargerMode(gun_index, MODE_ALARM);
+        }
+        //ChangeLcmByIndex(_LCM_FIX);
+        sleep(3);
+        if (pSysWarning->Level == 2) { //DS60-120 add
+            KillTaskExceptPrimary();
+        } else {
+            KillTask();
+        }
+        StopProcessingLoop();
+    } else {
+        for (uint8_t gun_index = 0; gun_index < pSysConfig->TotalConnectorCount; gun_index++) {
+            setChargerMode(gun_index, MODE_IDLE);
+        }
+    }
+
+    // Local DB
+    if (DB_Open() != PASS) {
+        log_info("DB_Open fail. \n");
+        isDb_ready = false;
+    } else {
+        isDb_ready = true;
+        for (int _index = 0; _index < pSysConfig->TotalConnectorCount; _index++) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_index);
+
+            pDcChargingInfo->IsAvailable = DB_Get_Operactive(_index);
+        }
+        DB_Reboot_Record();
+    }
+    log_info("===== Create DB End ===== \n");
+
+#if defined DD360Audi
+    ChangeLcmByIndex(_LCM_SELECT_GUN);
+#else
+    ChangeLcmByIndex(_LCM_IDLE);
+#endif //defined DD360Audi
+
+    sleep(1);
+    //***** 須新增的偵測 *****//
+    // 1. Thernal - 控制風扇轉速
+    // 2. ouput fuse - 控制風扇轉速
+    CreateRfidFork();
+    // Create Watchdog
+    //CreateWatchdog();
+    // Main loop
+
+    log_info("===== Charger info ===== ");
+    log_info("SW Version = %s", fwVersion);
+    log_info("ModelName = %s", pSysConfig->ModelName);
+    CheckFwSlotStatusLog();
+    //AdjustChargerCurrent();
+    gettimeofday(&_cmdMainPriority_time, NULL);
+
+    GunIndexInfo *pGunIndexInfo = (GunIndexInfo *)GetGunIndexInfo();
+
+    for (;;) {
+        CheckOcppStatus();
+        ChkPrimaryStatus();
+        if ((IsConnectorWholeIdle() || pSysInfo->PageIndex == _LCM_FIX) &&
+                pSysInfo->SystemTimeoutFlag != Timeout_ReturnToChargingGunDet) {
+            CheckFactoryConfigFunction();
+
+            CheckFwUpdateFunction();
+        }
+
+        // OCPP 邏輯
+        OcppRemoteStartChk();
+        // 讀卡邏輯
+        ScannerCardProcess();
+        // 當 AC 沒有搭上時,清除一些錯誤碼
+        ClearAlarmCodeWhenAcOff();
+        // 確認是否要回到充電中的槍畫面邏輯判斷
+        CheckReturnToChargingConn();
+
+        //確認Power cabinet PSU Status
+        powerCabinetPsuAlarmStatus();
+
+        if (pGunIndexInfo->AcGunIndex > 0 && isDetectPlugin() && !GetIsCardScan()) {
+            pSysInfo->SystemPage = _LCM_WAIT_FOR_PLUG;
+        }
+
+        if ((GetTimeoutValue(_cmdMainPriority_time) / 1000) > 5000) {
+            CheckTask();
+
+            for (uint8_t _index = 0; _index < pSysConfig->TotalConnectorCount; _index++) {
+                pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_index);
+
+                if ((pDcChargingInfo->SystemStatus >= S_PREPARING_FOR_EVSE &&
+                        pDcChargingInfo->SystemStatus <= S_CHARGING) ||
+                        (pDcChargingInfo->SystemStatus >= S_CCS_PRECHARGE_ST0 &&
+                         pDcChargingInfo->SystemStatus <= S_CCS_PRECHARGE_ST1)) {
+                    if (pDcChargingInfo->SystemStatus == S_CHARGING &&
+                            _ocppProfileChkFlag == 12) {
+                        ChargingProfileFlat(_index);
+                        _ocppProfileChkFlag = 0;
+                    } else if (pDcChargingInfo->SystemStatus != S_CHARGING) {
+                        ChargingProfileFlat(_index);
+                        _ocppProfileChkFlag = 0;
+                    } else {
+                        _ocppProfileChkFlag++;
+                    }
+                }
+                checkGunOTPState(_index); //check gun OTP
+            }
+            gettimeofday(&_cmdMainPriority_time, NULL);
+        }
+
+        // 確認當前錯誤 Level = 2 ?
+        ReviewCriticalAlarm();
+        gEvBoardErr.GunErrMessage = 0;
+
+        for (uint8_t gun_index = 0; gun_index < pSysConfig->TotalConnectorCount; gun_index++) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun_index);
+
+            autoStartChargingForComBox(gun_index); //for DD360ComBox
+
+            CheckGpioInStatus();
+
+            CheckErrorOccurStatus(gun_index);
+
+            // 確認 Relay Welding or Driving Fault
+            CheckRelayWeldingOrDrivingFault(gun_index);
+
+            // 收集各槍的錯誤狀態
+            collectError(gun_index);
+
+            ChkOcppStatus(gun_index);
+
+            if ((pDcChargingInfo->SystemStatus >= S_PREPARING_FOR_EVSE &&
+                    pDcChargingInfo->SystemStatus <= S_CHARGING) ||
+                    (pDcChargingInfo->SystemStatus >= S_CCS_PRECHARGE_ST0 &&
+                     pDcChargingInfo->SystemStatus <= S_CCS_PRECHARGE_ST1)) {
+                CheckSmartChargeProfile(gun_index);
+            }
+
+            //log_info("index = %d, ErrorCode = %s \n", gun_index, ShmOCPP16Data->StatusNotification[gun_index].ErrorCode);
+            switch (pDcChargingInfo->SystemStatus) {
+            case S_IDLE:
+                ReleaseAlarmCode(gun_index);
+
+                if (isModeChange(gun_index)) {
+                    log_info("S_IDLE================================== %x \n", gun_index);
+                    pDcChargingInfo->PresentChargedDuration = 0;
+                    pDcChargingInfo->RemainChargingDuration = 0;
+                    pDcChargingInfo->PresentChargingVoltage = 0;//DS60-120 add
+                    pDcChargingInfo->PresentChargingCurrent = 0;//DS60-120 add
+                    strcpy((char *)pDcChargingInfo->StartDateTime, "");
+                    strcpy((char *)pDcChargingInfo->StopDateTime, "");
+                    strcpy((char *)pDcChargingInfo->StartUserId, "");
+                    strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "");
+
+                    //Jerry add
+                    memset(&gAudiCustInfo->PricesInfo[gun_index], 0, sizeof(PricesInfo));
+                    gAudiCustInfo->PricesInfo[gun_index].Balance = FAIL_BALANCE_PRICES;
+                    destroySelGun(gun_index);
+                    ResetDetAlarmStatus(gun_index); //recovery OVP status code
+                    if (gAudiCustInfo->AuthorStateFromCabinet[gun_index] == YES) {
+                        gAudiCustInfo->AuthorStateFromCabinet[gun_index] = NO;
+                    }
+                    //strcpy((char *)ShmOCPP16Data->StatusNotification[gun_index].VendorErrorCode, "");
+                }
+
+            case S_RESERVATION:
+                if (isModeChange(gun_index)) {
+                    log_info("S_RESERVATION....................%x \n", gun_index);
+                    ShmOCPP16Data->CsMsg.bits[gun_index].ReserveNowConf = YES;
+                }
+
+                if (pDcChargingInfo->IsAvailable == NO) {
+                    setChargerMode(gun_index, MODE_MAINTAIN);
+                }
+
+            case S_MAINTAIN:
+            case S_FAULT: {
+                if (pSysWarning->Level == 2) {
+                    pDcChargingInfo =  (struct ChargingInfoData *)GetDcChargingInfoData(pSysInfo->CurGunSelected);
+
+                    if (gun_index == pSysInfo->CurGunSelected) {
+                        pSysInfo->SystemPage = _LCM_FIX;
+                    } else if (pDcChargingInfo->SystemStatus != S_IDLE &&
+                               pDcChargingInfo->SystemStatus != S_RESERVATION &&
+                               pDcChargingInfo->SystemStatus != S_MAINTAIN &&
+                               pDcChargingInfo->SystemStatus != S_FAULT) {
+                        if (pDcChargingInfo->SystemStatus == S_CHARGING) {
+                            pSysInfo->SystemPage = _LCM_COMPLETE;
+                        } else {
+#if defined DD360Audi
+                            pSysInfo->SystemPage = _LCM_SELECT_GUN;
+#else
+                            pSysInfo->SystemPage = _LCM_NONE;
+#endif //defined DD360Audi
+                        }
+                    }
+
+                    ClearDetectPluginFlag();
+//#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                    UpdateErrorCodeToOcpp(gun_index);
+//#endif //!defined DD360 && !defined DD360Audi
+                    setChargerMode(gun_index, MODE_FAULT);
+                } else {
+#if 1
+                    if (pDcChargingInfo->SystemStatus == S_FAULT) {
+#if defined DD360Audi
+                        pSysInfo->SystemPage = _LCM_SELECT_GUN;
+#else
+                        pSysInfo->SystemPage = _LCM_NONE;
+#endif //defined DD360Audi
+                        setChargerMode(gun_index, MODE_IDLE);
+                    }
+
+                    //if (pSysInfo->SystemPage == _LCM_FIX) {
+                    //    pSysInfo->SystemPage = _LCM_SELECT_GUN;//_LCM_NONE; //Jerry add
+                    //    //for (uint8_t g_index = 0; g_index < pSysConfig->TotalConnectorCount; g_index++) {
+                    //    setChargerMode(gun_index, MODE_IDLE);
+                    //    //}
+                    //}
+#endif //0
+
+                    if (pSysInfo->MainChargingMode == _MAIN_CHARGING_MODE_AVER) {
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                        if (pSysInfo->AcContactorStatus == YES)
+#else
+                        if (1)
+#endif //!defined DD360 && !defined DD360Audi
+                        {
+                            // 均充 -> 最大充
+                            if (pSysInfo->BridgeRelayStatus == NO) {
+                                if (pSysInfo->ReAssignedFlag == _REASSIGNED_NONE) {
+                                    log_info("=============Smart Charging============= Step 11 \n");
+                                    pSysInfo->ReAssignedFlag = _REASSIGNED_PREPARE_A_TO_M;
+                                }
+                            } else if (pSysInfo->ReAssignedFlag != _REASSIGNED_COMP &&
+                                       pSysInfo->ReAssignedFlag != _REASSIGNED_WAITING) {
+                                log_info("=============Smart Charging============= Step 14 \n");
+                                pSysInfo->ReAssignedFlag = _REASSIGNED_WAITING;
+                            } else if (pSysInfo->ReAssignedFlag == _REASSIGNED_COMP) {
+                                pSysInfo->MainChargingMode = _MAIN_CHARGING_MODE_MAX;
+                                pSysInfo->ReAssignedFlag = _REASSIGNED_NONE;
+                            }
+                        } else {
+                            pSysInfo->MainChargingMode = _MAIN_CHARGING_MODE_MAX;
+                            pSysInfo->ReAssignedFlag = _REASSIGNED_NONE;
+                        }
+                    } else {
+                        pSysInfo->ReAssignedFlag = _REASSIGNED_NONE;
+                    }
+
+                    if (PrecheckIsPass(gun_index)) {
+
+                        if (pDcChargingInfo->SystemStatus == S_FAULT) {
+                            pSysInfo->SystemPage = _LCM_NONE;
+                            setChargerMode(gun_index, MODE_IDLE);
+                        }
+
+                        if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_NO_CHARGING) {
+                            if (pSysInfo->CurGunSelected == gun_index) {
+#if defined DD360Audi
+                                pSysInfo->ConnectorPage = _LCM_SELECT_GUN;
+#else
+                                pSysInfo->ConnectorPage = _LCM_IDLE;
+#endif //
+                            }
+                        } else {
+                            // Idle 正常程序起點
+                            // 判斷是否有啟用檢查插槍
+                            if (isDetectPlugin()) {
+                                // 卡號驗證成功後,等待充電槍插入充電車
+                                if (pDcChargingInfo->RemoteStartFlag == YES) {
+                                    if (pDcChargingInfo->ConnectorPlugIn == YES &&
+                                            pDcChargingInfo->IsAvailable) {
+                                        log_info("-----------------1----------------- %d \n", gun_index);
+                                        pDcChargingInfo->RemoteStartFlag = NO;
+                                        pDcChargingInfo->isRemoteStart = YES; //DS60-120
+                                        ChangeGunSelectByIndex(gun_index);
+                                        AddPlugInTimes(gun_index);
+                                        setChargerMode(gun_index, MODE_REASSIGN_CHECK);
+                                        strcpy((char *)pDcChargingInfo->StartUserId, "");
+                                        ClearDetectPluginFlag();
+                                        continue;
+                                    }
+                                } else if (pSysInfo->OrderCharging == NO_DEFINE) {
+                                    if (pDcChargingInfo->ConnectorPlugIn == YES &&
+                                            pDcChargingInfo->IsAvailable &&
+                                            pDcChargingInfo->SystemStatus == S_IDLE
+#if defined DD360Audi
+                                            && (waitRightGunPlugIt(gun_index) == PASS ||
+                                                waitLeftGunPlugIt(gun_index) == PASS)
+#endif //defined DD360Audi
+                                       ) {
+                                        log_info("-----------------2----------------- \n");
+                                        ChangeGunSelectByIndex(gun_index);
+                                        AddPlugInTimes(gun_index);
+                                        strcpy((char *)pDcChargingInfo->StartUserId, (char *)pSysConfig->UserId);
+                                        log_info("index = %d, CardNumber = %s \n", gun_index, pDcChargingInfo->StartUserId);
+                                        strcpy((char *)pSysConfig->UserId, "");
+                                        // 當前操作的槍號,進入 Preparing
+                                        setChargerMode(gun_index, MODE_REASSIGN_CHECK);
+                                        ClearDetectPluginFlag();
+                                        continue;
+                                    }
+                                }
+
+                                if (!GetIsCardScan()) {
+                                    // LCM => Waiting for plugging
+                                    pSysInfo->SystemPage = _LCM_WAIT_FOR_PLUG;
+                                }
+                            } else if (pDcChargingInfo->SystemStatus == S_RESERVATION) {
+                                if (!isReservationExpired(gun_index)) {
+                                    pDcChargingInfo->SystemStatus = S_IDLE;
+                                }
+                            } else if (pSysConfig->AuthorisationMode == AUTH_MODE_DISABLE &&
+                                       (pDcChargingInfo->ConnectorPlugIn == YES && pDcChargingInfo->IsAvailable)) {
+                                log_info("-----------------3----------------- \n");
+                                bool isCanStartChargingFlag = GetStartChargingByAlterMode(gun_index);
+
+                                if (isCanStartChargingFlag) {
+                                    ChangeGunSelectByIndex(gun_index);
+                                    AddPlugInTimes(gun_index);
+                                    setChargerMode(gun_index, MODE_REASSIGN_CHECK);
+                                    ClearDetectPluginFlag();
+                                    continue;
+                                }
+                            } else {
+                                if (pSysInfo->CurGunSelected == gun_index) {
+#if defined DD360Audi
+                                    pSysInfo->ConnectorPage = _LCM_SELECT_GUN;
+#else
+                                    pSysInfo->ConnectorPage = _LCM_IDLE;
+#endif // defined DD360Audi
+                                }
+                            }
+                        } // Idle 正常程序終點
+                    } else {
+                        setChargerMode(gun_index, MODE_FAULT);
+                        if (gun_index == pSysInfo->CurGunSelected) {
+                            pSysInfo->SystemPage = _LCM_FIX;
+                        }
+                    }// PrecheckIsPass()
+                }
+            }
+            break;
+            case S_REASSIGN_CHECK: {
+                if (isModeChange(gun_index)) {
+                    log_info("S_REASSIGN_CHECK================================== %x \n", gun_index);
+#if defined DD360Audi
+                    pSysInfo->SystemPage = _LCM_SELECT_GUN;
+#else
+                    pSysInfo->SystemPage = _LCM_NONE;
+#endif //defined DD360Audi
+                    if (pSysInfo->OrderCharging != NO_DEFINE) {
+                        pSysInfo->OrderCharging = NO_DEFINE;
+                    }
+                    StopSystemTimeoutDet();
+                }
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                bool isRessign = false;
+                if (pSysConfig->TotalConnectorCount > 1 && pSysInfo->IsAlternatvieConf == NO) {
+                    if (pSysInfo->MainChargingMode == _MAIN_CHARGING_MODE_MAX) {
+                        for (byte index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+                            // 有其他槍已經分配好 psu 模塊
+                            if (pSysInfo->CurGunSelected != index &&
+                                    chargingInfo[index]->SystemStatus >= S_PREPARNING &&
+                                    chargingInfo[index]->SystemStatus != S_MAINTAIN) {
+                                log_info("=============Smart Charging============= Step 1 \n");
+                                pSysInfo->ReAssignedFlag = _REASSIGNED_PREPARE_M_TO_A;
+                                isRessign = true;
+                                break;
+                            }
+                        }
+                    } else if (pSysInfo->MainChargingMode == _MAIN_CHARGING_MODE_AVER &&
+                               pSysInfo->ReAssignedFlag != _REASSIGNED_NONE) {
+                        // 如果在切換最大充的過程中,需等待最大充切換完成後,在走均充流程
+                        if (pSysInfo->BridgeRelayStatus == YES) {
+                            if (pSysInfo->ReAssignedFlag != _REASSIGNED_COMP &&
+                                    pSysInfo->ReAssignedFlag != _REASSIGNED_WAITING) {
+                                log_info("=============Smart Charging============= Step 14 \n");
+                                pSysInfo->ReAssignedFlag = _REASSIGNED_WAITING;
+                            } else if (pSysInfo->ReAssignedFlag == _REASSIGNED_COMP) {
+                                pSysInfo->MainChargingMode = _MAIN_CHARGING_MODE_MAX;
+                                pSysInfo->ReAssignedFlag = _REASSIGNED_NONE;
+                                continue;
+                            }
+                        }
+
+                        if (pSysInfo->CurGunSelected == gun_index) {
+                            pSysInfo->ConnectorPage = _LCM_PRE_CHARGE;
+                        }
+                        continue;
+                    }
+                }
+#endif // !defined DD360 && !defined DD360Audi
+
+                if (0) { // if (isRessign)
+#if defined DD360 ||defined DD360Audi || defined DD360ComBox
+                    setChargerMode(gun_index, MODE_PRECHARGE);
+#else
+                    setChargerMode(gun_index, MODE_REASSIGN);
+#endif //defined DD360 || defined DD360Audi
+                } else {
+                    setChargerMode(gun_index, MODE_PRECHARGE);
+                }
+
+                if (pSysInfo->CurGunSelected == gun_index) {
+                    pSysInfo->ConnectorPage = _LCM_PRE_CHARGE;
+                }
+            }
+            break;
+            case S_REASSIGN: {
+                if (isModeChange(gun_index)) {
+                    log_info("S_REASSIGN================================== %x \n", gun_index);
+                    gettimeofday(&_toAverage_time, NULL);
+                }
+
+                // 重新分配,此階段主要是讓已經在充電或者準備進入充電前的緩衝
+                // 此狀態下~ 控制權在於 PSU 及 EV小板 Process
+                if (pSysInfo->ReAssignedFlag == _REASSIGNED_NONE ||
+                        pSysInfo->MainChargingMode == _MAIN_CHARGING_MODE_AVER) {
+                    if (pSysInfo->CanAverageCharging) {
+                        pSysInfo->MainChargingMode = _MAIN_CHARGING_MODE_AVER;//DS60-120 add
+                        setChargerMode(gun_index, MODE_PRECHARGE);
+                    } else {
+                        setChargerMode(gun_index, MODE_IDLE);
+                    }
+                    pSysInfo->ReAssignedFlag = _REASSIGNED_NONE; //DS60-120 add
+                } else if (pSysInfo->ReAssignedFlag == _REASSIGNED_RELAY_M_TO_A &&
+                           pSysInfo->BridgeRelayStatus == NO) {
+                    log_info("=============Smart Charging : _REASSIGNED_COMP============= Step 6 \n");
+                    pSysInfo->MainChargingMode = _MAIN_CHARGING_MODE_AVER;
+                    //pSysInfo->ReAssignedFlag = _REASSIGNED_NONE; //DS60-120 remove
+                    pSysInfo->CanAverageCharging = true; //DS60-120 add
+                }
+
+                //log_info("CurGunSelected = %d, gun_index = %d \n", pSysInfo->CurGunSelected, gun_index);
+                if (pSysInfo->CurGunSelected == gun_index) {
+                    pSysInfo->ConnectorPage = _LCM_PRE_CHARGE;
+                    // pSysInfo->SystemPage = _LCM_NONE;
+                }
+            }
+            break;
+            case S_PREPARNING: {
+                if (isModeChange(gun_index)) {
+                    log_info("S_PREPARNING================================== %x \n", gun_index);
+                    StopGunInfoTimeoutDet(gun_index);
+                    StartGunInfoTimeoutDet(gun_index, Timeout_Preparing);
+                }
+
+                if (ShmPsuData->SystemPresentPsuQuantity > 0 &&
+                        ShmPsuData->SystemAvailablePower > 10 &&
+                        GetTimeoutValue(pDcChargingInfo->TimeoutTimer) >= 5000000) {
+                    //if ((pDcChargingInfo->MaximumChargingVoltage > 0) && //DS60-120 remove
+                    //        (pDcChargingInfo->AvailableChargingCurrent > 0) &&
+                    //        (pDcChargingInfo->AvailableChargingPower > 0)) {
+                    setChargerMode(gun_index, MODE_PREPARE_FOR_EV);
+                    //}
+                }
+
+                //DS60-120 add
+                if (pSysConfig->TotalConnectorCount >= 2) {
+                    bool oughtAver = true;
+                    for (uint8_t index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+                        pDcChargingInfo =  (struct ChargingInfoData *)GetDcChargingInfoData(index);
+                        // 共同進入充電邏輯
+                        if (pDcChargingInfo->SystemStatus != S_PREPARNING) {
+                            oughtAver = false;
+                            break;
+                        }
+                    }
+
+                    if (oughtAver) {
+                        log_info("********* Automatically change to aver mode ********** \n");
+                        pSysInfo->MainChargingMode = _MAIN_CHARGING_MODE_AVER;
+                        pSysInfo->ReAssignedFlag = _REASSIGNED_NONE;
+                    }
+                }
+
+                if ((evBoardStopState = isEvBoardStopChargeFlag(gun_index)) > 0) {
+                    // 板端要求停止 (錯誤)
+                    if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL) {
+                        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "EVDisconnected");
+                    }
+
+                    if (evBoardStopState == EV_BOARD_STOP_CHARGING) {
+                        ChargingAlarmProcess(gun_index);
+                    } else if (evBoardStopState == POWER_CABINET_STOP_CHARGING) {
+                        ChargingTerminalProcess(gun_index);
+                    }
+                } else if (isEvBoardNormalStopChargeFlag(gun_index) == YES) {
+                    // 板端要求停止 (正常)
+                    if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL) {
+                        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "EVDisconnected");
+                    }
+                    ChargingTerminalProcess(gun_index);
+                } else if (OcppRemoteStop(gun_index) == YES ||
+                           WifiScheduleStop(gun_index)) {
+                    // 後臺要求停止
+                    ChargingTerminalProcess(gun_index);
+                }
+
+                if (pSysInfo->CurGunSelected == gun_index) {
+                    pSysInfo->ConnectorPage = _LCM_PRE_CHARGE;
+                    // pSysInfo->SystemPage = _LCM_NONE;
+                }
+            }
+            break;
+            case S_PREPARING_FOR_EV: { // 等待車端的通訊 (EV 小板),待車端回報後,開始樁端的測試
+                if (isModeChange(gun_index)) {
+                    log_info("S_PREPARING_FOR_EV================================== %x \n", gun_index);
+                    //strcpy((char *)pSysConfig->UserId, "");
+                    StopGunInfoTimeoutDet(gun_index);
+                    StartGunInfoTimeoutDet(gun_index, Timeout_EvChargingDet);
+                }
+
+                if (pDcChargingInfo->Type == _Type_Chademo) {
+                    // 檢查車端的槍鎖是否為鎖上
+                    if (isEvGunLocked_chademo(gun_index) == YES) {
+                        setChargerMode(gun_index, MODE_PREPARE_FOR_EVSE);
+                    }
+                } else if (pDcChargingInfo->Type == _Type_GB) {
+                    // 檢查車端的 charging enable 是否為 1
+                    if (isEvGunLocked_gb(gun_index) == YES) {
+                        setChargerMode(gun_index, MODE_PREPARE_FOR_EVSE);
+                    }
+                } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                    // 檢查車端的 charging enable 是否為 1
+                    if (isEvGunLocked_ccs(gun_index) == YES) {
+                        setChargerMode(gun_index, MODE_PREPARE_FOR_EVSE);
+                    }
+                }
+
+                if ((evBoardStopState = isEvBoardStopChargeFlag(gun_index)) > 0) {
+                    // 板端要求停止 (錯誤)
+                    if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL) {
+                        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "EVDisconnected");
+                    }
+
+                    if (evBoardStopState == EV_BOARD_STOP_CHARGING) {
+                        ChargingAlarmProcess(gun_index);
+                    } else if (evBoardStopState == POWER_CABINET_STOP_CHARGING) {
+                        ChargingTerminalProcess(gun_index);
+                    }
+                } else if (isEvBoardNormalStopChargeFlag(gun_index) == YES) {
+                    // 板端要求停止 (正常)
+                    if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL) {
+                        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "EVDisconnected");
+                    }
+                    ChargingTerminalProcess(gun_index);
+                } else if (OcppRemoteStop(gun_index) == YES ||
+                           WifiScheduleStop(gun_index)) {
+                    // 後臺要求停止
+                    ChargingTerminalProcess(gun_index);
+                }
+
+                // LCM => Pre-charging
+                if (pSysInfo->CurGunSelected == gun_index) {
+                    pSysInfo->ConnectorPage = _LCM_PRE_CHARGE;
+                    // pSysInfo->SystemPage = _LCM_NONE;
+                }
+            }
+            break;
+            case S_PREPARING_FOR_EVSE: { // 等待 RB 通訊及測試,並將狀態回報, CSU 確認 Pass 後,開始進入充電
+                if (isModeChange(gun_index)) {
+                    log_info("S_PREPARING_FOR_EVSE================================== %x \n", gun_index);
+                    StopGunInfoTimeoutDet(gun_index);
+                    StartGunInfoTimeoutDet(gun_index, Timeout_EvseChargingDet);
+                }
+
+                if (pDcChargingInfo->Type == _Type_Chademo) {
+                    // 檢查樁端的 GFD 結果
+                    if (isPrechargeStatus_chademo(gun_index) > 5 && isPrechargeStatus_chademo(gun_index) < 8) {
+                        // 當前操作的槍號,進入 Charging
+                        setChargerMode(gun_index, MODE_CHARGING);
+                    }
+
+                    if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                        // GFD 錯誤停止
+                        RecordAlarmCode(gun_index, "012234");
+                    } else if (pDcChargingInfo->GroundFaultStatus == GFD_WARNING) {
+                        // GFD 警告
+                        RecordWarningCode(gun_index, "012296");
+                    }
+                } else if (pDcChargingInfo->Type == _Type_GB) {
+                    // 檢查樁端的 GFD 結果
+                    //if (isPrechargeStatus_gb(gun_index) > 5 && isPrechargeStatus_gb(gun_index) < 9) {
+                    if (isPrechargeStatus_gb(gun_index) > 9) {
+                        setChargerMode(gun_index, MODE_CHARGING);
+                    }
+
+                    if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                        // GFD 錯誤停止
+                        RecordAlarmCode(gun_index, "012236");
+                    } else if (pDcChargingInfo->GroundFaultStatus == GFD_WARNING) {
+                        // GFD 警告
+                        RecordWarningCode(gun_index, "012298");
+                    }
+                } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                    // 檢查樁端的 GFD 結果
+                    if ((pDcChargingInfo->GroundFaultStatus == GFD_PASS ||
+                            pDcChargingInfo->GroundFaultStatus == GFD_WARNING)) {
+                        setChargerMode(gun_index, MODE_CCS_PRECHARGE_STEP0);
+                    }
+
+                    if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                        // GFD 錯誤停止
+                        RecordAlarmCode(gun_index, "012235");
+                    } else if (pDcChargingInfo->GroundFaultStatus == GFD_WARNING) {
+                        // GFD 警告
+                        RecordWarningCode(gun_index, "012297");
+                    }
+                }
+
+                if ((evBoardStopState = isEvBoardStopChargeFlag(gun_index)) > 0) {
+                    // 板端要求停止 (錯誤)
+                    if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL) {
+                        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "EVDisconnected");
+                    }
+
+                    if (evBoardStopState == EV_BOARD_STOP_CHARGING) {
+                        ChargingAlarmProcess(gun_index);
+                    } else if (evBoardStopState == POWER_CABINET_STOP_CHARGING) {
+                        ChargingTerminalProcess(gun_index);
+                    }
+                } else if (isEvBoardNormalStopChargeFlag(gun_index) == YES) {
+                    // 板端要求停止 (正常)
+                    if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL) {
+                        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "EVDisconnected");
+                    }
+                    ChargingTerminalProcess(gun_index);
+                } else if (OcppRemoteStop(gun_index) == YES ||
+                           WifiScheduleStop(gun_index)) {
+                    // 後臺要求停止
+                    ChargingTerminalProcess(gun_index);
+                }
+
+                // LCM => Pre-charging
+                if (pSysInfo->CurGunSelected == gun_index) {
+                    pSysInfo->ConnectorPage = _LCM_PRE_CHARGE;
+                    // pSysInfo->SystemPage = _LCM_NONE;
+                }
+            }
+            break;
+            case S_CHARGING: { // 剛進入充電狀態,等待 EV 小板要求的輸出電流後開始輸出
+                if (isModeChange(gun_index)) {
+                    log_info("S_CHARGING================================== %x \n", gun_index);
+                    StopGunInfoTimeoutDet(gun_index);
+                    ftime(&startChargingTime[gun_index]);
+                    strcpy((char *)ShmOCPP16Data->StartTransaction[gun_index].ResponseIdTagInfo.Status, ""); //DS60-120 add
+                    ChangeStartOrStopDateTime(YES, gun_index);
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                    OcppStartTransation(gun_index);
+#endif //!defined DD360 && !defined DD360Audi
+                }
+
+                if (ShmOCPP16Data->CpMsg.bits[gun_index].StartTransactionConf) {
+                    ShmOCPP16Data->CpMsg.bits[gun_index].StartTransactionConf = NO;
+                }
+                ftime(&endChargingTime[gun_index]);
+                pDcChargingInfo->PresentChargedDuration = DiffTimeb(startChargingTime[gun_index], endChargingTime[gun_index]);
+
+                if (pDcChargingInfo->Type == _Type_Chademo) {
+                    if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                        // GFD 錯誤停止
+                        RecordAlarmCode(gun_index, "012234");
+                    }
+                    //else if (((pDcChargingInfo->EvBatterytargetVoltage * 10) > 0 && pDcChargingInfo->EvBatterytargetVoltage < SYSTEM_MIN_VOL) ||
+                    //           (pDcChargingInfo->PresentChargedDuration >= 10 && pDcChargingInfo->PresentChargingVoltage < SYSTEM_MIN_VOL)) {
+                    //    // UVP
+                    //    RecordAlarmCode(gun_index, "012289");
+                    //    ChargingTerminalProcess(gun_index);
+                    //}
+                    else if (pDcChargingInfo->GroundFaultStatus == GFD_WARNING) {
+                        // GFD 警告
+                        RecordWarningCode(gun_index, "012296");
+                    }
+                } else if (pDcChargingInfo->Type == _Type_GB) {
+                    if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                        // GFD 錯誤停止
+                        RecordAlarmCode(gun_index, "012236");
+                    }
+                    //else if (isPrechargeStatus_gb(gun_index) == 10 &&
+                    //           (((pDcChargingInfo->EvBatterytargetVoltage * 10) > 0 && pDcChargingInfo->EvBatterytargetVoltage < SYSTEM_MIN_VOL) ||
+                    //            (pDcChargingInfo->PresentChargedDuration >= 10 && pDcChargingInfo->PresentChargingVoltage < SYSTEM_MIN_VOL))) {
+                    //    // UVP
+                    //    RecordAlarmCode(gun_index, "012290");
+                    //    ChargingTerminalProcess(gun_index);
+                    //}
+                    else if (pDcChargingInfo->GroundFaultStatus == GFD_WARNING) {
+                        // GFD 警告
+                        RecordWarningCode(gun_index, "012298");
+                    }
+                } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                    if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                        // GFD 錯誤停止
+                        RecordAlarmCode(gun_index, "012235");
+                    }
+                    //else if (((pDcChargingInfo->EvBatterytargetVoltage * 10) > 0 && pDcChargingInfo->EvBatterytargetVoltage < SYSTEM_MIN_VOL) ||
+                    //           (pDcChargingInfo->PresentChargedDuration >= 10 && pDcChargingInfo->PresentChargingVoltage < SYSTEM_MIN_VOL)) {
+                    //    // UVP
+                    //    RecordAlarmCode(gun_index, "012288");
+                    //    ChargingTerminalProcess(gun_index);
+                    //}
+                    else if (pDcChargingInfo->GroundFaultStatus == GFD_WARNING) {
+                        // GFD 警告
+                        RecordWarningCode(gun_index, "012297");
+                    }
+                }
+
+                if ((evBoardStopState = isEvBoardStopChargeFlag(gun_index)) > 0) {
+                    // 板端要求停止 (錯誤)
+                    if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL) {
+                        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "EVDisconnected");
+                    }
+                    //printf("%d evBoardStopState = %d\r\n", gun_index, evBoardStopState);
+                    if (evBoardStopState == EV_BOARD_STOP_CHARGING) {
+                        ChargingAlarmProcess(gun_index);
+                    } else if (evBoardStopState == POWER_CABINET_STOP_CHARGING) {
+                        ChargingTerminalProcess(gun_index);
+                    }
+                } else if (isEvBoardNormalStopChargeFlag(gun_index) == YES) {
+                    // 板端要求停止 (正常)
+                    if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL) {
+                        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "EVDisconnected");
+                    }
+                    ChargingTerminalProcess(gun_index);
+                } else if (OcppRemoteStop(gun_index) == YES ||
+                           WifiScheduleStop(gun_index) ||
+                           CheckBackendChargingTimeout(gun_index) ||
+                           CheckBackendChargingEnergy(gun_index) ||
+                           strcmp((char *)ShmOCPP16Data->StartTransaction[gun_index].ResponseIdTagInfo.Status, "Invalid") == EQUAL) {
+
+                    // 後臺要求停止
+                    ChargingTerminalProcess(gun_index);
+                }
+
+                // LCM => Charging
+                if (pSysInfo->CurGunSelected == gun_index) {
+                    pSysInfo->ConnectorPage = _LCM_CHARGING;
+                    // pSysInfo->SystemPage = _LCM_NONE;
+                }
+            }
+            break;
+            case S_ALARM:
+            case S_TERMINATING: {
+                if (isModeChange(gun_index)) {
+                    if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL) {
+                        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "Local");
+                    }
+
+                    if (pDcChargingInfo->SystemStatus == S_ALARM) {
+                        log_info("================== S_ALARM (%x) ================ \n", gun_index);
+                        UpdateErrorCodeToOcpp(gun_index);
+
+                        if (strcmp((char *)pDcChargingInfo->StartDateTime, "") != EQUAL) {
+                            OcppStopTransation(gun_index);
+                        }
+
+                        TheEndCharging(gun_index);
+                    } else {
+                        log_info("================== S_TERMINATING (%x) ================ \n", gun_index);
+                    }
+
+                    //log_info ("terminating......................... %x \n", gun_index);
+                    StopGunInfoTimeoutDet(gun_index);
+                }
+
+                if (pDcChargingInfo->Type == _Type_Chademo) {
+                    // 非車端的停止 : 需等待小板送出停止指令,讓車端解除槍
+                    //if (isEvStopCharging_chademo(gun_index) == YES) {
+                    //    /*+++ 20200908, vern, disable it for DD360 +++*/
+                    //    /*if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL)
+                    //        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "Local");*/
+                    //    /*--- 20200908, vern, disable it for DD360 ---*/
+                    //}
+
+                    if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                        // GFD 錯誤停止
+                        RecordAlarmCode(gun_index, "012234");
+                    } else if (pDcChargingInfo->GroundFaultStatus == GFD_WARNING) {
+                        // GFD 警告
+                        RecordWarningCode(gun_index, "012296");
+                    }
+
+                    //if (isEvStopCharging_chademo(gun_index) == YES ||
+                    //        isPrechargeStatus_chademo(gun_index) <= 0) {
+                    //    setChargerMode(gun_index, MODE_COMPLETE);
+                    //}
+                } else if (pDcChargingInfo->Type == _Type_GB) {
+                    //log_info("************ GB lock Status = %d, status = %d \n",
+                    //         isEvStopCharging_gb(gun_index),
+                    //         isPrechargeStatus_gb(gun_index));
+
+                    // 非車端的停止 : 需等待小板送出停止指令,讓車端解除槍
+                    //if (isEvStopCharging_chademo(gun_index) == YES) {
+                    //    /*+++ 20200908, vern, disable it for DD360 +++*/
+                    //    /*if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL)
+                    //            strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "Local");*/
+                    //    /*--- 20200908, vern, disable it for DD360 ---*/
+                    //}
+
+                    if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                        // GFD 錯誤停止
+                        RecordAlarmCode(gun_index, "012236");
+                    } else if (pDcChargingInfo->GroundFaultStatus == GFD_WARNING) {
+                        // GFD 警告
+                        RecordWarningCode(gun_index, "012298");
+                    }
+
+                    //if (isEvStopCharging_gb(gun_index) == YES ||
+                    //        isPrechargeStatus_gb(gun_index) <= 0) {
+                    //    setChargerMode(gun_index, MODE_COMPLETE);
+                    //}
+                } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                    // 非車端的停止 : 需等待小板送出停止指令,讓車端解除槍
+                    //if (isEvStopCharging_chademo(gun_index) == YES) {
+                    //    /*+++ 20200908, vern, disable it for DD360 +++*/
+                    //    /*if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL)
+                    //            strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "Local");*/
+                    //    /*--- 20200908, vern, disable it for DD360 ---*/
+                    //}
+
+                    if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                        // GFD 錯誤停止
+                        RecordAlarmCode(gun_index, "012235");
+                    } else if (pDcChargingInfo->GroundFaultStatus == GFD_WARNING) {
+                        // GFD 警告
+                        RecordWarningCode(gun_index, "012297");
+                    }
+
+                    //if (isEvStopCharging_ccs(gun_index) == YES &&
+                    //        (isPrechargeStatus_ccs(gun_index) >= 53 || isPrechargeStatus_ccs(gun_index) == 0 ||
+                    //         isPrechargeStatus_ccs(gun_index) == 13 || isPrechargeStatus_ccs(gun_index) == 14)) {
+                    //    setChargerMode(gun_index, MODE_COMPLETE);
+                    //}
+                }
+
+                if (pDcChargingInfo->SystemStatus == S_ALARM) {
+                    if (pDcChargingInfo->ConnectorPlugIn == NO &&
+                            GetTimeoutValue(pDcChargingInfo->TimeoutTimer) >= 10000000) {
+                        setChargerMode(gun_index, MODE_IDLE);
+                    }
+                } else {
+                    if (pDcChargingInfo->Type == _Type_Chademo) {
+                        if (isEvStopCharging_chademo(gun_index) == YES ||
+                                isPrechargeStatus_chademo(gun_index) <= 0) {
+                            setChargerMode(gun_index, MODE_COMPLETE);
+                        }
+                    } else if (pDcChargingInfo->Type == _Type_GB) {
+                        if (isEvStopCharging_gb(gun_index) == YES ||
+                                isPrechargeStatus_gb(gun_index) <= 0) {
+                            setChargerMode(gun_index, MODE_COMPLETE);
+                        }
+                    } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                        if (isEvStopCharging_ccs(gun_index) == YES &&
+                                (isPrechargeStatus_ccs(gun_index) >= 53 || isPrechargeStatus_ccs(gun_index) == 0 ||
+                                 isPrechargeStatus_ccs(gun_index) == 13 || isPrechargeStatus_ccs(gun_index) == 14)) {
+                            setChargerMode(gun_index, MODE_COMPLETE);
+                        }
+                    }
+                }
+
+                // 車端的停止
+                //if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL) {
+                //    strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "EVDisconnected");
+                //}
+
+                if (pSysInfo->CurGunSelected == gun_index) {
+                    pSysInfo->ConnectorPage = _LCM_COMPLETE;
+                    // pSysInfo->SystemPage = _LCM_NONE;
+                }
+            }
+            break;
+            case S_COMPLETE: {
+                if (isModeChange(gun_index)) {
+                    log_info ("complete......................... %x \n", gun_index);
+                    if (strcmp((char *)pDcChargingInfo->StartDateTime, "") != EQUAL) {
+                        OcppStopTransation(gun_index);
+                    }
+
+                    TheEndCharging(gun_index);
+                    //ftime(&endChargingTime[gun_index]);
+                    //if (pDcChargingInfo->PresentChargedDuration != 0) {
+                    //    pDcChargingInfo->PresentChargedDuration = DiffTimeb(startChargingTime[gun_index], endChargingTime[gun_index]);
+                    //}
+
+                    //StopGunInfoTimeoutDet(gun_index);
+                    //StartGunInfoTimeoutDet(gun_index, Timeout_EvseCompleteDet);
+                    //ChangeStartOrStopDateTime(NO, gun_index);
+                }
+
+                //if (((pDcChargingInfo->ConnectorPlugIn == NO) ||
+                //        (restartFlag == 1)) &&
+                //        (GetTimeoutValue(pDcChargingInfo->TimeoutTimer) >= 10000000)) {
+                //    setChargerMode(gun_index, MODE_IDLE);
+                //    destroySelGun(gun_index); //Jerry add
+                //}
+
+                if (pDcChargingInfo->ConnectorPlugIn == NO &&
+                        GetTimeoutValue(pDcChargingInfo->TimeoutTimer) >= 10000000) {
+                    setChargerMode(gun_index, MODE_IDLE);
+#if defined DD360Audi
+                    destroySelGun(gun_index); //Jerry add
+#endif //defined DD360Audi
+                }
+
+                if (pSysInfo->CurGunSelected == gun_index) {
+                    pSysInfo->ConnectorPage = _LCM_COMPLETE;
+                    // pSysInfo->SystemPage = _LCM_NONE;
+                }
+            }
+            break;
+            case S_CCS_PRECHARGE_ST0: {
+                if (isModeChange(gun_index)) {
+                    log_info("CCS Precharge Processing 1....................%x \n", gun_index);
+                    StopGunInfoTimeoutDet(gun_index);
+                    StartGunInfoTimeoutDet(gun_index, Timeout_ForCcsPrechargeDet);
+                }
+
+                if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                    // GFD 錯誤停止
+                    RecordAlarmCode(gun_index, "012235");
+                }
+
+                if ((evBoardStopState = isEvBoardStopChargeFlag(gun_index)) > 0) {
+                    // 板端要求停止 (錯誤)
+                    if (evBoardStopState == EV_BOARD_STOP_CHARGING) {
+                        ChargingAlarmProcess(gun_index);
+                    } else if (evBoardStopState == POWER_CABINET_STOP_CHARGING) {
+                        ChargingTerminalProcess(gun_index);
+                    }
+                } else if (isEvBoardNormalStopChargeFlag(gun_index) == YES) {
+                    // 板端要求停止 (正常)
+                    ChargingTerminalProcess(gun_index);
+                } else if (OcppRemoteStop(gun_index) == YES ||
+                           WifiScheduleStop(gun_index)) {
+                    // 後臺要求停止
+                    ChargingTerminalProcess(gun_index);
+                }
+
+                // 等待 EV 小板 (CCS) 通知可以開始 Precharge
+                // 切換 D+ Relay to Precharge Relay
+                if (isPrechargeStatus_ccs(gun_index) == 39 || isPrechargeStatus_ccs(gun_index) == 40) {
+                    if (pDcChargingInfo->RelayKPK2Status == YES && pDcChargingInfo->PrechargeStatus != PRECHARGE_READY)
+                        //if (pDcChargingInfo->PrechargeStatus != PRECHARGE_PRERELAY_PASS)
+                    {
+                        //log_info("Send precharge ready 1..........%x, status = %d \n", gun_index, isPrechargeStatus_ccs(gun_index));
+                        if (isPrechargeStatus_ccs(gun_index) == 39) {
+                            log_info("Conn %x, Precharge ready, CCS status = PreChargeResponse (%d) \n", gun_index, isPrechargeStatus_ccs(gun_index));
+                        } else if (isPrechargeStatus_ccs(gun_index) == 40) {
+                            log_info("Conn %x, Precharge ready, CCS status = PowerDeliveryRequest start (%d) \n", gun_index, isPrechargeStatus_ccs(gun_index));
+                        }
+
+                        pDcChargingInfo->PrechargeStatus = PRECHARGE_READY;
+                    }
+                } else if (isPrechargeStatus_ccs(gun_index) == 45 || isPrechargeStatus_ccs(gun_index) == 46) {
+                    setChargerMode(gun_index, MODE_CCS_PRECHARGE_STEP1);
+                }
+
+                if (pSysInfo->CurGunSelected == gun_index) {
+                    pSysInfo->ConnectorPage = _LCM_PRE_CHARGE;
+                    // pSysInfo->SystemPage = _LCM_NONE;
+                }
+                break;
+            }
+            case S_CCS_PRECHARGE_ST1: {
+                if (isModeChange(gun_index)) {
+                    log_info("CCS Precharge Processing 2....................%x \n", gun_index);
+                }
+
+                if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                    // GFD 錯誤停止
+                    RecordAlarmCode(gun_index, "012235");
+                }
+
+                if ((evBoardStopState = isEvBoardStopChargeFlag(gun_index)) > 0) {
+                    // 板端要求停止 (錯誤)
+                    if (evBoardStopState == EV_BOARD_STOP_CHARGING) {
+                        ChargingAlarmProcess(gun_index);
+                    } else if (evBoardStopState == POWER_CABINET_STOP_CHARGING) {
+                        ChargingTerminalProcess(gun_index);
+                    }
+
+                } else if (isEvBoardNormalStopChargeFlag(gun_index) == YES) {
+                    // 板端要求停止 (正常)
+                    ChargingTerminalProcess(gun_index);
+                } else if (OcppRemoteStop(gun_index) == YES ||
+                           WifiScheduleStop(gun_index)) {
+                    // 後臺要求停止
+                    ChargingTerminalProcess(gun_index);
+                }
+
+                // 等待小板通知進入充電
+                // 切換 D+ Relay to Precharge Relay
+                if (pDcChargingInfo->RelayK1K2Status == YES) {
+                    pDcChargingInfo->PrechargeStatus = PRECHARGE_READY;
+                    setChargerMode(gun_index, MODE_CHARGING);
+                }
+
+                if (pSysInfo->CurGunSelected == gun_index) {
+                    pSysInfo->ConnectorPage = _LCM_PRE_CHARGE;
+                    // pSysInfo->SystemPage = _LCM_NONE;
+                }
+                break;
+            }
+            }
+        }
+
+#if defined DD360Audi
+        if (pSysInfo->SystemPage != _LCM_SELECT_GUN) {
+#else
+        if (pSysInfo->SystemPage != _LCM_NONE) {
+#endif //defined DD360Audi
+            ChangeLcmByIndex(pSysInfo->SystemPage);
+        } else {
+            bool dcPageRun = false;
+            if (pGunIndexInfo->AcGunIndex > 0 && pSysInfo->CurGunSelectedByAc != NO_DEFINE) {
+                pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(0);
+
+                if  (pAcChargingInfo->SystemStatus == S_IDLE) {
+                    ChangeLcmByIndex(_LCM_IDLE);
+                } else if (pAcChargingInfo->SystemStatus == S_PREPARNING) {
+                    ChangeLcmByIndex(_LCM_PRE_CHARGE);
+                } else if (pAcChargingInfo->SystemStatus == S_CHARGING) {
+                    ChangeLcmByIndex(_LCM_CHARGING);
+                } else if (pAcChargingInfo->SystemStatus == S_TERMINATING ||
+                           pAcChargingInfo->SystemStatus == S_COMPLETE) {
+                    ChangeLcmByIndex(_LCM_COMPLETE);
+                } else {
+                    dcPageRun = true;
+                }
+            } else {
+                dcPageRun = true;
+            }
+
+            if (dcPageRun) {
+                ChangeLcmByIndex(pSysInfo->ConnectorPage);
+            }
+        }
+
+        for (uint8_t gun_index = 0; gun_index < pSysConfig->TotalConnectorCount; gun_index++) {
+            pDcChargingInfo =  (struct ChargingInfoData *)GetDcChargingInfoData(gun_index);
+
+            checkEvBoardAlarmState(pDcChargingInfo->Type);
+        }
+
+        //write(wtdFd, "a", 1);
+        //WriteWatchDogState("a");
+
+        usleep(whileLoopTime);
+    }
+
+    return FAIL;
+}

+ 29 - 9
EVSE/Projects/DD360/Apps/main.h → EVSE/Projects/DD360/Apps/CSU/main.h

@@ -28,7 +28,7 @@
 #define DEFAULT_AC_INDEX                        2
 #define PSU_MIN_CUR                             100
 
-#define DB_FILE                                 "/Storage/ChargeLog/localCgargingRecord.db"
+//#define DB_FILE                                 "/Storage/ChargeLog/localCgargingRecord.db"
 
 #define uSEC_VAL                                1000000
 #define SELFTEST_TIMEOUT                        60//45
@@ -43,9 +43,9 @@
 #define GUN_COMP_WAIT_TIMEOUT                   10
 #define GUN_PRECHARGING_TIMEOUT                 60
 
-#define log_info(format, args...) StoreLogMsg_1("[%s:%d][%s][Info] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
-#define log_warn(format, args...) StoreLogMsg_1("[%s:%d][%s][Warn] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
-#define log_error(format, args...) StoreLogMsg_1("[%s:%d][%s][Error] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+//#define log_info(format, args...) StoreLogMsg_1("[%s:%d][%s][Info] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+//#define log_warn(format, args...) StoreLogMsg_1("[%s:%d][%s][Warn] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+//#define log_error(format, args...) StoreLogMsg_1("[%s:%d][%s][Error] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
 
 //------------------------------------------------------------------------------
 typedef struct StLedConfig {
@@ -61,18 +61,38 @@ typedef struct StLedConfig {
 } LedConfig;
 
 //------------------------------------------------------------------------------
-bool isDetectPlugin();
-void _DetectPlugInTimeout();
-void StopSystemTimeoutDet();
+bool isDetectPlugin(void);
+void _DetectPlugInTimeout(void);
+void StartSystemTimeoutDet(uint8_t flag);
+void StopSystemTimeoutDet(void);
 
 void StartGunInfoTimeoutDet(uint8_t gunIndex, uint8_t flag);
 void StopGunInfoTimeoutDet(uint8_t gunIndex);
 
-void ClearAuthorizedFlag();
+void AuthorizingStart(void);
+bool IsAuthorizingMode(void);
+bool isAuthorizedComplete(void);
+void ClearAuthorizedFlag(void);
 
 void ChargingAlarmProcess(uint8_t gunIndex);
 void StopChargingProcessByString(uint8_t level);
 
-void AcChargingTerminalProcess();
+void EmcOccureByString(char *code);
+void ReleaseEmsOccureByString(uint8_t index, char *code);
+
+void confirmSelGun(uint8_t selGun);
+void destroySelGun(uint8_t curGun);
+int getConfirmSelectedGun(uint8_t curSel);
+void setSelGunWaitToAuthor(uint8_t curSel);
+
+void ChargingTerminalProcess(uint8_t gunIndex);
+void AcChargingTerminalProcess(void);
+
+void ChangeGunSelectByIndex(uint8_t sel);
+
+void setChargerMode(uint8_t gun_index, uint8_t mode);
+
+void KillAllTask(void);
+void KillTask(void);
 
 #endif /* _MAIN_H_ */

File diff suppressed because it is too large
+ 282 - 256
EVSE/Projects/DD360/Apps/CSU/mainNew.c


+ 2 - 0
EVSE/Projects/DD360/Apps/Config.h

@@ -317,6 +317,8 @@ typedef struct StDcCommonInfo {
     uint8_t CheckRelayStatus[6]; //check Relay welding or driving fault
     uint8_t GunRelayWeldingOccur[2];
     uint8_t GunRelayDrivingOccur[2];
+    uint8_t SystemModeChange;
+    uint8_t Reserved[3];
 } DcCommonInfo;
 
 #endif /* CONFIG_H_ */

+ 54 - 53
EVSE/Projects/DD360/Apps/DataBase/DataBase.c

@@ -9,7 +9,16 @@
 #include "../ShareMemory/shmMem.h"
 
 //------------------------------------------------------------------------------
-int DB_Open(sqlite3 *db)
+#define DB_FILE                                 "/Storage/ChargeLog/localCgargingRecord.db"
+
+//------------------------------------------------------------------------------
+static sqlite3 *localDb;
+
+//------------------------------------------------------------------------------
+//===============================================
+// SQLite3 related routine
+//===============================================
+int DB_Open(void)
 {
     int result = PASS;
     char *errMsg = NULL;
@@ -49,21 +58,21 @@ int DB_Open(sqlite3 *db)
                             "`idx` INTEGER PRIMARY KEY AUTOINCREMENT, "
                             "`rebootDatetime` TEXT NOT NULL, unique(rebootDatetime) on conflict replace);";
 
-    if (sqlite3_open(DB_FILE, &db)) {
+    if (sqlite3_open(DB_FILE, &localDb)) {
         result = FAIL;
-        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(db));
-        sqlite3_close(db);
+        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(localDb));
+        sqlite3_close(localDb);
     } else {
         log_info( "Local charging record database open successfully.\r\n");
 
-        if (sqlite3_exec(db, createRecordSql, 0, 0, &errMsg) != SQLITE_OK) {
+        if (sqlite3_exec(localDb, createRecordSql, 0, 0, &errMsg) != SQLITE_OK) {
             result = FAIL;
             log_info( "Create local charging record table error message: %s\n", errMsg);
         } else {
             log_info( "Opened local charging record table successfully\n");
         }
 
-        if (sqlite3_exec(db, createCfgSql, 0, 0, &errMsg) != SQLITE_OK) {
+        if (sqlite3_exec(localDb, createCfgSql, 0, 0, &errMsg) != SQLITE_OK) {
             result = FAIL;
             log_info( "Create local config table error message: %s\n", errMsg);
         } else {
@@ -71,14 +80,14 @@ int DB_Open(sqlite3 *db)
         }
 
         //DS60-120
-        if (sqlite3_exec(db, createrecordSql, 0, 0, &errMsg) != SQLITE_OK) {
+        if (sqlite3_exec(localDb, createrecordSql, 0, 0, &errMsg) != SQLITE_OK) {
             result = FAIL;
             log_info( "Create local record table error message: %s\n", errMsg);
         } else {
             log_info( "Opened local record table successfully\n");
         }
 
-        if (sqlite3_exec(db, createrebootSql, 0, 0, &errMsg) != SQLITE_OK) {
+        if (sqlite3_exec(localDb, createrebootSql, 0, 0, &errMsg) != SQLITE_OK) {
             result = FAIL;
             log_info( "Create reboot record table error message: %s\n", errMsg);
         } else {
@@ -86,49 +95,41 @@ int DB_Open(sqlite3 *db)
         }
         //-----
 
-        sqlite3_close(db);
+        sqlite3_close(localDb);
     }
 
     return result;
 }
 
-int DB_Insert_Record(sqlite3 *db, int gun_index)
+int DB_Insert_Record(int gun_index)
 {
     int result = PASS;
     char *errMsg = NULL;
     char insertSql[1024];
+    struct ChargingInfoData *pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun_index);
+    struct OCPP16Data *ShmOCPP16Data = (struct OCPP16Data *)GetShmOCPP16Data();
 
     sprintf(insertSql, "insert into charging_record(reservationId, transactionId, startMethod, userId, dateTimeStart, dateTimeStop, socStart, socStop, chargeEnergy, stopReason) "
             "values('%d', '%d', '%d', '%s', '%s', '%s', '%d', '%d', '%f', '%s');",
-            chargingInfo[gun_index]->ReservationId, //DS60-120 add
+            pDcChargingInfo->ReservationId, //DS60-120 add
             ShmOCPP16Data->StartTransaction[gun_index].ResponseTransactionId,
-            chargingInfo[gun_index]->StartMethod,
-            chargingInfo[gun_index]->StartUserId,
-            chargingInfo[gun_index]->StartDateTime,
-            chargingInfo[gun_index]->StopDateTime,
-            chargingInfo[gun_index]->EvBatteryStartSoc,
-            chargingInfo[gun_index]->EvBatterySoc,
-            chargingInfo[gun_index]->PresentChargedEnergy,
-            //DS60-120 remove
-            //ShmSysConfigAndInfo->SysInfo.AcChargingData[gun_index].ReservationId,
-            //ShmOCPP16Data->StartTransaction[gun_index].ResponseTransactionId,
-            //ShmSysConfigAndInfo->SysInfo.AcChargingData[gun_index].StartMethod,
-            //ShmSysConfigAndInfo->SysInfo.AcChargingData[gun_index].StartUserId,
-            //ShmSysConfigAndInfo->SysInfo.AcChargingData[gun_index].StartDateTime,
-            //ShmSysConfigAndInfo->SysInfo.AcChargingData[gun_index].StopDateTime,
-            //ShmSysConfigAndInfo->SysInfo.AcChargingData[gun_index].EvBatterySoc,
-            //ShmSysConfigAndInfo->SysInfo.AcChargingData[gun_index].EvBatterySoc,
-            //ShmSysConfigAndInfo->SysInfo.AcChargingData[gun_index].PresentChargedEnergy,
+            pDcChargingInfo->StartMethod,
+            pDcChargingInfo->StartUserId,
+            pDcChargingInfo->StartDateTime,
+            pDcChargingInfo->StopDateTime,
+            pDcChargingInfo->EvBatteryStartSoc,
+            pDcChargingInfo->EvBatterySoc,
+            pDcChargingInfo->PresentChargedEnergy,
             ShmOCPP16Data->StopTransaction[gun_index].StopReason);
 
     //if (sqlite3_open("/Storage/ChargeLog/localCgargingRecord.db", &db)) {
-    if (sqlite3_open(DB_FILE, &db)) { //DS60-120 add
+    if (sqlite3_open(DB_FILE, &localDb)) { //DS60-120 add
         result = FAIL;
-        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(db));
-        sqlite3_close(db);
+        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(localDb));
+        sqlite3_close(localDb);
     } else {
         log_info( "Local charging record database open successfully.\r\n");
-        if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
+        if (sqlite3_exec(localDb, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
             result = FAIL;
             log_info( "Insert local charging record error message: %s\n", errMsg);
         } else {
@@ -137,50 +138,50 @@ int DB_Insert_Record(sqlite3 *db, int gun_index)
 
         //DS60-120 add
         sprintf(insertSql, "delete from charging_record where idx < (select idx from charging_record order by idx desc limit 1)-2000;");
-        if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
+        if (sqlite3_exec(localDb, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
             result = FAIL;
             log_info( "delete local charging error message: %s\n", errMsg);
         } else {
             log_info( "delete local charging record successfully\n");
         }
 
-        sqlite3_close(db);
+        sqlite3_close(localDb);
     }
 
     return result;
 }
 
-int DB_Update_Operactive(sqlite3 *db, uint8_t gun_index, uint8_t IsAvailable)
+int DB_Update_Operactive(uint8_t gun_index, uint8_t IsAvailable)
 {
     uint8_t result = false;
     char *errMsg = NULL;
     char sqlStr[1024];
     srand(time(NULL));
 
-    if (sqlite3_open(DB_FILE, &db)) {
+    if (sqlite3_open(DB_FILE, &localDb)) {
         result = FAIL;
-        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(db));
-        sqlite3_close(db);
+        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(localDb));
+        sqlite3_close(localDb);
     } else {
         log_info( "Local charging record database open successfully (%d).\r\n", IsAvailable);
 
         //sprintf(sqlStr, "insert or replace into config (IsAvailable, connector, val) values('IsAvailable', %d, %d);", gun_index, IsAvailable);
         sprintf(sqlStr, "insert or replace into config (item, connector, val) values('IsAvailable', %d, %d);", gun_index, IsAvailable); //DS60-120 add
         log_info("sqlStr= %s\r\n", sqlStr);
-        if (sqlite3_exec(db, sqlStr, 0, 0, &errMsg) != SQLITE_OK) {
+        if (sqlite3_exec(localDb, sqlStr, 0, 0, &errMsg) != SQLITE_OK) {
             result = FAIL;
             log_info( "update config error message: %s\n", errMsg);
         } else {
             log_info("update connector-%d config item isOperactive to %d\r\n", gun_index, IsAvailable);
         }
 
-        sqlite3_close(db);
+        sqlite3_close(localDb);
     }
 
     return result;
 }
 
-int DB_Get_Operactive(sqlite3 *db, uint8_t gun_index)
+int DB_Get_Operactive(uint8_t gun_index)
 {
     uint8_t result = true;
     char *errMsg = NULL;
@@ -192,13 +193,13 @@ int DB_Get_Operactive(sqlite3 *db, uint8_t gun_index)
     sprintf(sqlStr, "select * from config where item='IsAvailable' and connector=%d;", gun_index); //DS60-120 add
     //DEBUG_INFO("sqlStr= %s\r\n", sqlStr);
 
-    if (sqlite3_open(DB_FILE, &db)) {
+    if (sqlite3_open(DB_FILE, &localDb)) {
         result = FAIL;
-        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(db));
-        sqlite3_close(db);
+        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(localDb));
+        sqlite3_close(localDb);
     } else {
         log_info( "Local config query database open successfully.\r\n");
-        sqlite3_get_table(db, sqlStr, &rs, &rows, &cols, &errMsg);
+        sqlite3_get_table(localDb, sqlStr, &rs, &rows, &cols, &errMsg);
         if (rows > 0) {
             for (int idxRow = 1; idxRow <= rows; idxRow++) {
                 if (strcmp(rs[(idxRow * cols) + 3], "0") == 0) {
@@ -211,13 +212,13 @@ int DB_Get_Operactive(sqlite3 *db, uint8_t gun_index)
         }
 
         sqlite3_free_table(rs);
-        sqlite3_close(db);
+        sqlite3_close(localDb);
     }
 
     return result;
 }
 
-int DB_Reboot_Record(sqlite3 *db)
+int DB_Reboot_Record(void)
 {
     int result = PASS;
     char *errMsg = NULL;
@@ -225,13 +226,13 @@ int DB_Reboot_Record(sqlite3 *db)
 
     sprintf(insertSql, "insert into reboot_record(rebootDatetime) values(CURRENT_TIMESTAMP);");
 
-    if (sqlite3_open(DB_FILE, &db)) {
+    if (sqlite3_open(DB_FILE, &localDb)) {
         result = FAIL;
-        log_info( "Can't open database: %s\n", sqlite3_errmsg(db));
-        sqlite3_close(db);
+        log_info( "Can't open database: %s\n", sqlite3_errmsg(localDb));
+        sqlite3_close(localDb);
     } else {
         log_info( "Local charging record database open successfully.\n");
-        if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
+        if (sqlite3_exec(localDb, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
             result = FAIL;
             log_info( "Insert reboot record error message: %s\n", errMsg);
         } else {
@@ -239,14 +240,14 @@ int DB_Reboot_Record(sqlite3 *db)
         }
 
         sprintf(insertSql, "delete from reboot_record where idx < (select idx from charging_record order by idx desc limit 1)-2000;");
-        if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
+        if (sqlite3_exec(localDb, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
             result = FAIL;
             log_info( "delete reboot record error message: %s\n", errMsg);
         } else {
             log_info( "delete reboot record successfully\n");
         }
 
-        sqlite3_close(db);
+        sqlite3_close(localDb);
     }
 
     return result;

+ 15 - 10
EVSE/Projects/DD360/Apps/Makefile

@@ -16,6 +16,7 @@ INC_FLAGS += -I $(TOP)/Define
 INC_FLAGS += -I $(TOP)/Log
 INC_FLAGS += -I $(TOP)/ShareMemory
 INC_FLAGS += -I $(TOP)/CSU
+INC_FLAGS += -I $(TOP)/DataBase
 INC_FLAGS += -I $(TOP)/ModuleInternalComm
 INC_FLAGS += -I $(TOP)/ModuleEvComm
 INC_FLAGS += -I $(TOP)/ModulePrimary
@@ -27,6 +28,7 @@ DefineLib = $(TOP)/Define
 LogLib = $(TOP)/Log
 ShmMemLib = $(TOP)/ShareMemory
 CSULib = $(TOP)/CSU
+DataBaseLib = $(TOP)/DataBase
 InternalCommLib = $(TOP)/ModuleInternalComm
 EvCommLib = $(TOP)/ModuleEvComm
 PrimaryLib = $(TOP)/ModulePrimary
@@ -62,10 +64,13 @@ COMMON_OBJ_FILES = common.o \
 					$(DefineLib)/define.o \
 					$(ShmMemLib)/shmMem.o \
 					$(LogLib)/log.o \
-					$(SelectGunLib)/SelectGun.o
-#main
-MAIN_OBJ_FILES = $(COMMON_OBJ_FILES) $(SQLite3_H) $(ModuleUpgrade_H) $(RFID_H) $(Lib_Module_RatedCurrent) \
-					main.o $(CSULib)/Primary.o
+					$(SelectGunLib)/SelectGun.o \
+
+
+MAIN_OBJ_FILES = $(COMMON_OBJ_FILES) $(DataBaseLib)/DataBase.o \
+					$(CSULib)/main.o  $(CSULib)/Primary.o $(CSULib)/WatchDog.o $(CSULib)/ZipFile.o \
+					$(CSULib)/RFID.o $(CSULib)/SelfTest.o $(CSULib)/UpgradeFW.o \
+					$(CSULib)/Ethernet.o
 MAIN_SRC_FILES = $(patsubst %.o, %.c, $(MAIN_OBJ_FILES))
 %.o: %.c
 	$(CC) $(CFLAGS) -c $<
@@ -95,8 +100,8 @@ apps: MainTask DoCommTask EvCommTask \
 				FactoryConfigApp OtherTools CleanExec
 
 MainTask:
-	#$(CC) $(DEFINE) $(MAIN_SRC_FILES) $(CFLAGS) $(TFLAGS) $(INC_FLAGS) ${Lib_Module_RFID} \
-	#	 ${Lib_Module_Upgrade} ${Lib_SQLite3} $(Lib_Module_RatedCurrent) -o main
+	#$(CC) $(DEFINE) $(MAIN_SRC_FILES) $(CFLAGS) $(TFLAGS) $(INC_FLAGS) $(SQLite3_H) $(ModuleUpgrade_H) $(RateCurrent_H) \
+	#	$(RFID_H) $(Lib_Module_RFID) $(Lib_Module_Upgrade) $(Lib_SQLite3) $(Lib_Module_RateCurrent) -o main
 	$(CC) $(DEFINE) $(SQLite3_H) $(ModuleUpgrade_H) $(RFID_H) $(RatedCurrent_H) $(CFLAGS) -c -o main.o main.c
 	$(CC) $(DEFINE) $(SQLite3_H) $(ModuleUpgrade_H) $(RFID_H) $(RatedCurrent_H) $(CFLAGS) -c -o timeout.o timeout.c
 	$(CC) $(DEFINE) $(CFLAGS) -c -o common.o common.c
@@ -108,10 +113,10 @@ DoCommTask:
 	$(CC) -o Module_DoComm DoComm.o define.o
 
 EvCommTask:
-	$(CC) $(DEFINE) $(EVCOMM_SRC_FILES) $(CFLAGS) $(TFLAGS) $(INC_FLAGS) $(Lib_Module_RatedCurrent) -o Module_EvComm
-	#$(CC) $(DEFINE) $(CFLAGS) $(RatedCurrent_H) -c -o Ev_Comm.o $(EvCommLib)/Ev_Comm.c
-	#$(CC) $(DEFINE) $(CFLAGS) $(RatedCurrent_H) -c -o Module_EvComm.o $(EvCommLib)/Module_EvComm.c
-	#$(CC) -o Module_EvComm Ev_Comm.o Module_EvComm.o $(Lib_Module_RatedCurrent)
+	#$(CC) $(DEFINE) $(EVCOMM_SRC_FILES) $(CFLAGS) $(TFLAGS) $(INC_FLAGS) $(Lib_Module_RatedCurrent) -o Module_EvComm
+	$(CC) $(DEFINE) $(CFLAGS) $(RatedCurrent_H) -c -o Ev_Comm.o $(EvCommLib)/Ev_Comm.c
+	$(CC) $(DEFINE) $(CFLAGS) $(RatedCurrent_H) -c -o Module_EvComm.o $(EvCommLib)/Module_EvComm.c
+	$(CC) -o Module_EvComm Ev_Comm.o Module_EvComm.o $(Lib_Module_RatedCurrent)
 
 EventLoggingTask:
 	$(CC) $(DEFINE) $(CFLAGS) -c -o define.o $(DefineLib)/define.c

+ 2 - 2
EVSE/Projects/DD360/Apps/ModuleEvComm/Module_EvComm.c

@@ -2228,7 +2228,7 @@ static float ReadAdcVolt(uint8_t AdcChannel)
     //AIN3=pilot voltage
     int fd = -1;
     uint8_t str[64] = {0};
-    uint8_t AdcValue[4] = {0};
+    uint8_t AdcValue[8] = {'\0'};
 
     if (AdcChannel > 7) {
         return -1;
@@ -2240,7 +2240,7 @@ static float ReadAdcVolt(uint8_t AdcChannel)
 
     close(fd);
 
-    return (1.8 * atoi((int)AdcValue)) / 4095;
+    return (1.8 * atoi((char *)&AdcValue[0])) / 4095;
 }
 
 static void getChillerTemperature(ChillerTemp *chillerTemp)

+ 31 - 29
EVSE/Projects/DD360/Apps/ModuleEvComm/Module_EvRxComm.c

@@ -96,22 +96,22 @@ static float ReadAdcVolt(uint8_t AdcChannel)
     //AIN2=CCS_Proximity/2
     //AIN3=pilot voltage
     int fd = -1;
-    uint8_t str[64];
-    uint8_t AdcValue[4];
+    uint8_t str[64] = {0};
+    uint8_t AdcValue[8] = {'\0'};
+    //uint32_t AdcValue = 0;
 
     if (AdcChannel > 7) {
         return -1;
     }
 
-    memset(str, 0, sizeof(str));
-    memset(AdcValue, 0, sizeof(AdcValue));
     sprintf((char *)str, "/sys/bus/iio/devices/iio\:device0/in_voltage%d_raw", AdcChannel);
     fd = open((char *)str, O_RDONLY);
     read(fd, AdcValue, 4);
 
     close(fd);
 
-    return (1.8 * atoi((int)AdcValue)) / 4095;
+    return (1.8 * atoi((char *)&AdcValue[0])) / 4095;
+    //return (1.8 * atoi((char *)&AdcValue)) / 4095;
 }
 
 static void getChillerTemperature(ChillerTemp *chillerTemp)
@@ -124,14 +124,14 @@ static void getChillerTemperature(ChillerTemp *chillerTemp)
         adcVoltage = 0.0;
         adcVoltage =  ReadAdcVolt(i);
         if ((adcVoltage <= 0.9) && (adcVoltage >= 0.8)) { //0 ~ -40
-            chillerTemp->Temp[i] = ((adcVoltage - 0.908) * 500) + 60;
+            pChillerTemp->Temp[i] = ((adcVoltage - 0.908) * 500) + 60;
             //log_info("1 adcVoltage = %f", (adcVoltage - 0.9) * 500);
         } else if ((adcVoltage <= 1.07) && (adcVoltage > 0.9)) {
-            chillerTemp->Temp[i] = ((adcVoltage - 0.91) * 705.88) + 60;
+            pChillerTemp->Temp[i] = ((adcVoltage - 0.91) * 705.88) + 60;
             //log_info("2 adcVoltage = %f", (adcVoltage - 0.9) * 500);
-        } /*else {
-            chillerTemp->Temp[i] = 195;
-        }*/
+        } else {
+            pChillerTemp->Temp[i] = 195;
+        }
 
         //CcsConnectorTemp1 = ReadAdcVolt(i);
         //if ((CcsConnectorTemp1 <= 0.9) && (CcsConnectorTemp1 >= 0.8)) { //0 ~ -40
@@ -182,7 +182,6 @@ static void AddrAssignment(uint8_t *data)
     //}
 }
 
-
 void CANReceiver(int fd)
 {
     pid_t canRecPid;
@@ -211,7 +210,7 @@ void CANReceiver(int fd)
         ShmCHAdeMOData = (struct CHAdeMOData *)GetShmCHAdeMOData();
         ShmGBTData = (struct GBTData *)GetShmGBTData();
         ShmCcsData = (struct CcsData *)GetShmCcsData();
-        ShmDcCommonData = (DcCommonInfo *)GetShmDcCommonInfo();
+        ShmDcCommonData = (DcCommonInfo *)GetShmDcCommonData();
 
         while (isContinue) {
             memset(&frame, 0, sizeof(struct can_frame));
@@ -493,23 +492,26 @@ void CANReceiver(int fd)
                     //         pDcChargingInfo->ConnectorTemp);
                 }
 #endif //0
-                //log_info("EvboardStatus = %x \n",
-                //         ShmCHAdeMOData->evse[gunTypeIndex].EvboardStatus);
-                //log_info("ConnectorPlug locked = %x \n",
-                //         frame.data[0]);
-
-                //if (frame.data[1] >= GUN_OTP_VALUE ||
-                //        frame.data[2] >= GUN_OTP_VALUE ||
-                //        chiilerTemp.Temp[0] >= GUN_OTP_VALUE ||
-                //        chiilerTemp.Temp[1] >= GUN_OTP_VALUE) {
-                //    log_info("Conn %d Temp 0= %d, Temp 1 = %d, chillerTemp1 = %d, chillerTemp2 = %d\r\n",
-                //             targetGun,
-                //             frame.data[1],
-                //             frame.data[2],
-                //             chiilerTemp.Temp[0],
-                //             chiilerTemp.Temp[1]);
-                //}
-                //log_info("PilotVoltage = %x \n", (-120 + frame.data[3]) / 10);
+                if (ShmDcCommonData->SystemModeChange == YES) {
+                    ShmDcCommonData->SystemModeChange = NO;
+                    //log_info("EvboardStatus = %x \n",
+                    //         ShmCHAdeMOData->evse[gunTypeIndex].EvboardStatus);
+                    //log_info("ConnectorPlug locked = %x \n",
+                    //         frame.data[0]);
+
+                    //if (frame.data[1] >= GUN_OTP_VALUE ||
+                    //        frame.data[2] >= GUN_OTP_VALUE ||
+                    //        chiilerTemp.Temp[0] >= GUN_OTP_VALUE ||
+                    //        chiilerTemp.Temp[1] >= GUN_OTP_VALUE) {
+                    log_info("Conn %d Temp 0= %d, Temp 1 = %d, chillerTemp1 = %d, chillerTemp2 = %d\r\n",
+                             targetGun,
+                             frame.data[1],
+                             frame.data[2],
+                             chiilerTemp.Temp[0],
+                             chiilerTemp.Temp[1]);
+                    //}
+                    //log_info("PilotVoltage = %x \n", (-120 + frame.data[3]) / 10);
+                }
                 break;
 
             case ACK_EVSE_ISOLATION_STATUS:

+ 2 - 2
EVSE/Projects/DD360/Apps/ModuleEvComm/Module_EvTxComm.c

@@ -484,7 +484,7 @@ static void checkConnectorOVPState(uint8_t gunIndex)
     struct ChargingInfoData *pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
 
     // 避免槍溫偵測誤判
-    static uint8_t gunTempAllowCount[2] = {0, 0};
+    static uint8_t gunTempAllowCount[2] = {0};
     bool isOTP = false;
 
     switch (pDcChargingInfo->Type) {
@@ -593,7 +593,7 @@ int main(int argc, char *argv[])
     pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
     pAlarmCode = (struct AlarmCodeData *)GetShmAlarmCodeData();
     pFaultCode = (struct FaultCodeData *)GetShmFaultCodeData();
-    ShmDcCommonData = (DcCommonInfo *)GetShmDcCommonInfo();
+    ShmDcCommonData = (DcCommonInfo *)GetShmDcCommonData();
     ShmCHAdeMOData = (struct CHAdeMOData *)GetShmCHAdeMOData();
     ShmGBTData = (struct GBTData *)GetShmGBTData();
     ShmCcsData = (struct CcsData *)GetShmCcsData();

+ 2 - 1
EVSE/Projects/DD360/Apps/ModuleInternalComm/RelayBoard.c

@@ -1131,7 +1131,7 @@ void RelayBoardTask(int uartFD)
         pAlarmCode = (struct AlarmCodeData *)GetShmAlarmCodeData();
         ShmRelayModuleData = (struct RelayModuleData *)GetShmRelayModuleData();
         ShmPsuData = (struct PsuData *)GetShmPsuData();
-        ShmDcCommonData = (DcCommonInfo *)GetShmDcCommonInfo();
+        ShmDcCommonData = (DcCommonInfo *)GetShmDcCommonData();
         ShmPrimaryMcuData = (struct PrimaryMcuData *)GetShmPrimaryMcuData();
 
         Uart5Fd = uartFD;
@@ -1284,6 +1284,7 @@ void RelayBoardTask(int uartFD)
                     //regRelay.relay_event.bits.Gun1_Parallel_N = outputRelay.relay_event.bits.Gun1_Parallel_N;
 
                     //MatchRelayStatus();
+
                     //log_info("Match Relay, AC = %x, g1_p = %x, g1_n = %x, g2_p = %x, g2_n = %x, pre = %x, bri_p = %x, bri_n = %x \n",
                     //         regRelay.relay_event.bits.AC_Contactor,
                     //         regRelay.relay_event.bits.Gun1_P,

+ 22 - 12
EVSE/Projects/DD360/Apps/ShareMemory/shmMem.c

@@ -40,7 +40,7 @@ static struct LedModuleData *ShmLedModuleData = NULL;
 static struct OCPP16Data *ShmOCPP16Data = NULL;
 
 static SelectGunInfo *ShmSelectGunInfo = NULL;
-static DcCommonInfo *ShmDcCommonInfo = NULL;
+static DcCommonInfo *ShmDcCommonData = NULL;
 
 static struct ChargingInfoData *DcChargingData[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY] = {NULL};
 static struct ChargingInfoData *AcChargingData[AC_QUANTITY] = {NULL};
@@ -51,7 +51,7 @@ static GunIndexInfo gGunIndexInfo = {0};
 //struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
 //struct WARNING_CODE_INFO *pSysWarning = (struct WARNING_CODE_INFO *)GetShmSysWarningInfo();
 
-//struct AlarmCodeData *pAlarmCode =(struct AlarmCodeData *)GetShmAlarmCodeData();
+//struct AlarmCodeData *pAlarmCode = (struct AlarmCodeData *)GetShmAlarmCodeData();
 //struct InfoCodeData *pInfoCode = (struct InfoCodeData *)GetShmInfoCodeData();
 //struct FaultCodeData *pFaultCode = (struct FaultCodeData *)GetShmFaultCodeData();
 
@@ -68,7 +68,10 @@ static GunIndexInfo gGunIndexInfo = {0};
 //struct OCPP16Data *ShmOCPP16Data = (struct OCPP16Data *)GetShmOCPP16Data();
 
 //SelectGunInfo *ShmSelectGunInfo = (SelectGunInfo *)GetShmSelectGunInfo();
-//DcCommonInfo *ShmDcCommonInfo = (DcCommonInfo *)GetShmDcCommonInfo();
+//DcCommonInfo *ShmDcCommonData = (DcCommonInfo *)GetShmDcCommonData();
+
+//struct ChargingInfoData *pDcChargingInfo = NULL;
+//struct ChargingInfoData *pAcChargingInfo = NULL;
 
 //------------------------------------------------------------------------------
 void *GetGunIndexInfo(void)
@@ -306,17 +309,17 @@ void *GetShmSelectGunInfo(void)
     return ShmSelectGunInfo;
 }
 
-void *GetShmDcCommonInfo(void)
+void *GetShmDcCommonData(void)
 {
-    if (ShmDcCommonInfo == NULL) {
+    if (ShmDcCommonData == NULL) {
         return NULL;
     }
 
-    return ShmDcCommonInfo;
+    return ShmDcCommonData;
 }
 
 //------------------------------------------------------------------------------
-/*static void initialGunIndexToUnUse(void)
+static void initialGunIndexToUnUse(void)
 {
     uint8_t index = 0;
     struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
@@ -337,7 +340,6 @@ void *GetShmDcCommonInfo(void)
         pSysInfo->AcChargingData[index].Index = NO_DEFINE;
     }
 }
-*/
 
 #if 0
 static void getFirmwareVersion(void)
@@ -424,7 +426,7 @@ static void getFirmwareVersion(void)
 }
 #endif //0
 
-void InitialShareMemoryParameter(void)
+void InitialShareMemoryInfo(void)
 {
     FILE *fp = NULL;
     char cmd[512] = {0};
@@ -532,7 +534,15 @@ void InitialShareMemoryParameter(void)
     pAlarmCode->AlarmEvents.bits.ModelNameNoneMatchStestFail = NO;
     pAlarmCode->AlarmEvents.bits.PsuNoResource = NO;
     pAlarmCode->AlarmEvents.bits.FailToCreateShareMemory = NO;
-    //initialGunIndexToUnUse();//DS60-120 add
+
+    initialGunIndexToUnUse();//DS60-120 add
+
+    //ShmDcCommonData->CcsVersion = _CCS_VERSION_CHECK_TAG_V015S0;
+    //ShmDcCommonData->psuKeepCommunication = NO;
+    //ShmDcCommonData->acContactSwitch = NO;
+    ShmDcCommonData->ConnectErrList[0].GunErrMessage = 0;
+    ShmDcCommonData->ConnectErrList[1].GunErrMessage = 0;
+    //ShmDcCommonData->LcmFwVersion = 0;
 }
 
 int InitSelectGunShmMem(void)
@@ -558,7 +568,7 @@ int InitCommonShmMem(void)
 
     if ((MeterSMId = shmget(ShmCommonKey, sizeof(DcCommonInfo), IPC_CREAT | 0777)) < 0) {
         return FAIL;
-    } else if ((ShmDcCommonInfo = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+    } else if ((ShmDcCommonData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
         return FAIL;
     }
 
@@ -750,7 +760,7 @@ void ClearAllShmMemParameter(void)
     //memset(ShmOCPP16Data,0,sizeof(struct OCPP16Data));
 
     //memset(ShmCsuMeterInfo, 0, sizeof(struct MeterInformation));
-    memset(ShmDcCommonInfo, 0, sizeof(DcCommonInfo));
+    memset(ShmDcCommonData, 0, sizeof(DcCommonInfo));
 
 #if defined DD360 || defined DD360Audi || defined DD360ComBox
     memset(ShmSelectGunInfo, 0, sizeof(SelectGunInfo));

+ 1 - 4
EVSE/Projects/DD360/Apps/ShareMemory/shmMem.h

@@ -28,7 +28,7 @@ bool MappingGunChargingInfo(char *whichTask);
 
 int CreateAllCsuShareMemory(void);
 void ClearAllShmMemParameter(void);
-void InitialShareMemoryParameter(void);
+void InitialShareMemoryInfo(void);
 
 void SetDcChargingInfoData(uint8_t index, struct ChargingInfoData *chargingInfoIndex);
 void *GetDcChargingInfoData(uint8_t index);
@@ -66,8 +66,5 @@ void MappingChargingInfoData(void);
 
 void *GetShmSelectGunInfo(void);
 
-void *GetShmDcCommonInfo(void);
-
-
 int InitSelectGunShmMem(void);
 #endif /* _CSU_SHARE_MEMORY_H_ */

+ 60 - 3
EVSE/Projects/DD360/Apps/main.c

@@ -27,12 +27,12 @@
 #include <ctype.h>
 #include <ifaddrs.h>
 #include <math.h>
-#include "./Define/define.h"
+#include "../../define.h"
 #include <stdbool.h>
 #include <dirent.h>
 
 #include "Config.h"
-#include "main.h"
+//#include "main.h"
 #include "common.h"
 #include "timeout.h"
 
@@ -40,6 +40,62 @@
 #include "./SelectGun/SelectGun.h"
 #endif //defined DD360Audi
 
+//------------------------------------------------------------------------------
+#define MODELNAME_FAIL                          0
+#define BUFFER_SIZE                             128
+#define BTN_RELEASE                             0
+#define BTN_PRESS                               1
+#define MAX_BUF                                 64
+#define MtdBlockSize                            0x600000
+#define SYSFS_GPIO_DIR                          "/sys/class/gpio"
+#define UPGRADE_FAN                             0x02
+#if defined DD360 ||defined DD360Audi || defined DD360ComBox
+#define UPGRADE_RB                              0x09 //0x09 for DD360 dispenser
+#else
+#define UPGRADE_RB                              0x03 //other module use
+#endif //defined DD360 || defined DD360Audi
+#define UPGRADE_PRI                             0x04
+#define UPGRADE_AC                              0x05
+#define UPGRADE_LED                             0x06
+#define SYSTEM_MIN_VOL                          80 //150
+#define MIN_OUTPUT_CUR                          0
+#define AC_OUTPUT_VOL                           220
+
+#define DEFAULT_AC_INDEX                        2
+#define PSU_MIN_CUR                             100
+
+#define DB_FILE                                 "/Storage/ChargeLog/localCgargingRecord.db"
+
+#define uSEC_VAL                                1000000
+#define SELFTEST_TIMEOUT                        60//45
+#define AUTHORIZE_TIMEOUT                       15//30
+#define AUTHORIZE_COMP_TIMEOUT                  3
+#define AUTHORIZE_FAIL_TIMEOUT                  3
+#define AUTHORIZE_STOP_TIMEOUT                  30
+#define RETURN_TO_CHARGING_PAGE                 30
+#define GUN_PREPARE_TIMEOUT                     30
+#define GUN_EV_WAIT_TIMEOUT                     120
+#define GUN_EVSE_WAIT_TIMEOUT                   60
+#define GUN_COMP_WAIT_TIMEOUT                   10
+#define GUN_PRECHARGING_TIMEOUT                 60
+
+#define log_info(format, args...) StoreLogMsg_1("[%s:%d][%s][Info] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+#define log_warn(format, args...) StoreLogMsg_1("[%s:%d][%s][Warn] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+#define log_error(format, args...) StoreLogMsg_1("[%s:%d][%s][Error] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+
+//------------------------------------------------------------------------------
+typedef struct StLedConfig {
+    //OutputDrvValue[0]
+    uint8_t LeftButtonLed: 1;                   //bit 0,    H: ON,      L:OFF
+    uint8_t RightButtonLed: 1;                  //bit 1,    H: ON,      L:OFF
+    uint8_t GreenLED: 1;                        //bit 2,    H: ON,      L:OFF
+    uint8_t YellowLED: 1;                       //bit 3,    H: ON,      L:OFF
+    uint8_t RedLED: 1;                          //bit 4,    H: ON,      L:OFF
+    uint8_t SystemLed4: 1;                      //bit 5,    H: ON,      L:OFF
+    uint8_t AcContactor: 1;                     //bit 6,    H: ON,      L:OFF
+    uint8_t Reserved: 1;                        //bit 7 reserved
+} LedConfig;
+
 //------------------------------------------------------------------------------
 char *valid_Internet[2] = {"8.8.8.8", "180.76.76.76"};
 uint8_t mask_table[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
@@ -306,7 +362,8 @@ static void checkGunOTPState(uint8_t _index)
     case _Type_CCS_2:
         // CCS 不管甚麼輸出都會有槍溫偵測!!~
         if (chargingInfo[_index]->ConnectorTemp != UNDEFINED_TEMP) {
-            ResetChargerAlarmCode(_index, "011019");
+            ResetChargerAlarmCode(_index, "011019"); //清除溫度檢測異常status code
+
             if (chargingInfo[_index]->ConnectorTemp >= GUN_OTP_VALUE) {
                 RecordAlarmCode(_index, "012230");
             } else if (chargingInfo[_index]->ConnectorTemp != 0 &&

+ 0 - 17
EVSE/Projects/DD360Audi/Apps/CSU/AcPlug.c

@@ -1,17 +0,0 @@
-#include <stdio.h>      /*標準輸入輸出定義*/
-#include <stdlib.h>     /*標準函數庫定義*/
-#include <string.h>
-#include <stdint.h>
-
-#include "../Config.h"
-#include "../Log/log.h"
-#include "../Define/define.h"
-#include "../ShareMemory/shmMem.h"
-
-//------------------------------------------------------------------------------
-void AcChargingTerminalProcess(void)
-{
-    struct ChargingInfoData *pAcChargingInfoData = (struct ChargingInfoData *)GetAcChargingInfoData(0);
-
-    pAcChargingInfoData->SystemStatus = MODE_TERMINATING;
-}

+ 278 - 0
EVSE/Projects/DD360Audi/Apps/CSU/Ethernet.c

@@ -0,0 +1,278 @@
+#include <stdio.h>      /*標準輸入輸出定義*/
+#include <stdlib.h>     /*標準函數庫定義*/
+#include <string.h>
+#include <stdint.h>
+
+#include "../Config.h"
+#include "../Log/log.h"
+#include "../Define/define.h"
+#include "../ShareMemory/shmMem.h"
+
+#include "../common.h"
+
+//------------------------------------------------------------------------------
+void GetMacAddress(void)
+{
+    uint8_t index = 0;
+    struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
+
+    for (index = 0; index < 2; index++) {
+        int fd;
+        struct ifreq ifr;
+        char tarEth[5];
+        char Mac[18];
+
+        sprintf(tarEth, "eth%d", index);
+        fd = socket(AF_INET, SOCK_DGRAM, 0);
+
+        ifr.ifr_addr.sa_family = AF_INET;
+        strncpy(ifr.ifr_name, tarEth, IFNAMSIZ - 1);
+
+        ioctl(fd, SIOCGIFHWADDR, &ifr);
+        close(fd);
+
+        sprintf(Mac, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
+                ifr.ifr_hwaddr.sa_data[0],
+                ifr.ifr_hwaddr.sa_data[1],
+                ifr.ifr_hwaddr.sa_data[2],
+                ifr.ifr_hwaddr.sa_data[3],
+                ifr.ifr_hwaddr.sa_data[4],
+                ifr.ifr_hwaddr.sa_data[5]
+               );
+
+        if (index == 0) {
+            strcpy((char *) pSysConfig->Eth0Interface.EthMacAddress, Mac);
+        } else {
+            strcpy((char *) pSysConfig->Eth1Interface.EthMacAddress, Mac);
+        }
+    }
+}
+
+static int isRouteFail(void)
+{
+    int result = YES;
+    FILE *fp;
+    char buf[512];
+
+    fp = popen("route -n", "r");
+    if (fp != NULL) {
+        while (fgets(buf, sizeof(buf), fp) != NULL) {
+            if (strstr(buf, "eth0") != NULL) {
+                result = NO;
+            }
+        }
+    }
+    pclose(fp);
+
+    return result;
+}
+
+static int isReachableInternet(void)
+{
+    int result = FAIL;
+    FILE *fp;
+    char cmd[256];
+    char buf[512];
+    char tmp[512];
+    struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
+    struct AlarmCodeData *pAlarmCode = (struct AlarmCodeData *)GetShmAlarmCodeData();
+
+    strcpy(cmd, "ifconfig eth0");
+    fp = popen(cmd, "r");
+
+    if (fp != NULL) {
+        while (fgets(buf, sizeof(buf), fp) != NULL) {
+            if (strstr(buf, "inet addr:") > 0) {
+                sscanf(buf, "%*s%s", tmp);
+                substr(tmp, tmp, strspn(tmp, "addr:"), strlen(buf) - strspn(tmp, "addr:"));
+
+                if (strcmp(tmp, (char *)pSysConfig->Eth0Interface.EthIpAddress) != EQUAL) {
+                    strcpy((char *) pSysConfig->Eth0Interface.EthIpAddress, tmp);
+                }
+            }
+        }
+    }
+    pclose(fp);
+
+#if defined DD360 ||defined DD360Audi || defined DD360ComBox
+    if (pAlarmCode->AlarmEvents.bits.DisconnectedFromDo == NORMAL) {
+        result = FAIL;
+    } else {
+        result = PASS;
+    }
+#else
+    memset(buf, 0x00, sizeof(buf));
+    for (int idx = 0; idx < ARRAY_SIZE(valid_Internet); idx++) {
+        sprintf(cmd, "ping -c 1 -w 3 -I eth0 %s", valid_Internet[idx]);
+        fp = popen(cmd, "r");
+        if (fp != NULL) {
+            while (fgets(buf, sizeof(buf), fp) != NULL) {
+                if (strstr(buf, "transmitted") > 0) {
+                    //sscanf(buf, "%*s%*s%*s%*s%*s%*s%s", tmp);
+
+                    if (strstr(buf, "100%") != NULL) {
+                    } else {
+                        result = PASS;
+                    }
+                    //DEBUG_INFO("%s",buf);
+                    //DEBUG_INFO("%s\n",tmp);
+                }
+            }
+        }
+        pclose(fp);
+    }
+
+#endif //defined DD360 || defined DD360Audi
+
+    return result;
+}
+
+void InitEthernet(void)
+{
+    char tmpbuf[256];
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+    bool ethResult = false;
+    uint8_t cnt_pingDNS_Fail = 0;
+#endif //!defined DD360 && !defined DD360Audi
+
+    struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
+
+    system("ifconfig eth0 down");// eth0 down
+    system("ifconfig eth1 down");// eth1 down
+    sleep(2);
+
+    // /sbin/ifconfig eth0 192.168.1.10 netmask 255.255.255.0 down
+    system("echo 1 > /sys/class/gpio/gpio110/value");//reset PHY
+    sleep(2);
+    //Init Eth0 for internet
+    memset(tmpbuf, 0, 256);
+    sprintf(tmpbuf, "/sbin/ifconfig eth0 %s netmask %s up",
+            pSysConfig->Eth0Interface.EthIpAddress,
+            pSysConfig->Eth0Interface.EthSubmaskAddress);
+    //sprintf(tmpbuf,"/sbin/ifconfig eth0 192.168.100.10 netmask 255.255.255.0 up");
+    system(tmpbuf);
+
+    memset(tmpbuf, 0, 256);
+    sprintf(tmpbuf, "route add default gw %s eth0 ",
+            pSysConfig->Eth0Interface.EthGatewayAddress);
+    //sprintf(tmpbuf,"route add default gw 192.168.100.1 eth0 ");
+    system(tmpbuf);
+    //system("ifconfig lo up");
+    //  /sbin/ifconfig eth0 192.168.1.10 netmask 255.255.255.0 up
+    //Init Eth1 for administrator tool
+    memset(tmpbuf, 0, 256);
+    sprintf(tmpbuf, "/sbin/ifconfig eth1 %s netmask %s up",
+            pSysConfig->Eth1Interface.EthIpAddress,
+            pSysConfig->Eth1Interface.EthSubmaskAddress);
+    system(tmpbuf);
+
+    //Run DHCP client if enabled
+    system("killall udhcpc");
+    system("rm -rf /etc/resolv.conf");
+    system("echo nameserver 8.8.8.8 > /etc/resolv.conf");       //Google DNS server
+    system("echo nameserver 180.76.76.76 > /etc/resolv.conf");  //Baidu DNS server
+    //system("/sbin/ifconfig eth0 down;/sbin/ifconfig eth0 up");
+
+    if (pSysConfig->Eth0Interface.EthDhcpClient == 0) {
+        sprintf(tmpbuf, "/sbin/udhcpc -i eth0 -x hostname:CSU3_%s -s /root/dhcp_script/eth0.script > /dev/null &",
+                pSysConfig->SystemId);
+        system(tmpbuf);
+    }
+
+    //Upgrade system id to /etc/hostname
+    sprintf(tmpbuf, "echo %s > /etc/hostname", pSysConfig->SystemId);
+    system(tmpbuf);
+
+    pid_t pid = fork();
+    if (pid == 0) {
+        log_info("InitEthernet = %d\r\n", pid);
+        for (;;) {
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+            if (isRouteFail()) {
+                //log_info("eth0 not in route, restart eht0. \n");
+                system("/sbin/ifconfig eth0 down;/sbin/ifconfig eth0 up");
+
+                if (pSysConfig->Eth0Interface.EthDhcpClient == 0) {
+                    InitialDHCP();
+                }
+            }
+
+            if (isReachableInternet() == PASS) {
+                pSysInfo->ethInternetConn = YES;
+                cnt_pingDNS_Fail = 0;
+            } else {
+                if (++cnt_pingDNS_Fail > 3) {
+                    pSysInfo->ethInternetConn = NO;
+                }
+            }
+
+            ethResult = pSysInfo->ethInternetConn;
+
+            if (ethResult == YES) {
+                system("/sbin/ifmetric eth0 0");
+
+                if ((pSysConfig->ModelName[10] == 'W') ||
+                        (pSysConfig->ModelName[10] == 'D')) {
+                    system("/sbin/ifmetric mlan0 1");
+                }
+
+                if ((pSysConfig->ModelName[10] == 'T') ||
+                        (pSysConfig->ModelName[10] == 'D')) {
+                    system("/sbin/ifmetric ppp0 2");
+                }
+            }
+
+            if (!ethResult &&
+                    pSysConfig->AthInterface.WifiMode != _SYS_WIFI_MODE_DISABLE &&
+                    (pSysConfig->ModelName[10] == 'W' ||
+                     pSysConfig->ModelName[10] == 'D')) {
+                //ethResult = pSysConfig->AthInterface.WifiNetworkConn;
+                ethResult = pInfoCode->InfoEvents.bits.InternetDisconnectViaWiFi == YES ? NO : YES;
+
+                if (ethResult) {
+                    if ((pSysConfig->ModelName[10] == 'W') ||
+                            (pSysConfig->ModelName[10] == 'D')) {
+                        system("/sbin/ifmetric eth0 1");
+                        system("/sbin/ifmetric mlan0 0");
+                    }
+
+
+                    if ((pSysConfig->ModelName[10] == 'T') ||
+                            (pSysConfig->ModelName[10] == 'D')) {
+                        system("/sbin/ifmetric ppp0 2");
+                    }
+                }
+            }
+
+            if (!ethResult &&
+                    pSysConfig->TelecomInterface.TelcomEnabled == YES &&
+                    (pSysConfig->ModelName[10] == 'T' ||
+                     pSysConfig->ModelName[10] == 'D')) {
+                //ethResult = pSysConfig->TelecomInterface.TelcomNetworkConn;
+                ethResult = pInfoCode->InfoEvents.bits.InternetDisconnectVia4Gi == YES ? NO : YES;
+
+                if (ethResult) {
+                    if ((pSysConfig->ModelName[10] == 'W') ||
+                            (pSysConfig->ModelName[10] == 'D')) {
+                        system("/sbin/ifmetric mlan0 2");
+                    }
+
+                    if ((pSysConfig->ModelName[10] == 'T') ||
+                            (pSysConfig->ModelName[10] == 'D')) {
+                        system("/sbin/ifmetric eth0 1");
+                        system("/sbin/ifmetric ppp0 0");
+                    }
+                }
+            }
+
+            pSysInfo->InternetConn = ethResult;
+#else
+            isReachableInternet();
+#endif //!defined DD360 && !defined DD360
+
+            sleep(5);
+        }
+    }
+
+    log_info("Initial Ethernet OK\r\n");
+}

+ 0 - 0
EVSE/Projects/DD360Audi/Apps/CSU/Gpio.c


+ 56 - 129
EVSE/Projects/DD360Audi/Apps/CSU/Primary.c

@@ -42,22 +42,22 @@ void PrimaryLedIndicatorCtrlFork(void)
     if (pid == 0) {
         uint8_t gunIndex = 0;
         int isContinue = 1;
-        LedConfig *pLedConfig = NULL;
+
         struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
         struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
-        struct WARNING_CODE_INFO *pSysWarningInfo = (struct WARNING_CODE_INFO *)GetShmSysWarningInfo();
+        struct WARNING_CODE_INFO *pSysWarning = (struct WARNING_CODE_INFO *)GetShmSysWarningInfo();
         struct PrimaryMcuData *ShmPrimaryMcuData = (struct PrimaryMcuData *)GetShmPrimaryMcuData();
-        struct ChargingInfoData *pDcChargingInfoData = NULL;
+        struct ChargingInfoData *pDcChargingInfo = NULL;
 
-        pLedConfig = (LedConfig *)&ShmPrimaryMcuData->OutputDrv.OutputDrvValue[0];
+        LedConfig *pLedConfig = (LedConfig *)&ShmPrimaryMcuData->OutputDrv.OutputDrvValue[0];
 
         while (isContinue) {
             for (gunIndex = 0; gunIndex < pSysConfig->TotalConnectorCount; gunIndex++) {
-                pDcChargingInfoData = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+                pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
 
-                //printf("led indicator status = %d\r\n", pDcChargingInfoData->SystemStatus);
-                //printf("level = %d\r\n", pSysWarningInfo->Level);
-                switch (pDcChargingInfoData->SystemStatus) {
+                //printf("led indicator status = %d\r\n", chargingInfo[gunIndex]->SystemStatus);
+                //printf("level = %d\r\n", pSysWarning->Level);
+                switch (pDcChargingInfo->SystemStatus) {
                 case S_BOOTING:
                     if (pSysInfo->SelfTestSeq == _STEST_COMPLETE) {
                         //Module_DoComm tcp disconnect
@@ -127,7 +127,7 @@ void PrimaryLedIndicatorCtrlFork(void)
 
                 case S_TERMINATING:
                 case S_COMPLETE:
-                    if (pSysWarningInfo->Level == 2) {
+                    if (pSysWarning->Level == 2) {
                         pLedConfig->YellowLED = NO;
                         pLedConfig->GreenLED = NO;
                         if (checkCabinetEthConnectState(pLedConfig) == YES) {
@@ -146,7 +146,7 @@ void PrimaryLedIndicatorCtrlFork(void)
                 case S_FAULT:
                     pLedConfig->YellowLED = NO;
                     pLedConfig->GreenLED = NO;
-                    if (pSysWarningInfo->Level == 2) {
+                    if (pSysWarning->Level == 2) {
                         if (checkCabinetEthConnectState(pLedConfig) == YES) {
                             break;
                         }
@@ -160,125 +160,47 @@ void PrimaryLedIndicatorCtrlFork(void)
                 case S_UPDATE:
                 case S_NONE:
                     break;
-                }//switch
+                }
 
-            } //for
-            usleep(500000);
-        } //while
-    } //fork
+                usleep(500000);
+            }//switch
+        }//for
+    }//while
 }
 
 //------------------------------------------------------------------------------
-// 急停狀況的停止充電處理函式
-void EmcOccureByString(char *code)
-{
-    uint8_t level = 2;
-    uint8_t gunIndex = 0;
-    struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
-    struct ChargingInfoData *pDcChargingInfoData = NULL;
-
-
-    // 嚴重的急停有以下幾種 : EMC 按鈕、Mainbreak、Dooropen
-    // 其錯誤等級為 2
-
-//#if defined DD360 ||defined DD360Audi || defined DD360ComBox
-//    //DS60-120 remove
-//    if (strncmp(code, "012251", 6) == EQUAL ||
-//            strncmp(code, "012252", 6) == EQUAL ||
-//            strncmp(code, "012238", 6) == EQUAL ||
-//            strncmp(code, "042251", 6) == EQUAL ||
-//            strncmp(code, "042252", 6) == EQUAL ||
-//            strncmp(code, "012304", 6) == EQUAL ||
-//            strncmp(code, "042200", 6) == EQUAL ||
-//            strncmp(code, "042201", 6) == EQUAL ||
-//            strncmp(code, "042202", 6) == EQUAL ||
-//            strncmp(code, "042267", 6) == EQUAL)
-//#endif //defined DD360 || defined DD360Audi
-    {
-        for (gunIndex = 0; gunIndex < pSysConfig->TotalConnectorCount; gunIndex++) {
-            pDcChargingInfoData = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
-
-            //strncpy((char *)ShmOCPP16Data->StatusNotification[gunIndex].VendorErrorCode, code, 6);
-
-            if ((pDcChargingInfoData->SystemStatus > S_IDLE &&
-                    pDcChargingInfoData->SystemStatus < S_TERMINATING) ||
-                    (pDcChargingInfoData->SystemStatus >= S_CCS_PRECHARGE_ST0 &&
-                     pDcChargingInfoData->SystemStatus <= S_CCS_PRECHARGE_ST1)) {
-                //ChargingTerminalProcess(gunIndex);
-                ChargingAlarmProcess(gunIndex);
-            }
-        }
-//#if defined DD360 ||defined DD360Audi || defined DD360ComBox
-        StopChargingProcessByString(level);
-        //InformOcppErrOccur(4);
-//#endif //defined DD360 || defined DD360Audi
-    }
-}
-
-void ReleaseEmsOccureByString(uint8_t index, char *code)
-{
-    bool isTrigger = false;
-    uint8_t level = 2;
-    struct AlarmCodeData *pAlarmCode = (struct AlarmCodeData *)GetShmAlarmCodeData();
-
-    if (strncmp(code, "042251", 6) == 0 ) {
-        isTrigger = true;
-    } else if (strncmp(code, "012251", 6) == 0 &&
-               pAlarmCode->AlarmEvents.bits.EmergencyStopTrip == YES) {
-        isTrigger = true;
-        pAlarmCode->AlarmEvents.bits.EmergencyStopTrip = NO;
-    } else if (strncmp(code, "012252", 6) == 0 &&
-               pAlarmCode->AlarmEvents.bits.DoorOpen == YES) {
-        isTrigger = true;
-        pAlarmCode->AlarmEvents.bits.DoorOpen = NO;
-    } else if (strncmp(code, "012237", 6) == 0 &&
-               pAlarmCode->AlarmEvents.bits.SpdTrip == YES) {
-        isTrigger = true;
-        pAlarmCode->AlarmEvents.bits.SpdTrip = NO;
-    } else if (strncmp(code, "012238", 6) == 0 &&
-               pAlarmCode->AlarmEvents.bits.MainPowerBreakerTrip == YES) {
-        isTrigger = true;
-        pAlarmCode->AlarmEvents.bits.MainPowerBreakerTrip = NO;
-    }
-
-    if (isTrigger) {
-        ReleaseChargingProcessByString(level);
-        InformOcppErrOccur(6);
-    }
-}
-
 void ChkPrimaryStatus(void)
 {
-    uint8_t Rtn;
     static bool leftBtnPush = false;
     static bool rightBtnPush = false;
+    uint8_t Rtn;
     struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
     struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
-    struct WARNING_CODE_INFO *pSysWarningInfo = (struct WARNING_CODE_INFO *)GetShmSysWarningInfo();
+    struct WARNING_CODE_INFO *pSysWarning = (struct WARNING_CODE_INFO *)GetShmSysWarningInfo();
     struct PrimaryMcuData *ShmPrimaryMcuData = (struct PrimaryMcuData *)GetShmPrimaryMcuData();
     struct AlarmCodeData *pAlarmCode = (struct AlarmCodeData *)GetShmAlarmCodeData();
-    struct ChargingInfoData *pDcChargingInfoData = NULL;
-    struct ChargingInfoData *pAcChargingInfoData = (struct ChargingInfoData *)GetAcChargingInfoData(0);
+    struct ChargingInfoData *pDcChargingInfo = NULL;
+    struct ChargingInfoData *pAcChargingInfo = NULL;
 
-    if (pSysWarningInfo->WarningCount > 0) {
+    if (pSysWarning->WarningCount > 0) {
         Rtn = 0;
-        for (uint8_t i = 0; i < pSysWarningInfo->WarningCount; i++) {
-            if (memcmp(&pSysWarningInfo->WarningCode[i][0], "042251", 6) == 0) {
+        for (uint8_t i = 0; i < pSysWarning->WarningCount; i++) {
+            if (memcmp(&pSysWarning->WarningCode[i][0], "042251", 6) == 0) {
                 EmcOccureByString("042251");
                 Rtn = 1;
-            } else if (memcmp(&pSysWarningInfo->WarningCode[i][0], "042252", 6) == 0) {
+            } else if (memcmp(&pSysWarning->WarningCode[i][0], "042252", 6) == 0) {
                 EmcOccureByString("042252");
                 Rtn = 1;
-            } else if (memcmp(&pSysWarningInfo->WarningCode[i][0], "042200", 6) == 0) {
+            } else if (memcmp(&pSysWarning->WarningCode[i][0], "042200", 6) == 0) {
                 EmcOccureByString("042200");
                 Rtn = 1;
-            } else if (memcmp(&pSysWarningInfo->WarningCode[i][0], "042201", 6) == 0) {
+            } else if (memcmp(&pSysWarning->WarningCode[i][0], "042201", 6) == 0) {
                 EmcOccureByString("042201");
                 Rtn = 1;
-            } else if (memcmp(&pSysWarningInfo->WarningCode[i][0], "042202", 6) == 0) {
+            } else if (memcmp(&pSysWarning->WarningCode[i][0], "042202", 6) == 0) {
                 EmcOccureByString("042202");
                 Rtn = 1;
-            } else if (memcmp(&pSysWarningInfo->WarningCode[i][0], "012304", 6) == 0) {
+            } else if (memcmp(&pSysWarning->WarningCode[i][0], "012304", 6) == 0) {
                 EmcOccureByString("012304");
                 Rtn = 1;
             }
@@ -335,17 +257,25 @@ void ChkPrimaryStatus(void)
     //    pSysConfig->ShowInformation = NO;
     //}
 
-    pDcChargingInfoData = (struct ChargingInfoData *)GetDcChargingInfoData(pSysInfo->CurGunSelected);
-
     if (ShmPrimaryMcuData->InputDet.bits.Button1 == BTN_PRESS &&
-            !leftBtnPush &&
-            WaitAuthorPageState()
+            !leftBtnPush
+#if defined DD360Audi
+            &&
+            pSysInfo->SystemPage != _LCM_AUTHORIZING &&
+            pSysInfo->SystemPage != _LCM_AUTHORIZ_COMP &&
+            pSysInfo->SystemPage != _LCM_AUTHORIZ_FAIL
+#endif //defined DD360Audi
        ) {
+        pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(pSysInfo->CurGunSelected);
+
         if (!leftBtnPush) {
             leftBtnPush = true;
-            log_info("left btn down...............................%x\n", pDcChargingInfoData->SystemStatus);
+            log_info("left btn down...............................%x\n",
+                     pDcChargingInfo->SystemStatus);
             if (pSysInfo->CurGunSelectedByAc != NO_DEFINE) {
-                switch (pAcChargingInfoData->SystemStatus) {
+                pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(0);
+
+                switch (pAcChargingInfo->SystemStatus) {
                 case S_IDLE:
                     if (isDetectPlugin()) {
                         _DetectPlugInTimeout();
@@ -376,17 +306,14 @@ void ChkPrimaryStatus(void)
                 }
             }
 
-            switch (pDcChargingInfoData->SystemStatus) {
+            switch (pDcChargingInfo->SystemStatus) {
             case S_IDLE:
                 if (isDetectPlugin()) {
                     _DetectPlugInTimeout();
                     StopSystemTimeoutDet();
-#if defined DD360Audi
                     destroySelGun(pSysInfo->CurGunSelected);
-#endif //defined DD360Audi
-                }
+                }             else {
 #if defined DD360Audi
-                else {
                     if (getConfirmSelectedGun(pSysInfo->CurGunSelected) == PASS) {
                         //printf("destroy gun = %d\r\n", pSysInfo->CurGunSelected);
                         destroySelGun(pSysInfo->CurGunSelected);
@@ -395,8 +322,9 @@ void ChkPrimaryStatus(void)
                         log_info("confirm select gun ............................... %d \n",
                                  pSysInfo->CurGunSelected);
                     }
-                }
+
 #endif //defined DD360Audi
+                }
                 break;
 
             case S_REASSIGN_CHECK:
@@ -425,7 +353,7 @@ void ChkPrimaryStatus(void)
             case S_COMPLETE:
                 // 回 IDLE
                 //log_info("right btn down.................S_COMPLETE \n");
-                //pDcChargingInfoData->SystemStatus = S_IDLE;
+                //pDcChargingInfo->SystemStatus = S_IDLE;
                 break;
             }
         }
@@ -440,18 +368,17 @@ void ChkPrimaryStatus(void)
             !rightBtnPush
 #if defined DD360Audi
             &&
-            getCurLcmPage() != _LCM_IDLE &&
-            getCurLcmPage() != _LCM_AUTHORIZING &&
-            getCurLcmPage() != _LCM_AUTHORIZ_COMP &&
-            getCurLcmPage() != _LCM_AUTHORIZ_FAIL &&
-            getCurLcmPage() != _LCM_WAIT_FOR_PLUG
+            pSysInfo->SystemPage != _LCM_IDLE &&
+            pSysInfo->SystemPage != _LCM_AUTHORIZING &&
+            pSysInfo->SystemPage != _LCM_AUTHORIZ_COMP &&
+            pSysInfo->SystemPage != _LCM_AUTHORIZ_FAIL &&
+            pSysInfo->SystemPage != _LCM_WAIT_FOR_PLUG
 #endif //defined DD360Audi
        ) {
         if (!rightBtnPush) {
             rightBtnPush = true;
             //log_info("right btn down............................... %d \n", pSysInfo->CurGunSelected);
-            if (pSysInfo->CurGunSelected + 1 <
-                    pSysConfig->TotalConnectorCount &&
+            if (pSysInfo->CurGunSelected + 1 < pSysConfig->TotalConnectorCount &&
                     pSysInfo->IsAlternatvieConf == NO) {
                 pSysInfo->CurGunSelected++;
                 ChangeGunSelectByIndex(pSysInfo->CurGunSelected);
@@ -460,11 +387,11 @@ void ChkPrimaryStatus(void)
                 pSysInfo->CurGunSelectedByAc = DEFAULT_AC_INDEX;
             } else if (pSysInfo->IsAlternatvieConf == YES) {
                 for (uint8_t _index = 0; _index < pSysConfig->TotalConnectorCount; _index++) {
-                    pDcChargingInfoData = (struct ChargingInfoData *)GetDcChargingInfoData(_index);
+                    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_index);
 
-                    if (pDcChargingInfoData->SystemStatus != S_BOOTING &&
-                            pDcChargingInfoData->SystemStatus != S_IDLE &&
-                            pDcChargingInfoData->SystemStatus != S_RESERVATION) {
+                    if (pDcChargingInfo->SystemStatus != S_BOOTING &&
+                            pDcChargingInfo->SystemStatus != S_IDLE &&
+                            pDcChargingInfo->SystemStatus != S_RESERVATION) {
                         pSysInfo->CurGunSelected = _index;
                         ChangeGunSelectByIndex(pSysInfo->CurGunSelected);
                         return;

+ 247 - 152
EVSE/Projects/DD360Audi/Apps/CSU/RFID.c

@@ -7,19 +7,55 @@
 #include "../Log/log.h"
 #include "../Define/define.h"
 #include "../ShareMemory/shmMem.h"
+#include "../SelectGun/SelectGun.h"
+
+#include "../main.h"
+#include "../timeout.h"
+
+//------------------------------------------------------------------------------
+static char *rfidPortName = "/dev/ttyS2";
+
+static bool isCardScan = false;
 
 //------------------------------------------------------------------------------
+static bool canStartCharging(void)
+{
+    char buf2[16] = "";
+    memset(buf2, 0, ARRAY_SIZE(buf2));
+    struct OCPP16Data *ShmOCPP16Data = (struct OCPP16Data *)GetShmOCPP16Data();
+
+    for (uint8_t index = 0; index < strlen((char *)ShmOCPP16Data->Authorize.ResponseIdTagInfo.Status); index++) {
+        sprintf(buf2 + (index - 1) * 2, "%02X", ShmOCPP16Data->Authorize.ResponseIdTagInfo.Status[index]);
+    }
+    sprintf(buf2, "%s", ShmOCPP16Data->Authorize.ResponseIdTagInfo.Status);
+
+    // 因為無法得知實際的長度,所以只能用搜尋的方式
+    if (strcmp(buf2, "Accepted") == EQUAL) {
+        return true;
+    } else {
+
+    }
+
+    return false;
+}
+
 static void UserScanFunction(void)
 {
     bool idleReq = false;
-    uint8_t stopReq = 255;
+    uint8_t stopReq = NO_DEFINE;
+    static uint8_t _authorizeIndex = NO_DEFINE;
+    struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
+    struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
+    struct ChargingInfoData *pAcChargingInfo =  (struct ChargingInfoData *)GetAcChargingInfoData(0);
+    struct ChargingInfoData *pDcChargingInfo = NULL;
+    GunIndexInfo *pGunIndexInfo = (GunIndexInfo *)GetGunIndexInfo();
 
     // 當前非驗證的狀態
     if (!IsAuthorizingMode()) {
 #if defined DD360Audi
         //當前沒有選槍
-        if (getConfirmSelectedGun(ShmSysConfigAndInfo->SysInfo.CurGunSelected) == FAIL) { //Jerry add
-            strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+        if (getConfirmSelectedGun(pSysInfo->CurGunSelected) == FAIL) { //Jerry add
+            strcpy((char *)pSysConfig->UserId, "");
             return;
         }
 #endif //defined DD360Audi
@@ -27,139 +63,145 @@ static void UserScanFunction(void)
         // 先判斷現在是否可以提供刷卡
         // 1. 如果當前沒有槍是閒置狀態,則無提供刷卡功能
         // 2. 停止充電
-        if (ShmSysConfigAndInfo->SysInfo.PageIndex == _LCM_FIX) {
-            strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+        if (pSysInfo->PageIndex == _LCM_FIX) {
+            strcpy((char *)pSysConfig->UserId, "");
             return;
         }
 
-        for (uint8_t i = 0; i < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; i++) {
-            if (chargingInfo[i]->SystemStatus == S_CHARGING) {
+        for (uint8_t i = 0; i < pSysConfig->TotalConnectorCount; i++) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(i);
+
+            if (pDcChargingInfo->SystemStatus == S_CHARGING) {
                 stopReq = i;
             }
-            if ((chargingInfo[i]->SystemStatus == S_IDLE &&
-                    chargingInfo[i]->IsAvailable) == YES ||
-                    (_acgunIndex > 0 && ac_chargingInfo[0]->SystemStatus ==
-                     S_IDLE && ac_chargingInfo[0]->IsAvailable)
+            if ((pDcChargingInfo->SystemStatus == S_IDLE &&
+                    pDcChargingInfo->IsAvailable) == YES ||
+                    (pGunIndexInfo->AcGunIndex > 0 && pAcChargingInfo->SystemStatus ==
+                     S_IDLE && pAcChargingInfo->IsAvailable)
                ) {
                 idleReq = true;
             }
         }
 
-        if (_acgunIndex > 0 && ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc == DEFAULT_AC_INDEX &&
-                ac_chargingInfo[0]->SystemStatus == S_CHARGING) {
+        if (pGunIndexInfo->AcGunIndex > 0 && pSysInfo->CurGunSelectedByAc == DEFAULT_AC_INDEX &&
+                pAcChargingInfo->SystemStatus == S_CHARGING) {
             stopReq = DEFAULT_AC_INDEX;
         }
 
-        if (strlen((char *)ShmSysConfigAndInfo->SysConfig.UserId) > 0) {
-            if (_acgunIndex > 0 && stopReq == DEFAULT_AC_INDEX &&
-                    ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc == DEFAULT_AC_INDEX) {
+        if (strlen((char *)pSysConfig->UserId) > 0) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(pSysInfo->CurGunSelected);
+
+            if (pGunIndexInfo->AcGunIndex > 0 && stopReq == DEFAULT_AC_INDEX &&
+                    pSysInfo->CurGunSelectedByAc == DEFAULT_AC_INDEX) {
                 char value[32];
 
                 log_info("ac stop charging \n");
-                log_info("index = %d, card number = %s, UserId = %s \n", ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc,
-                         ac_chargingInfo[0]->StartUserId, ShmSysConfigAndInfo->SysConfig.UserId);
-                memcpy(value, (uint8_t *)ac_chargingInfo[0]->StartUserId,
-                       ARRAY_SIZE(ac_chargingInfo[0]->StartUserId));
-                if (strcmp((char *)ShmSysConfigAndInfo->SysConfig.UserId, value) == EQUAL) {
+                log_info("index = %d, card number = %s, UserId = %s \n", pSysInfo->CurGunSelectedByAc,
+                         pAcChargingInfo->StartUserId, pSysConfig->UserId);
+                memcpy(value, (uint8_t *)pAcChargingInfo->StartUserId,
+                       ARRAY_SIZE(pAcChargingInfo->StartUserId));
+                if (strcmp((char *)pSysConfig->UserId, value) == EQUAL) {
                     AcChargingTerminalProcess();
                 }
-                strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
-            } else if (stopReq < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount &&
-                       chargingInfo[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus == S_CHARGING &&
-                       (_acgunIndex <= 0 || (_acgunIndex > 0 && ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc == NO_DEFINE))) {
+                strcpy((char *)pSysConfig->UserId, "");
+            } else if (stopReq < pSysConfig->TotalConnectorCount &&
+                       pDcChargingInfo->SystemStatus == S_CHARGING &&
+                       (pGunIndexInfo->AcGunIndex <= 0 || (pGunIndexInfo->AcGunIndex > 0 && pSysInfo->CurGunSelectedByAc == NO_DEFINE))) {
                 char value[32];
 
                 log_info("stop charging \n");
                 log_info("index = %d, card number = %s, UserId = %s \n",
-                         ShmSysConfigAndInfo->SysInfo.CurGunSelected,
-                         chargingInfo[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->StartUserId,
-                         ShmSysConfigAndInfo->SysConfig.UserId);
-                memcpy(value, (uint8_t *)chargingInfo[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->StartUserId,
-                       ARRAY_SIZE(chargingInfo[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->StartUserId));
+                         pSysInfo->CurGunSelected,
+                         pDcChargingInfo->StartUserId,
+                         pSysConfig->UserId);
+                memcpy(value, (uint8_t *)pDcChargingInfo->StartUserId,
+                       ARRAY_SIZE(pDcChargingInfo->StartUserId));
 
                 // 同一張卡直接停掉
-                if (strcmp((char *)ShmSysConfigAndInfo->SysConfig.UserId, value) == EQUAL) {
-                    ChargingTerminalProcess(ShmSysConfigAndInfo->SysInfo.CurGunSelected);
-                    strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                if (strcmp((char *)pSysConfig->UserId, value) == EQUAL) {
+                    ChargingTerminalProcess(pSysInfo->CurGunSelected);
+                    strcpy((char *)pSysConfig->UserId, "");
                 } else {
                     // 進驗證
-                    if (_acgunIndex > 0 && ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc == DEFAULT_AC_INDEX) {
-                        _authorizeIndex = ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc;
+                    if (pGunIndexInfo->AcGunIndex > 0 && pSysInfo->CurGunSelectedByAc == DEFAULT_AC_INDEX) {
+                        _authorizeIndex = pSysInfo->CurGunSelectedByAc;
                     } else {
-                        _authorizeIndex = ShmSysConfigAndInfo->SysInfo.CurGunSelected;
+                        _authorizeIndex = pSysInfo->CurGunSelected;
                     }
 #if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
                     StartSystemTimeoutDet(Timeout_AuthorizingForStop);
                     AuthorizingStart();
 #else
-                    strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                    strcpy((char *)pSysConfig->UserId, "");
 #endif //!defined DD360 && !defined DD360Audi
                 }
             } else if (idleReq) {
-                if (ShmSysConfigAndInfo->SysConfig.TotalConnectorCount > 1 &&
+                if (pSysConfig->TotalConnectorCount > 1 &&
                         stopReq != 255 &&
-                        ShmSysConfigAndInfo->SysInfo.IsAlternatvieConf == YES) {
+                        pSysInfo->IsAlternatvieConf == YES) {
                     idleReq = false;
-                    strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
-                } else if ((_acgunIndex > 0 && ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc == DEFAULT_AC_INDEX) ||
-                           chargingInfo[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus == S_IDLE) {
+                    strcpy((char *)pSysConfig->UserId, "");
+                } else if ((pGunIndexInfo->AcGunIndex > 0 && pSysInfo->CurGunSelectedByAc == DEFAULT_AC_INDEX) ||
+                           pDcChargingInfo->SystemStatus == S_IDLE) {
                     log_info("// LCM => Authorizing \n");
 #if defined DD360Audi
-                    setSelGunWaitToAuthor(ShmSysConfigAndInfo->SysInfo.CurGunSelected); //Jerry add
+                    setSelGunWaitToAuthor(pSysInfo->CurGunSelected); //Jerry add
 #endif //defined DD360Audi
                     // LCM => Authorizing
-                    ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_AUTHORIZING;
+                    pSysInfo->SystemPage = _LCM_AUTHORIZING;
                     // 進入確認卡號狀態
                     AuthorizingStart();
                 } else {
-                    strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                    strcpy((char *)pSysConfig->UserId, "");
                 }
             } else {
-                strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                strcpy((char *)pSysConfig->UserId, "");
             }
         }
     } else {
         // 透過後臺停止充電的判斷
         if (isAuthorizedComplete()
 #if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
-                || (ShmSysConfigAndInfo->SysInfo.OcppConnStatus == NO &&
-                    ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING)
+                || (pSysInfo->OcppConnStatus == NO &&
+                    pSysConfig->OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING)
 #endif //!defined DD360 && !defined DD360Audi
            ) {
             // 判斷後台回覆狀態
             if (canStartCharging()
 #if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
-                    || (ShmSysConfigAndInfo->SysInfo.OcppConnStatus == NO &&
-                        ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING)
+                    || (pSysInfo->OcppConnStatus == NO &&
+                        pSysConfig->OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING)
 #endif //!defined DD360 && !defined DD360Audi
                ) {
                 if (_authorizeIndex != NO_DEFINE) {
+                    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_authorizeIndex);
+
                     // 先找 AC
                     if (_authorizeIndex == DEFAULT_AC_INDEX) {
-                        if (ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST &&
-                                strcmp((char *)chargingInfo[_authorizeIndex]->StartUserId, "") != EQUAL) {
+                        if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST &&
+                                strcmp((char *)pDcChargingInfo->StartUserId, "") != EQUAL) {
                             AcChargingTerminalProcess();
                         }
                     } else {
-                        if (ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST &&
-                                strcmp((char *)chargingInfo[_authorizeIndex]->StartUserId, "") != EQUAL) {
+                        if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST &&
+                                strcmp((char *)pDcChargingInfo->StartUserId, "") != EQUAL) {
                             ChargingTerminalProcess(_authorizeIndex);
                         }
                     }
-                    strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                    strcpy((char *)pSysConfig->UserId, "");
                     _authorizeIndex = NO_DEFINE;
                 }
             } else {
-                strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                strcpy((char *)pSysConfig->UserId, "");
             }
             ClearAuthorizedFlag();
-        } else if (ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST) {
+        } else if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST) {
             // 白名單驗證
             for (int i = 0; i < 10; i++) {
-                if (strcmp((char *)ShmSysConfigAndInfo->SysConfig.LocalWhiteCard[i], "") != EQUAL) {
-                    if (strcmp((char *)ShmSysConfigAndInfo->SysConfig.LocalWhiteCard[i], (char *)ShmSysConfigAndInfo->SysConfig.UserId) == EQUAL) {
+                if (strcmp((char *)pSysConfig->LocalWhiteCard[i], "") != EQUAL) {
+                    if (strcmp((char *)pSysConfig->LocalWhiteCard[i], (char *)pSysConfig->UserId) == EQUAL) {
                         ChargingTerminalProcess(_authorizeIndex);
-                        strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                        strcpy((char *)pSysConfig->UserId, "");
                         ClearAuthorizedFlag();
                         break;
                     }
@@ -169,152 +211,205 @@ static void UserScanFunction(void)
     }
 }
 
-void ScannerCardProcess()
+bool GetIsCardScan(void)
+{
+    return isCardScan;
+}
+
+void SetIsCardScan(bool value)
+{
+    isCardScan = value;
+}
+
+void ScannerCardProcess(void)
 {
-    if (!isDetectPlugin() && !isCardScan && ShmSysConfigAndInfo->SysWarningInfo.Level != 2 &&
-            ShmSysConfigAndInfo->SysConfig.AuthorisationMode == AUTH_MODE_ENABLE) {
+    struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
+    struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
+    struct WARNING_CODE_INFO *pSysWarning = (struct WARNING_CODE_INFO *)GetShmSysWarningInfo();
+    SelectGunInfo *ShmSelectGunInfo = (SelectGunInfo *)GetShmSelectGunInfo();
+
+    if (!isDetectPlugin() && !isCardScan && pSysWarning->Level != 2 &&
+            pSysConfig->AuthorisationMode == AUTH_MODE_ENABLE) {
         isCardScan = true;
         // 處理刷卡及驗證卡號的動作
         UserScanFunction();
     }
 
-    if (ShmSysConfigAndInfo->SysInfo.PageIndex == _LCM_AUTHORIZING) {
+    if (pSysInfo->PageIndex == _LCM_AUTHORIZING) {
         StartSystemTimeoutDet(Timeout_Authorizing);
 
         // 確認驗證卡號完成沒
         if (isAuthorizedComplete()
 #if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
-                || ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING
+                || pSysConfig->OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING
 #else
-                && gAudiCustInfo->PricesInfo[ShmSysConfigAndInfo->SysInfo.CurGunSelected].Balance != FAIL_BALANCE_PRICES
+                && ShmSelectGunInfo->PricesInfo[pSysInfo->CurGunSelected].Balance != FAIL_BALANCE_PRICES
 #endif //!defined DD360 && !defined DD360Audi
            ) {
             StopSystemTimeoutDet();
             // 判斷後台回覆狀態
             if (canStartCharging()
 #if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
-                    || ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING
+                    || pSysConfig->OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING
 #endif //!defined DD360 && !defined DD360Audi
                ) {
                 // LCM => Authorize complete
-                ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_AUTHORIZ_COMP;
+                pSysInfo->SystemPage = _LCM_AUTHORIZ_COMP;
             } else {
                 // LCM => Authorize fail
-                ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_AUTHORIZ_FAIL;
-                strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                pSysInfo->SystemPage = _LCM_AUTHORIZ_FAIL;
+                strcpy((char *)pSysConfig->UserId, "");
             }
             ClearAuthorizedFlag();
-        } else if (ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST) {
+        } else if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST) {
             // 白名單驗證
             for (int i = 0; i < 10; i++) {
-                if (strcmp((char *)ShmSysConfigAndInfo->SysConfig.LocalWhiteCard[i], "") != EQUAL) {
-                    if (strcmp((char *)ShmSysConfigAndInfo->SysConfig.LocalWhiteCard[i], (char *)ShmSysConfigAndInfo->SysConfig.UserId) == EQUAL) {
-                        ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_AUTHORIZ_COMP;
+                if (strcmp((char *)pSysConfig->LocalWhiteCard[i], "") != EQUAL) {
+                    if (strcmp((char *)pSysConfig->LocalWhiteCard[i], (char *)pSysConfig->UserId) == EQUAL) {
+                        pSysInfo->SystemPage = _LCM_AUTHORIZ_COMP;
                         ClearAuthorizedFlag();
                         break;
                     }
                 }
             }
         }
-    } else if (ShmSysConfigAndInfo->SysInfo.PageIndex == _LCM_AUTHORIZ_FAIL) {
+    } else if (pSysInfo->PageIndex == _LCM_AUTHORIZ_FAIL) {
         StartSystemTimeoutDet(Timeout_VerifyFail);
         isCardScan = false;
-    } else if (ShmSysConfigAndInfo->SysInfo.PageIndex == _LCM_AUTHORIZ_COMP) {
+    } else if (pSysInfo->PageIndex == _LCM_AUTHORIZ_COMP) {
         StartSystemTimeoutDet(Timeout_VerifyComp);
-    } else if (ShmSysConfigAndInfo->SysInfo.PageIndex == _LCM_WAIT_FOR_PLUG) {
+    } else if (pSysInfo->PageIndex == _LCM_WAIT_FOR_PLUG) {
         StartSystemTimeoutDet(Timeout_WaitPlug);
     } else {
         isCardScan = false;
     }
 }
 
-void CreateRfidFork()
+
+static int InitialRfidPort(void)
+{
+    int fd = open(rfidPortName, O_RDWR);
+    struct termios tios;
+    struct AlarmCodeData *pAlarmCode = (struct AlarmCodeData *)GetShmAlarmCodeData();
+
+    if (fd != FAIL) {
+        ioctl (fd, TCGETS, &tios);
+        tios.c_cflag = B19200 | CS8 | CLOCAL | CREAD;
+        tios.c_lflag = 0;
+        tios.c_iflag = 0;
+        tios.c_oflag = 0;
+        tios.c_cc[VMIN] = 0;
+        tios.c_cc[VTIME] = (uint8_t) 1;
+        tios.c_lflag = 0;
+        tcflush(fd, TCIFLUSH);
+        ioctl(fd, TCSETS, &tios);
+    }
+
+    if (fd < 0) {
+        pAlarmCode->AlarmEvents.bits.RfidModuleCommFail = 1;
+    }
+
+    return fd;
+}
+
+void CreateRfidFork(void)
 {
     pid_t rfidRecPid;
 
     rfidRecPid = fork();
     log_info("CreateRfidFork = %d\r\n", rfidRecPid);
     if (rfidRecPid == 0) {
+        int fd = -1;
+        RFID rfid = {0};
+        fd = InitialRfidPort();
+        struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
+
         while (true) {
             // 刷卡判斷
-            RFID rfid;
-            if (ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_NO_CHARGING ||
-                    !ShmSysConfigAndInfo->SysConfig.isRFID)
-            {}
-            else if (getRequestCardSN(rfidFd, 0, &rfid)) {
-                //log_info("Get Card..-%s- \n", ShmSysConfigAndInfo->SysConfig.UserId);
-                if (strlen((char *)ShmSysConfigAndInfo->SysConfig.UserId) == 0) {
-                    if (ShmSysConfigAndInfo->SysConfig.RfidCardNumEndian == RFID_ENDIAN_LITTLE) {
-                        switch (rfid.snType) {
-                        case RFID_SN_TYPE_6BYTE:
-                            sprintf((char *) ShmSysConfigAndInfo->SysConfig.UserId,
-                                    "%02X%02X%02X%02X%02X%02X",
-                                    rfid.currentCard[0], rfid.currentCard[1],
-                                    rfid.currentCard[2], rfid.currentCard[3],
-                                    rfid.currentCard[4], rfid.currentCard[5]);
-                            break;
-                        case RFID_SN_TYPE_7BYTE:
-                            sprintf((char *) ShmSysConfigAndInfo->SysConfig.UserId,
-                                    "%02X%02X%02X%02X%02X%02X%02X",
-                                    rfid.currentCard[0], rfid.currentCard[1],
-                                    rfid.currentCard[2], rfid.currentCard[3],
-                                    rfid.currentCard[4], rfid.currentCard[5],
-                                    rfid.currentCard[6]);
-                            break;
-                        case RFID_SN_TYPE_10BYTE:
-                            sprintf((char *) ShmSysConfigAndInfo->SysConfig.UserId,
-                                    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
-                                    rfid.currentCard[0], rfid.currentCard[1],
-                                    rfid.currentCard[2], rfid.currentCard[3],
-                                    rfid.currentCard[4], rfid.currentCard[5],
-                                    rfid.currentCard[6], rfid.currentCard[7],
-                                    rfid.currentCard[8], rfid.currentCard[9]);
-                            break;
-                        case RFID_SN_TYPE_4BYTE:
-                            sprintf((char *) ShmSysConfigAndInfo->SysConfig.UserId,
-                                    "%02X%02X%02X%02X",
-                                    rfid.currentCard[0], rfid.currentCard[1],
-                                    rfid.currentCard[2], rfid.currentCard[3]);
-                            break;
-                        }
-                    } else if (ShmSysConfigAndInfo->SysConfig.RfidCardNumEndian == RFID_ENDIAN_BIG) {
-                        switch (rfid.snType) {
-                        case RFID_SN_TYPE_6BYTE:
-                            sprintf((char *) ShmSysConfigAndInfo->SysConfig.UserId,
-                                    "%02X%02X%02X%02X%02X%02X",
-                                    rfid.currentCard[5], rfid.currentCard[4],
-                                    rfid.currentCard[3], rfid.currentCard[2],
-                                    rfid.currentCard[1], rfid.currentCard[0]);
-                            break;
-                        case RFID_SN_TYPE_7BYTE:
-                            sprintf((char *) ShmSysConfigAndInfo->SysConfig.UserId,
-                                    "%02X%02X%02X%02X%02X%02X%02X",
-                                    rfid.currentCard[6], rfid.currentCard[5],
-                                    rfid.currentCard[4], rfid.currentCard[3],
-                                    rfid.currentCard[2], rfid.currentCard[1],
-                                    rfid.currentCard[0]);
-                            break;
-                        case RFID_SN_TYPE_10BYTE:
-                            sprintf((char *) ShmSysConfigAndInfo->SysConfig.UserId,
-                                    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
-                                    rfid.currentCard[9], rfid.currentCard[8],
-                                    rfid.currentCard[7], rfid.currentCard[6],
-                                    rfid.currentCard[5], rfid.currentCard[4],
-                                    rfid.currentCard[3], rfid.currentCard[2],
-                                    rfid.currentCard[1], rfid.currentCard[0]);
-                            break;
-                        case RFID_SN_TYPE_4BYTE:
-                            sprintf((char *) ShmSysConfigAndInfo->SysConfig.UserId,
-                                    "%02X%02X%02X%02X",
-                                    rfid.currentCard[3], rfid.currentCard[2],
-                                    rfid.currentCard[1], rfid.currentCard[0]);
-                            break;
-                        }
+            if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_NO_CHARGING ||
+                    !pSysConfig->isRFID) {
+                usleep(500000);
+                continue;
+            }
+
+            if (getRequestCardSN(fd, 0, &rfid) == false) {
+                usleep(500000);
+                continue;
+            }
+
+            //log_info("Get Card..-%s- \n", pSysConfig->UserId);
+            if (strlen((char *)pSysConfig->UserId) == 0) {
+                if (pSysConfig->RfidCardNumEndian == RFID_ENDIAN_LITTLE) {
+                    switch (rfid.snType) {
+                    case RFID_SN_TYPE_6BYTE:
+                        sprintf((char *) pSysConfig->UserId,
+                                "%02X%02X%02X%02X%02X%02X",
+                                rfid.currentCard[0], rfid.currentCard[1],
+                                rfid.currentCard[2], rfid.currentCard[3],
+                                rfid.currentCard[4], rfid.currentCard[5]);
+                        break;
+                    case RFID_SN_TYPE_7BYTE:
+                        sprintf((char *) pSysConfig->UserId,
+                                "%02X%02X%02X%02X%02X%02X%02X",
+                                rfid.currentCard[0], rfid.currentCard[1],
+                                rfid.currentCard[2], rfid.currentCard[3],
+                                rfid.currentCard[4], rfid.currentCard[5],
+                                rfid.currentCard[6]);
+                        break;
+                    case RFID_SN_TYPE_10BYTE:
+                        sprintf((char *) pSysConfig->UserId,
+                                "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
+                                rfid.currentCard[0], rfid.currentCard[1],
+                                rfid.currentCard[2], rfid.currentCard[3],
+                                rfid.currentCard[4], rfid.currentCard[5],
+                                rfid.currentCard[6], rfid.currentCard[7],
+                                rfid.currentCard[8], rfid.currentCard[9]);
+                        break;
+                    case RFID_SN_TYPE_4BYTE:
+                        sprintf((char *) pSysConfig->UserId,
+                                "%02X%02X%02X%02X",
+                                rfid.currentCard[0], rfid.currentCard[1],
+                                rfid.currentCard[2], rfid.currentCard[3]);
+                        break;
+                    }
+                } else if (pSysConfig->RfidCardNumEndian == RFID_ENDIAN_BIG) {
+                    switch (rfid.snType) {
+                    case RFID_SN_TYPE_6BYTE:
+                        sprintf((char *) pSysConfig->UserId,
+                                "%02X%02X%02X%02X%02X%02X",
+                                rfid.currentCard[5], rfid.currentCard[4],
+                                rfid.currentCard[3], rfid.currentCard[2],
+                                rfid.currentCard[1], rfid.currentCard[0]);
+                        break;
+                    case RFID_SN_TYPE_7BYTE:
+                        sprintf((char *) pSysConfig->UserId,
+                                "%02X%02X%02X%02X%02X%02X%02X",
+                                rfid.currentCard[6], rfid.currentCard[5],
+                                rfid.currentCard[4], rfid.currentCard[3],
+                                rfid.currentCard[2], rfid.currentCard[1],
+                                rfid.currentCard[0]);
+                        break;
+                    case RFID_SN_TYPE_10BYTE:
+                        sprintf((char *) pSysConfig->UserId,
+                                "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
+                                rfid.currentCard[9], rfid.currentCard[8],
+                                rfid.currentCard[7], rfid.currentCard[6],
+                                rfid.currentCard[5], rfid.currentCard[4],
+                                rfid.currentCard[3], rfid.currentCard[2],
+                                rfid.currentCard[1], rfid.currentCard[0]);
+                        break;
+                    case RFID_SN_TYPE_4BYTE:
+                        sprintf((char *) pSysConfig->UserId,
+                                "%02X%02X%02X%02X",
+                                rfid.currentCard[3], rfid.currentCard[2],
+                                rfid.currentCard[1], rfid.currentCard[0]);
+                        break;
                     }
-                    log_info("card number = %s\n", ShmSysConfigAndInfo->SysConfig.UserId);
                 }
+                log_info("card number = %s\n", pSysConfig->UserId);
             }
             usleep(500000);
         }
     }
 }
+

+ 215 - 0
EVSE/Projects/DD360Audi/Apps/CSU/SelfTest.c

@@ -0,0 +1,215 @@
+#include <stdio.h>      /*標準輸入輸出定義*/
+#include <stdlib.h>     /*標準函數庫定義*/
+#include <string.h>
+#include <stdint.h>
+
+#include "../Config.h"
+#include "../Log/log.h"
+#include "../Define/define.h"
+#include "../ShareMemory/shmMem.h"
+
+#include "../main.h"
+#include "../timeout.h"
+
+//------------------------------------------------------------------------------
+extern void ChkPrimaryStatus(void);
+
+//------------------------------------------------------------------------------
+void SelfTestRun(void)
+{
+    bool evInitFlag = false;
+    struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
+    struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
+    struct WARNING_CODE_INFO *pSysWarning = (struct WARNING_CODE_INFO *)GetShmSysWarningInfo();
+
+    struct PsuData *ShmPsuData = (struct PsuData *)GetShmPsuData();
+    struct CHAdeMOData *ShmCHAdeMOData = (struct CHAdeMOData *)GetShmCHAdeMOData();
+    struct GBTData *ShmGBTData = (struct GBTData *)GetShmGBTData();
+    struct CcsData *ShmCcsData = (struct CcsData *)GetShmCcsData();
+
+    struct PrimaryMcuData *ShmPrimaryMcuData = (struct PrimaryMcuData *)GetShmPrimaryMcuData();
+    struct FanModuleData *ShmFanModuleData = (struct FanModuleData *)GetShmFanModuleData();
+    struct RelayModuleData *ShmRelayModuleData = (struct RelayModuleData *)GetShmRelayModuleData();
+    struct ChargingInfoData *pDcChargingInfo = NULL;
+    struct ChargingInfoData *pAcChargingInfo = NULL;
+
+    StartSystemTimeoutDet(Timeout_SelftestChk);
+    pSysInfo->SelfTestSeq = _STEST_VERSION;
+
+    while (pSysInfo->SelfTestSeq != _STEST_COMPLETE //||
+            //GetTimeoutValue(pSysInfo->SystemTimeoutTimer) / uSEC_VAL <= 20 //DS60-120 add
+          ) {
+        if (pSysInfo->SelfTestSeq == _STEST_COMPLETE) {
+            return;
+        }
+
+        ChkPrimaryStatus();
+        if (pSysWarning->Level == 2 //||
+                //pAlarmCode->AlarmEvents.bits.PsuDipSwitchStestFail == YES //DS60-120 add
+           ) {
+            pSysInfo->SelfTestSeq = _STEST_FAIL;
+            return;
+        }
+
+        if (pSysConfig->TotalConnectorCount > 0) {
+            if (ShmPsuData->Work_Step == _NO_WORKING ||
+                    pSysInfo->SelfTestSeq == _STEST_FAIL) {
+                pSysInfo->SelfTestSeq = _STEST_FAIL;
+                return;
+            }
+
+            switch (pSysInfo->SelfTestSeq) {
+            case _STEST_VERSION: {
+                if ((strlen((char *)pSysInfo->RelayModuleFwRev) != 0 ||
+                        pSysInfo->RelayModuleFwRev[0] != '\0')
+                        && (ShmRelayModuleData->SelfTest_Comp != YES)
+                   ) {
+                    log_info("Relay Board FW Rev = %s", pSysInfo->RelayModuleFwRev);
+                    ShmRelayModuleData->SelfTest_Comp = YES;
+                }
+#if !defined NO_FAN_BOARD && !defined DD360ComBox
+                if ((strlen((char *)pSysInfo->FanModuleFwRev) != 0 ||
+                        pSysInfo->FanModuleFwRev[0] != '\0')
+                        && (ShmFanModuleData->SelfTest_Comp != YES)
+                   ) {
+                    log_info("Fan Board FW Rev = %s", pSysInfo->FanModuleFwRev);
+                    ShmFanModuleData->SelfTest_Comp = YES;
+                }
+#else
+                ShmFanModuleData->SelfTest_Comp = YES;
+#endif //NO_FAN_BOARD
+
+                if ((strlen((char *)ShmPrimaryMcuData->version) != 0 ||
+                        ShmPrimaryMcuData->version[0] != '\0')
+                        && (ShmPrimaryMcuData->SelfTest_Comp != YES)
+                   ) {
+                    log_info("Primary FW Rev = %s", pSysInfo->CsuPrimFwRev);
+                    ShmPrimaryMcuData->SelfTest_Comp = YES;
+                }
+
+                // EV 小板
+                if (!evInitFlag) {
+                    evInitFlag = YES;
+                    for (uint8_t index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+                        pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+                        //log_info("index = %d, charging index = %d, type = %d\r\n",
+                        //         index,
+                        //         chargingInfo[index]->type_index,
+                        //         chargingInfo[index]->Type);
+                        if (pDcChargingInfo->Type == _Type_Chademo) {
+                            if ((strlen((char *)ShmCHAdeMOData->evse[pDcChargingInfo->type_index].version) != 0 ||
+                                    ShmCHAdeMOData->evse[pDcChargingInfo->type_index].version[0] != '\0')
+                                    //&& (ShmCHAdeMOData->evse[pDcChargingInfo->type_index].SelfTest_Comp != YES)
+                               ) {
+                                log_info("CHAdeMO[%d] FW Rev = %s", pDcChargingInfo->type_index, ShmCHAdeMOData->evse[pDcChargingInfo->type_index].version);
+                                ShmCHAdeMOData->evse[pDcChargingInfo->type_index].SelfTest_Comp = YES;
+                            } else {
+                                //log_info("chademo fw lose...... %s \n", ShmCHAdeMOData->evse[pDcChargingInfo->type_index].version);
+                                evInitFlag = NO;
+                            }
+                        } else if (pDcChargingInfo->Type == _Type_GB) {
+                            if ((strlen((char *)ShmGBTData->evse[pDcChargingInfo->type_index].version) != 0 ||
+                                    ShmGBTData->evse[pDcChargingInfo->type_index].version[0] != '\0')
+                                    //&& (ShmGBTData->evse[pDcChargingInfo->type_index].SelfTest_Comp != YES)
+                               ) {
+                                log_info("GBT[%d] FW Rev = %s", pDcChargingInfo->type_index, ShmGBTData->evse[pDcChargingInfo->type_index].version);
+                                ShmGBTData->evse[pDcChargingInfo->type_index].SelfTest_Comp = YES;
+                            } else {
+                                //log_info("GBT fw lose...... %s \n", ShmCHAdeMOData->evse[pDcChargingInfo->type_index].version);
+                                evInitFlag = NO;
+                            }
+                        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                            if (ShmCcsData->CommProtocol == _CCS_COMM_V2GMessage_DIN70121) {
+                                if ((strlen((char *)ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].version) != 0 ||
+                                        ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].version[0] != '\0')
+                                        /*&&(ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].SelfTest_Comp != YES)*/
+                                   ) {
+                                    log_info("CCS[%d] FW Rev = %s",
+                                             pDcChargingInfo->type_index,
+                                             ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].version);
+                                    ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].SelfTest_Comp = YES;
+                                } else {
+                                    //log_info("CCS[%d] ccs fw lose...... %s \n",
+                                    //         chargingInfo[index]->type_index,
+                                    //         ShmCcsData->V2GMessage_DIN70121[chargingInfo[index]->type_index].version);
+                                    evInitFlag = NO;
+                                }
+                            }
+                        }
+                    }
+
+                    for (uint8_t index = 0; index < pSysConfig->AcConnectorCount; index++) {
+                        pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(index);
+
+                        if (pAcChargingInfo->Type == _Type_AC) {
+                            if ((strlen((char *)pAcChargingInfo->version) != 0 || pAcChargingInfo->version[0] != '\0')
+                                    && (pAcChargingInfo->SelfTest_Comp != YES)
+                               ) {
+                                log_info("AC connector[%d] FW Rev = %s", index, pAcChargingInfo->version);
+                                pAcChargingInfo->SelfTest_Comp = YES;
+                            } else {
+                                evInitFlag = NO;
+                            }
+                        }
+                    }
+                }
+
+                if ( ShmFanModuleData->SelfTest_Comp &&
+                        ShmRelayModuleData->SelfTest_Comp &&
+                        ShmPrimaryMcuData->SelfTest_Comp &&
+                        evInitFlag
+                   ) {
+                    pSysInfo->SelfTestSeq = _STEST_AC_CONTACTOR;
+                }
+            }
+            break;
+            case _STEST_AC_CONTACTOR: {
+                //ShmPsuData->Work_Step = _TEST_COMPLETE;
+                // 因為 30KW 以下沒有 Relay feedback 功能,所以暫時先直接跳過
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                if (pSysInfo->AcContactorStatus == YES) {
+                    pSysInfo->SelfTestSeq = _STEST_PSU_DETECT;
+                    log_info("AC contactor self test OK");
+                }
+#else
+                pSysInfo->SelfTestSeq = _STEST_PSU_DETECT;
+                log_info("Waiting for DO communication");
+#endif //!defined DD360 && !defined DD360Audi
+            }
+            break;
+            case _STEST_PSU_DETECT: {
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                if (ShmPsuData->Work_Step >= GET_SYS_CAP) {
+                    pSysInfo->SelfTestSeq = _STEST_PSU_CAP;
+                }
+#else
+                pSysInfo->SelfTestSeq = _STEST_PSU_CAP;
+#endif //defined DD360 && !defined DD360Audi
+            }
+            break;
+            case _STEST_PSU_CAP: {
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                // 此測試是要確認當前總輸出能力
+                // 如果沒有 PSU 模組請 bypass
+                if (ShmPsuData->Work_Step == BOOTING_COMPLETE) {
+                    sleep(1);
+                    pSysInfo->SelfTestSeq = _STEST_COMPLETE;
+                    pSysInfo->BootingStatus = BOOT_COMPLETE;
+                }
+#else
+                //check the power limit from DO
+                pSysInfo->SelfTestSeq = _STEST_COMPLETE;
+                pSysInfo->BootingStatus = BOOT_COMPLETE;
+                log_info("Successful Self Test");
+#endif //defined DD360 && !defined DD360Audi
+            }
+            break;
+            }
+        } else {
+            break;
+        }
+
+        usleep(100000);
+    }
+}

+ 0 - 303
EVSE/Projects/DD360Audi/Apps/CSU/TimeTask.c

@@ -1,303 +0,0 @@
-
-void _CcsPrechargeTimeout(uint8_t gunIndex)
-{
-    log_info("*********** _CcsPrechargeTimeout ***********\n");
-    setChargerMode(gunIndex, MODE_IDLE);
-}
-
-void _DetectEvseChargingEnableTimeout(uint8_t gunIndex)
-{
-    log_info("*********** _DetectEvseChargingEnableTimeout (GFD timeout) ***********\n");
-    //if (chargingInfo[gunIndex]->GroundFaultStatus != GFD_PASS)
-    {
-        setChargerMode(gunIndex, MODE_IDLE);
-        _AutoReturnTimeout();
-    }
-}
-
-void _DetectEvChargingEnableTimeout(uint8_t gunIndex)
-{
-    if (chargingInfo[gunIndex]->Type == _Type_Chademo) {
-        if (!isEvGunLocked_chademo(gunIndex)) {
-            log_info("*********** _DetectEvChargingEnableTimeout (chademo) ***********\n");
-        }
-    } else if (chargingInfo[gunIndex]->Type == _Type_GB) {
-        if (!isEvGunLocked_ccs(gunIndex)) {
-            log_info("*********** _DetectEvChargingEnableTimeout (gb) ***********\n");
-        }
-    } else if (chargingInfo[gunIndex]->Type == _Type_CCS_2) {
-        if (!isEvGunLocked_ccs(gunIndex)) {
-            log_info("*********** _DetectEvChargingEnableTimeout (ccs) ***********\n");
-        }
-    }
-    ChargingTerminalProcess(gunIndex);
-    _AutoReturnTimeout();
-}
-
-void _PrepareTimeout(uint8_t gunIndex)
-{
-    log_info("*********** _PrepareTimeout ***********\n");
-    setChargerMode(gunIndex, MODE_IDLE);
-    ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuNoResource = YES;
-    _AutoReturnTimeout();
-}
-
-void ClearAuthorizedFlag()
-{
-    ShmOCPP16Data->SpMsg.bits.AuthorizeConf = NO;
-    ShmSysConfigAndInfo->SysInfo.AuthorizeFlag = NO;
-}
-
-void DisplayChargingInfo()
-{
-    log_info("*********** DisplayChargingInfo *********** \n");
-    for (uint8_t i = 0; i < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; i++) {
-        if (chargingInfo[i]->SystemStatus != S_IDLE &&
-                chargingInfo[i]->SystemStatus != S_RESERVATION) {
-            ChangeGunSelectByIndex(i);
-            return;
-        }
-    }
-
-    if (ShmSysConfigAndInfo->SysConfig.AcConnectorCount > 0 &&
-            ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc == NO_DEFINE &&
-            ac_chargingInfo[0]->SystemStatus >= S_PREPARNING && ac_chargingInfo[0]->SystemStatus <= S_COMPLETE) {
-        ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc = DEFAULT_AC_INDEX;
-    }
-
-    usleep(50000);
-#if defined DD360Audi
-    ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_SELECT_GUN;
-#else
-    ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_NONE;
-#endif //defined DD360Audi
-}
-
-void _DetectPlugInTimeout()
-{
-    log_info("*********** _DetectPlugInTimeout *********** \n");
-    strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
-    ClearDetectPluginFlag();
-    //usleep(50000);
-    sleep(1); //Jerry add
-#if defined DD360Audi
-    ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_SELECT_GUN;
-#else
-    ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_NONE;
-#endif //defined DD360Audi
-}
-
-void _AutoReturnTimeout()
-{
-    log_info("*********** _AutoReturnTimeout %d*********** \n", ShmSysConfigAndInfo->SysInfo.PageIndex);
-    if (ShmSysConfigAndInfo->SysInfo.PageIndex == _LCM_WAIT_FOR_PLUG) {
-        ClearDetectPluginFlag();
-    } else if (ShmSysConfigAndInfo->SysInfo.PageIndex == _LCM_AUTHORIZ_COMP) {
-        DetectPluginStart();
-    }
-    usleep(50000);
-#if defined DD360Audi
-    ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_SELECT_GUN;
-#else
-    ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_NONE;
-#endif //defined DD360Audi
-}
-
-void StopSystemTimeoutDet()
-{
-    gettimeofday(&ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer, NULL);
-    ShmSysConfigAndInfo->SysInfo.SystemTimeoutFlag = Timeout_None;
-}
-
-void _SelfTestTimeout()
-{
-    if (ShmSysConfigAndInfo->SysInfo.BootingStatus != BOOT_COMPLETE) {
-        for (uint8_t gun_index = 0; gun_index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; gun_index++) {
-            setChargerMode(gun_index, MODE_ALARM);
-        }
-    }
-    ShmPsuData->Work_Step = _NO_WORKING;
-    ShmSysConfigAndInfo->SysInfo.SelfTestSeq = _STEST_FAIL;
-    log_info("Self test timeout. \n");
-}
-
-void CheckConnectionTimeout(void)
-{
-#if defined DD360 || defined DD360Audi || defined DD360ComBox
-    if (gAudiCustInfo->RemoteSetup.ConnectionTimeout != 0) { //Jerry add
-        _connectionTimeout = gAudiCustInfo->RemoteSetup.ConnectionTimeout;
-    } else {
-        _connectionTimeout = CONN_PLUG_TIME_OUT;
-    }
-
-    return;
-#endif //defined DD360 || defined DD360Audi || defined DD360ComBox
-
-    if (system("pidof -s OcppBackend > /dev/null") != 0) {
-        _connectionTimeout = CONN_PLUG_TIME_OUT;
-    } else {
-        if (strcmp((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[ConnectionTimeOut].ItemData, "") != 0) {
-            _connectionTimeout = atoi((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[ConnectionTimeOut].ItemData);
-            if (_connectionTimeout <= 0) {
-                _connectionTimeout = CONN_PLUG_TIME_OUT;
-            }
-        } else {
-            _connectionTimeout = CONN_PLUG_TIME_OUT;
-        }
-    }
-}
-
-void CreateTimeoutFork(void)
-{
-    pid_t timeoutPid;
-
-    timeoutPid = fork();
-    log_info("CreateTimeoutFork = %d\r\n", timeoutPid);
-    if (timeoutPid == 0) {
-        gettimeofday(&_cmdSubPriority_time, NULL);
-        CheckConnectionTimeout();
-
-        while (1) {
-            if ((GetTimeoutValue(_cmdSubPriority_time) / 1000) > 5000) {
-                CheckConnectionTimeout();
-                gettimeofday(&_cmdSubPriority_time, NULL);
-            }
-
-            //printf("Timeout ***********SystemTimeoutFlag = %d, ********\n", ShmSysConfigAndInfo->SysInfo.SystemTimeoutFlag);
-            // 系統
-            switch (ShmSysConfigAndInfo->SysInfo.SystemTimeoutFlag) {
-            case Timeout_SelftestChk:
-                if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) / uSEC_VAL >= SELFTEST_TIMEOUT) {
-                    _SelfTestTimeout();
-                    StopSystemTimeoutDet();
-                    destroySelGun(DESTROY_ALL_SEL); //jerry add
-                }
-                break;
-
-            case Timeout_Authorizing:
-                if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) / uSEC_VAL >= AUTHORIZE_TIMEOUT) {
-                    _AuthorizedTimeout();
-                    StopSystemTimeoutDet();
-                    destroySelGun(ShmSysConfigAndInfo->SysInfo.CurGunSelected);
-                    if (gAudiCustInfo->AuthorStateFromCabinet[ShmSysConfigAndInfo->SysInfo.CurGunSelected] == YES) { //DoComm no ask cabinet balance
-                        gAudiCustInfo->AuthorStateFromCabinet[ShmSysConfigAndInfo->SysInfo.CurGunSelected] = NO;
-                        ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DisconnectedFromDo = ABNORMAL;
-                        log_error("Author timeout restart DoComm\r\n");
-                        system("killall Module_DoComm");
-                        sleep(1);
-                        system("/root/Module_DoComm &");
-                    }
-                }
-                break;
-
-            case Timeout_VerifyFail:
-                if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) / uSEC_VAL >= AUTHORIZE_FAIL_TIMEOUT) {
-                    _AutoReturnTimeout();
-                    StopSystemTimeoutDet();
-                    destroySelGun(ShmSysConfigAndInfo->SysInfo.CurGunSelected);
-                    if (gAudiCustInfo->AuthorStateFromCabinet[ShmSysConfigAndInfo->SysInfo.CurGunSelected] == YES) { //DoComm no ask cabinet balance
-                        gAudiCustInfo->AuthorStateFromCabinet[ShmSysConfigAndInfo->SysInfo.CurGunSelected] = NO;
-                        ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DisconnectedFromDo = ABNORMAL;
-                        log_error("Author timeout restart DoComm\r\n");
-                        system("killall Module_DoComm");
-                        sleep(1);
-                        system("/root/Module_DoComm &");
-                    }
-                }
-                break;
-
-            case Timeout_VerifyComp:
-                if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) / uSEC_VAL >= AUTHORIZE_COMP_TIMEOUT) {
-                    _AutoReturnTimeout();
-                    StopSystemTimeoutDet();
-                }
-                break;
-
-            case Timeout_WaitPlug:
-                if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) / uSEC_VAL >= _connectionTimeout) {
-                    _DetectPlugInTimeout();
-                    StopSystemTimeoutDet();
-                    destroySelGun(ShmSysConfigAndInfo->SysInfo.CurGunSelected);
-                }
-                break;
-
-            case Timeout_ReturnToChargingGunDet:
-                if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) / uSEC_VAL >= RETURN_TO_CHARGING_PAGE) {
-#if defined DD360Audi
-                    if (getCurLcmPage() != _LCM_PRE_CHARGE &&
-                            getCurLcmPage() != _LCM_CHARGING &&
-                            getCurLcmPage() != _LCM_COMPLETE) {
-                        destroySelGun(ShmSysConfigAndInfo->SysInfo.CurGunSelected); //jerry add
-
-                    }
-#endif //defined DD360Audi
-                    DisplayChargingInfo();
-                    StopSystemTimeoutDet();
-                }
-                break;
-
-            case Timeout_AuthorizingForStop:
-                if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) / uSEC_VAL >= AUTHORIZE_STOP_TIMEOUT) {
-                    strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
-                    ClearAuthorizedFlag();
-                    StopSystemTimeoutDet();
-                }
-                break;
-
-            } //switch
-
-            // 各槍
-            for (uint8_t gun_index = 0; gun_index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; gun_index++) {
-                //printf("Timeout ***********TimeoutFlag = %d, ********\n", chargingInfo[gun_index]->TimeoutFlag);
-                switch (chargingInfo[gun_index]->TimeoutFlag) {
-                case Timeout_Preparing:
-                    if (GetTimeoutValue(chargingInfo[gun_index]->TimeoutTimer) / uSEC_VAL >= GUN_PREPARE_TIMEOUT) {
-                        _PrepareTimeout(gun_index);
-                        StopGunInfoTimeoutDet(gun_index);
-                        destroySelGun(gun_index); //jerry add
-                    }
-                    break;
-
-                case Timeout_EvChargingDet:
-                    if (GetTimeoutValue(chargingInfo[gun_index]->TimeoutTimer) / uSEC_VAL >= GUN_EV_WAIT_TIMEOUT) {
-                        _DetectEvChargingEnableTimeout(gun_index);
-                        StopGunInfoTimeoutDet(gun_index);
-                        destroySelGun(gun_index); //jerry add
-                    }
-                    break;
-
-                case Timeout_EvseChargingDet:
-                    if (GetTimeoutValue(chargingInfo[gun_index]->TimeoutTimer) / uSEC_VAL >= GUN_EVSE_WAIT_TIMEOUT) {
-                        _DetectEvseChargingEnableTimeout(gun_index);
-                        StopGunInfoTimeoutDet(gun_index);
-                        destroySelGun(gun_index); //jerry add
-                    }
-                    break;
-
-                case Timeout_EvseCompleteDet:
-                    if (GetTimeoutValue(chargingInfo[gun_index]->TimeoutTimer) / uSEC_VAL >= GUN_COMP_WAIT_TIMEOUT) {
-                        StopGunInfoTimeoutDet(gun_index);
-                        destroySelGun(gun_index); //jerry add
-                    }
-                    break;
-
-                case Timeout_ForCcsPrechargeDet:
-                    if (GetTimeoutValue(chargingInfo[gun_index]->TimeoutTimer) / uSEC_VAL >= GUN_PRECHARGING_TIMEOUT) {
-                        _CcsPrechargeTimeout(gun_index);
-                        StopGunInfoTimeoutDet(gun_index);
-                        destroySelGun(gun_index); //jerry add
-                    }
-                    break;
-
-                case Timeout_SelectGun: //Jerry add
-                    if (GetTimeoutValue(chargingInfo[gun_index]->TimeoutTimer) / uSEC_VAL >= SEL_GUN_TIMEOUT) {
-                        StopGunInfoTimeoutDet(gun_index);
-                        destroySelGun(gun_index); //jerry add
-                    }
-                    break;
-                } //switch
-            } //for
-            sleep(1);
-        }//while
-    }
-}

+ 134 - 8
EVSE/Projects/DD360Audi/Apps/CSU/Update.c → EVSE/Projects/DD360Audi/Apps/CSU/UpgradeFW.c

@@ -3,30 +3,115 @@
 #include <string.h>
 #include <stdint.h>
 
+#include <sys/types.h>
+#include <dirent.h>
+
 #include "../Config.h"
 #include "../Log/log.h"
 #include "../Define/define.h"
 #include "../ShareMemory/shmMem.h"
 
+#include "../main.h"
+
+//------------------------------------------------------------------------------
+static char *_priPortName = "/dev/ttyS1";
+static char *_485PortName = "/dev/ttyS5";
+
 //------------------------------------------------------------------------------
-int CheckUpdateProcess(void)
+static int InitComPort(uint8_t target)
+{
+    int fd;
+    struct termios tios;
+
+    if (target == UPGRADE_PRI) {
+        fd = open(_priPortName, O_RDWR);
+    } else if (target == UPGRADE_FAN ||  target == UPGRADE_RB || target == UPGRADE_AC || target == UPGRADE_LED) {
+        fd = open(_485PortName, O_RDWR);
+    }
+
+    if (fd <= 0) {
+#ifdef SystemLogMessage
+        log_error("open 407 Communication port NG \n");
+#endif
+        return -1;
+    }
+    ioctl (fd, TCGETS, &tios);
+    tios.c_cflag = B115200 | CS8 | CLOCAL | CREAD;
+    tios.c_lflag = 0;
+    tios.c_iflag = 0;
+    tios.c_oflag = 0;
+    tios.c_cc[VMIN] = 0;
+    tios.c_cc[VTIME] = (uint8_t)1;
+    tios.c_lflag = 0;
+    tcflush(fd, TCIFLUSH);
+    ioctl (fd, TCSETS, &tios);
+
+    return fd;
+}
+
+static int InitCanBus(void)
+{
+    int fd = -1;
+    int nbytes;
+    struct timeval tv;
+    struct ifreq ifr0;
+    struct sockaddr_can addr0;
+
+    system("/sbin/ip link set can0 down");
+    system("/sbin/ip link set can0 type can bitrate 500000 restart-ms 100");
+    system("/sbin/ip link set can0 up");
+
+    fd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
+
+    tv.tv_sec = 0;
+    tv.tv_usec = 10000;
+    if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct  timeval)) < 0) {
+#ifdef SystemLogMessage
+        log_error("Set SO_RCVTIMEO NG");
+#endif
+    }
+    nbytes = 40960;
+    if (setsockopt(fd, SOL_SOCKET,  SO_RCVBUF, &nbytes, sizeof(int)) < 0) {
+#ifdef SystemLogMessage
+        log_error("Set SO_RCVBUF NG");
+#endif
+    }
+    nbytes = 40960;
+    if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &nbytes, sizeof(int)) < 0) {
+#ifdef SystemLogMessage
+        log_error("Set SO_SNDBUF NG");
+#endif
+    }
+
+    strcpy(ifr0.ifr_name, "can0");
+    ioctl(fd, SIOCGIFINDEX, &ifr0); /* ifr.ifr_ifindex gets filled with that device's index */
+    addr0.can_family = AF_CAN;
+    addr0.can_ifindex = ifr0.ifr_ifindex;
+    bind(fd, (struct sockaddr *)&addr0, sizeof(addr0));
+
+    return fd;
+}
+
+static int CheckUpdateProcess(void)
 {
     //bool isPass = true;
     uint8_t retSucc = 0;
     uint8_t retFail = 0;
     uint8_t index = 0;
     uint8_t target = 0;
+    char Buf[256];
     char *new_str = NULL;
     uint8_t *ptr = NULL;
     int fd = 0;
     int CanFd = 0;
     int uartFd = 0;
     unsigned int Type = 0;
-    long int MaxLen = (48 * 1024 * 1024, ImageLen = 0);
+    long int MaxLen = 48 * 1024 * 1024, ImageLen = 0;
     DIR *d;
     struct dirent *dir;
     struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
-    struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
+    DcCommonInfo *ShmDcCommonData = (DcCommonInfo *)GetShmDcCommonData();
+    struct ChargingInfoData *pDcChargingInfo = NULL;
 
     d = opendir("/mnt/");
     if (d) {
@@ -84,14 +169,47 @@ int CheckUpdateProcess(void)
                 case 0x10000008:
                 case 0x10000009:
                 case 0x1000000A:
+                    CanFd = InitCanBus();
+                    if (CanFd > 0) {
+                        for (index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+                            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+                            if (pDcChargingInfo->Type == _Type_CCS_2) {
+                                uint8_t targetID = pDcChargingInfo->Evboard_id;
+
+                                if (pSysConfig->TotalConnectorCount == 1 &&
+                                        ShmDcCommonData->CcsVersion == _CCS_VERSION_CHECK_TAG_V015S0) {
+                                    targetID += 1;
+                                }
+
+                                system("echo 3 > /proc/sys/vm/drop_caches");
+                                sleep(2);
+                                log_info("Upgrade CCS Processing..target id = %d \n", targetID);
+                                if (Upgrade_CCS(CanFd,
+                                                Type,
+                                                targetID,
+                                                new_str,
+                                                (char *)pSysConfig->ModelName) == FAIL) {
+                                    log_info("Upgrade CCS Failed \n");
+                                    retFail++;
+                                } else {
+                                    retSucc++;
+                                }
+                            }
+                        }
+                        close(CanFd);
+                    }
+                    memset(Buf, 0, sizeof(Buf));
+                    sprintf(Buf, "rm -rvf /mnt/%s", new_str);
+                    system(Buf);
                     //isPass = true;
+#if 0
                     CanFd = InitCanBus();
                     if (CanFd > 0) {
                         for (index = 0; index < pSysConfig->TotalConnectorCount; index++) {
                             //if (!isPass) {
                             //    break;
                             //}
-
                             if (chargingInfo[index]->Type == _Type_CCS_2) {
                                 if (Upgrade_CCS(CanFd, Type, chargingInfo[index]->Evboard_id, new_str, (char *)pSysConfig->ModelName) == FAIL) {
                                     //isPass = false;
@@ -112,6 +230,7 @@ int CheckUpdateProcess(void)
                         retSucc++;
                     }
                     //return isPass;
+#endif //0
                     break;
 
                 case 0x10000006:
@@ -157,13 +276,15 @@ int CheckUpdateProcess(void)
                     CanFd = InitCanBus();
                     if (CanFd > 0) {
                         for (index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+                            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
                             //if (!isPass) {
                             //    break;
                             //}
 
-                            if ((Type == 0x1000000B && chargingInfo[index]->Type == _Type_Chademo) ||
-                                    (Type == 0x1000000C && chargingInfo[index]->Type == _Type_GB)) {
-                                if (Upgrade_CAN(CanFd, Type, chargingInfo[index]->Evboard_id, new_str, (char *)pSysConfig->ModelName) == PASS) {
+                            if ((Type == 0x1000000B && pDcChargingInfo->Type == _Type_Chademo) ||
+                                    (Type == 0x1000000C && pDcChargingInfo->Type == _Type_GB)) {
+                                if (Upgrade_CAN(CanFd, Type, pDcChargingInfo->Evboard_id, new_str, (char *)pSysConfig->ModelName) == PASS) {
                                     //isPass = PASS;
                                     retSucc++;
                                 } else {
@@ -201,6 +322,8 @@ void CheckFwUpdateFunction(void)
 {
     struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
     struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
+    struct OCPP16Data *ShmOCPP16Data = (struct OCPP16Data *)GetShmOCPP16Data();
+    struct ChargingInfoData *pAcChargingInfo = NULL;
 
     //log_info("pSysInfo->FirmwareUpdate = %d \n", pSysInfo->FirmwareUpdate);
     if (pSysInfo->FirmwareUpdate == YES) {
@@ -240,8 +363,11 @@ void CheckFwUpdateFunction(void)
             for (uint8_t _index = 0; _index < pSysConfig->TotalConnectorCount; _index++) {
                 setChargerMode(_index, MODE_UPDATE);
             }
+
             for (uint8_t _index = 0; _index < pSysConfig->AcConnectorCount; _index++) {
-                ac_chargingInfo[_index]->SystemStatus = MODE_UPDATE;
+                pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(_index);
+
+                pAcChargingInfo->SystemStatus = MODE_UPDATE;
             }
 
             uint8_t updateResult = CheckUpdateProcess();

+ 48 - 0
EVSE/Projects/DD360Audi/Apps/CSU/WatchDog.c

@@ -0,0 +1,48 @@
+#include <stdio.h>      /*標準輸入輸出定義*/
+#include <stdlib.h>     /*標準函數庫定義*/
+#include <string.h>
+#include <stdint.h>
+
+#include "../Config.h"
+#include "../Log/log.h"
+#include "../Define/define.h"
+#include "../ShareMemory/shmMem.h"
+
+//------------------------------------------------------------------------------
+static int gWatchDogfd = -1;
+
+//------------------------------------------------------------------------------
+void WriteWatchDogState(char *value)
+{
+    write(gWatchDogfd, value, 1);
+}
+
+static int initWatchDog(void)
+{
+    int fd;
+    system("/usr/bin/fuser -k /dev/watchdog");
+    sleep(1);
+    system("echo V > /dev/watchdog");
+    sleep(1);
+    fd = open("/dev/watchdog", O_RDWR);
+
+    if (fd <= 0) {
+        log_error("System watch dog initial fail.\r\n");
+    }
+
+    return fd;
+}
+
+void CreateWatchdog(void)
+{
+    struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
+    struct AlarmCodeData *pAlarmCode = (struct AlarmCodeData *)GetShmAlarmCodeData();
+
+    if (pSysConfig->SwitchDebugFlag == NO) {
+        gWatchDogfd = initWatchDog();
+
+        if (gWatchDogfd < 0) {
+            pAlarmCode->AlarmEvents.bits.CsuInitFailed = 1;
+        }
+    }
+}

+ 15 - 0
EVSE/Projects/DD360Audi/Apps/CSU/ZipFile.c

@@ -1,7 +1,21 @@
+#include <stdio.h>      /*標準輸入輸出定義*/
+#include <stdlib.h>     /*標準函數庫定義*/
+#include <string.h>
+#include <stdint.h>
 
+#include <sys/types.h>
+#include <dirent.h>
+
+#include "../Config.h"
+#include "../Log/log.h"
+#include "../Define/define.h"
+#include "../ShareMemory/shmMem.h"
+
+//------------------------------------------------------------------------------
 void zipLogFiles(void)
 {
     const char *logPath = "/Storage/SystemLog";
+
     // 獲取目錄
     DIR *pDir = opendir(logPath);
     if (pDir != NULL) {
@@ -57,6 +71,7 @@ void zipLogFiles(void)
             }
         }
     }
+
     // Close folder
     closedir(pDir);
 }

+ 7407 - 0
EVSE/Projects/DD360Audi/Apps/CSU/main.c

@@ -0,0 +1,7407 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/mman.h>
+#include <linux/wireless.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include <unistd.h>
+#include <stdarg.h>
+#include <stdio.h>      /*標準輸入輸出定義*/
+#include <stdlib.h>     /*標準函數庫定義*/
+#include <unistd.h>     /*Unix 標準函數定義*/
+#include <fcntl.h>      /*檔控制定義*/
+#include <termios.h>    /*PPSIX 終端控制定義*/
+#include <errno.h>      /*錯誤號定義*/
+#include <errno.h>
+#include <string.h>
+#include <stdint.h>
+#include <time.h>
+#include <ctype.h>
+#include <ifaddrs.h>
+#include <math.h>
+#include "./Define/define.h"
+#include <stdbool.h>
+#include <dirent.h>
+
+#include "Config.h"
+#include "main.h"
+#include "common.h"
+#include "timeout.h"
+
+#include "./Log/log.h"
+#include "./Define/define.h"
+#include "./ShareMemory/shmMem.h"
+
+#if defined DD360 ||defined DD360Audi || defined DD360ComBox
+#include "./SelectGun/SelectGun.h"
+#endif //defined DD360Audi
+
+//------------------------------------------------------------------------------
+char *valid_Internet[2] = {"8.8.8.8", "180.76.76.76"};
+uint8_t mask_table[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
+int whileLoopTime = 10000; // 10 ms
+//int wtdFd = -1;
+//uint8_t _authorizeIndex = NO_DEFINE;
+
+//struct SysConfigAndInfo         *ShmSysConfigAndInfo;
+//struct StatusCodeData           *ShmStatusCodeData;
+static struct SysInfoData *pSysInfo = NULL;
+static struct SysConfigData *pSysConfig = NULL;
+static struct WARNING_CODE_INFO *pSysWarning = NULL;
+
+static struct AlarmCodeData *pAlarmCode = NULL;
+static struct FaultCodeData *pFaultCode = NULL;
+static struct InfoCodeData  *pInfoCode = NULL;
+
+static struct PsuData *ShmPsuData = NULL;
+static struct CHAdeMOData *ShmCHAdeMOData = NULL;
+static struct GBTData *ShmGBTData = NULL;
+static struct CcsData *ShmCcsData = NULL;
+static struct PrimaryMcuData *ShmPrimaryMcuData = NULL;
+static struct FanModuleData *ShmFanModuleData = NULL;
+static struct RelayModuleData *ShmRelayModuleData = NULL;
+static struct LedModuleData *ShmLedModuleData = NULL;
+static struct OCPP16Data *ShmOCPP16Data = NULL;
+static DcCommonInfo *ShmDcCommonData = NULL;
+
+static struct ChargingInfoData *pDcChargingInfo = NULL;
+static struct ChargingInfoData *pAcChargingInfo = NULL;
+
+//struct ChargingInfoData *chargingInfo[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
+//struct ChargingInfoData *ac_chargingInfo[AC_QUANTITY];
+struct timeb startChargingTime[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
+struct timeb endChargingTime[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
+
+#if defined DD360 ||defined DD360Audi || defined DD360ComBox
+static SelectGunInfo             *gAudiCustInfo = NULL; //Jerry add
+#endif //defined DD360Audi
+static EvBoardErrMsg gEvBoardErr = {0};
+
+// for initial index to check EV board type is correct
+//uint8_t _gunIndex = 0;
+//uint8_t _acgunIndex = 0;
+//uint8_t _chademoIndex = 0;
+//uint8_t _ccsIndex = 0;
+//uint8_t _gb_Index = 0;
+//uint8_t _ac_Index = 0;
+uint8_t bd0_1_status = 0;
+uint8_t bd0_2_status = 0;
+uint8_t bd1_1_status = 0;
+uint8_t bd1_2_status = 0;
+
+//static uint8_t restartFlag = 0;
+
+//bool isCardScan = false;
+//bool isModelNameMatch = true;
+
+//int rfidFd = -1;
+//char *rfidPortName = "/dev/ttyS2";
+char *fwVersion = "V1.08.00.0000.00"; // "V0.16.00.0000.00";
+
+//sqlite3 *localDb;
+bool isDb_ready;
+
+//------------------------------------------------------------------------------
+//bool IsAuthorizingMode();
+//void ClearAuthorizedFlag();
+//bool isDetectPlugin();
+void ClearDetectPluginFlag();
+
+long long DiffTimebWithNow(struct timeb ST);
+uint8_t DetectBitValue(uint8_t _byte, uint8_t _bit);
+void SetBitValue(uint8_t *_byte, uint8_t _bit, uint8_t value);
+//void ChargingTerminalProcess(uint8_t gunIndex);
+//void ChkPrimaryStatus();
+//void StartSystemTimeoutDet(uint8_t flag);
+//void StopSystemTimeoutDet();
+//void StartGunInfoTimeoutDet(uint8_t gunIndex, uint8_t flag);
+//void StopGunInfoTimeoutDet(uint8_t gunIndex);
+//int StoreLogMsg_1(const char *fmt, ...);
+unsigned long GetTimeoutValue(struct timeval _sour_time);
+void gpio_set_value(unsigned int gpio, unsigned int value);
+//void ChangeGunSelectByIndex(uint8_t sel);
+void InformOcppErrOccur(uint8_t codeType);
+
+void RecordAlarmCode(uint8_t gunIndex, char *code);
+void RecordWarningCode(uint8_t gunIndex, char *code);
+void ReleaseWarningCodeByString(uint8_t gunIndex, char *code);
+void ReleaseAlarmCode(uint8_t gunIndex);
+void ResetChargerAlarmCode(uint8_t gunIndex, char *code);
+
+void AdjustChargerCurrent();
+
+//------------------------------------------------------------------------------
+//Primary.c
+extern void PrimaryLedIndicatorCtrlFork(void);
+extern void ChkPrimaryStatus(void);
+
+//RFID.c
+extern void CreateRfidFork(void);
+extern void ScannerCardProcess(void);
+extern bool GetIsCardScan(void);
+extern void SetIsCardScan(bool value);
+
+//SelfTest.c
+extern void SelfTestRun(void);
+
+//UpgradeFW.c
+extern void CheckFwUpdateFunction(void);
+
+//Ethernet.c
+extern void InitEthernet(void);
+extern void GetMacAddress(void);
+
+//WatchDog.c
+extern void CreateWatchdog(void);
+extern void WriteWatchDogState(char *value);
+
+//ZipFile.c
+extern void zipLogFiles(void);
+
+///DataBase/DataBase.c
+extern int DB_Open(void);
+extern int DB_Insert_Record(int gun_index);
+extern int DB_Update_Operactive(uint8_t gun_index, uint8_t IsAvailable);
+extern int DB_Get_Operactive(uint8_t gun_index);
+extern int DB_Reboot_Record(void);
+
+//------------------------------------------------------------------------------
+//--- share memory value ---
+//------------------------------------------------------------------------------
+static void changeLcmPage(uint8_t index)
+{
+    pSysInfo->SystemPage = index;
+}
+
+static uint8_t getCurLcmPage(void)
+{
+    return pSysInfo->SystemPage;
+}
+
+//------------------------------------------------------------------------------
+void destroySelGun(uint8_t curGun)
+{
+    uint8_t i = 0;
+    uint8_t totalGun = pSysConfig->TotalConnectorCount;
+
+#if !defined DD360Audi
+    return;
+#endif //!defined DD360Audi
+
+    //for status timeout
+    if (curGun == DESTROY_ALL_SEL) {
+        gAudiCustInfo->SelGunInfo.RightGun = SEL_GUN_RELEASE;
+        gAudiCustInfo->SelGunInfo.LeftGun = SEL_GUN_RELEASE;
+        log_info("destroy all gun = %d, %d\r\n",
+                 gAudiCustInfo->SelGunInfo.LeftGun,
+                 gAudiCustInfo->SelGunInfo.RightGun);
+        for (i = 0; i < totalGun; i++) {
+            StopGunInfoTimeoutDet(i);
+            memset(&gAudiCustInfo->PricesInfo[i], 0, sizeof(PricesInfo));
+        }
+        pSysInfo->CurGunSelected = 0;
+        strcpy((char *)pSysConfig->UserId, "");
+        //changeLcmPage(_LCM_SELECT_GUN);
+        return;
+    }
+
+    //for charging timeout or complete
+    if ((curGun == LEFT_GUN_NUM) && (gAudiCustInfo->SelGunInfo.LeftGun != SEL_GUN_RELEASE)) {
+        if (gAudiCustInfo->SelGunInfo.LeftGun == SEL_GUN_CONFIRM ||
+                gAudiCustInfo->SelGunInfo.LeftGun == SEL_GUN_ATHOR) {
+            changeLcmPage(_LCM_SELECT_GUN);
+        }
+        gAudiCustInfo->SelGunInfo.LeftGun = SEL_GUN_RELEASE;
+        StopGunInfoTimeoutDet(LEFT_GUN_NUM);
+        if (ShmOCPP16Data->SpMsg.bits.AuthorizeConf != NO) {
+            ClearAuthorizedFlag();
+        }
+
+        log_info("destroy left gun, cur page = %d\r\n", getCurLcmPage());
+        if (getCurLcmPage() == pSysInfo->SystemPage) {
+            log_info("clear left balance\r\n");
+            memset(&gAudiCustInfo->PricesInfo[curGun], 0, sizeof(PricesInfo));
+            gAudiCustInfo->PricesInfo[curGun].Balance = FAIL_BALANCE_PRICES;
+        }
+    }
+
+    if ((curGun == RIGHT_GUN_NUM) && (gAudiCustInfo->SelGunInfo.RightGun != SEL_GUN_RELEASE)) {
+        if (gAudiCustInfo->SelGunInfo.RightGun == SEL_GUN_CONFIRM ||
+                gAudiCustInfo->SelGunInfo.RightGun == SEL_GUN_ATHOR) {
+            changeLcmPage(_LCM_SELECT_GUN);
+        }
+        gAudiCustInfo->SelGunInfo.RightGun = SEL_GUN_RELEASE;
+        StopGunInfoTimeoutDet(RIGHT_GUN_NUM);
+        if (ShmOCPP16Data->SpMsg.bits.AuthorizeConf != NO) {
+            ClearAuthorizedFlag();
+        }
+
+        log_info("destroy right gun, cur page = %d\r\n", getCurLcmPage());
+        if (getCurLcmPage() == pSysInfo->SystemPage) {
+            log_info("clear right balance\r\n");
+            memset(&gAudiCustInfo->PricesInfo[curGun], 0, sizeof(PricesInfo));
+            gAudiCustInfo->PricesInfo[curGun].Balance = FAIL_BALANCE_PRICES;
+        }
+    }
+}
+
+static int waitRightGunPlugIt(uint8_t curGun)
+{
+#if !defined DD360Audi
+    return;
+#endif //!defined DD360Audi
+
+    if ((curGun == RIGHT_GUN_NUM) && (gAudiCustInfo->SelGunInfo.RightGun == SEL_GUN_ATHOR)) {
+        return PASS;
+    }
+
+    return FAIL;
+}
+
+static int waitLeftGunPlugIt(uint8_t curGun)
+{
+#if !defined DD360Audi
+    return;
+#endif //!defined DD360Audi
+
+    if ((curGun == LEFT_GUN_NUM) && (gAudiCustInfo->SelGunInfo.LeftGun == SEL_GUN_ATHOR)) {
+        return PASS;
+    }
+
+    return FAIL;
+}
+
+void setSelGunWaitToAuthor(uint8_t curSel)
+{
+#if !defined DD360Audi
+    return;
+#endif //!defined DD360Audi
+
+    if (curSel == LEFT_GUN_NUM && gAudiCustInfo->SelGunInfo.LeftGun == SEL_GUN_CONFIRM) {
+        gAudiCustInfo->SelGunInfo.LeftGun = SEL_GUN_ATHOR;
+        //printf("setSelGunWaitToAuthor left\r\n");
+        StopGunInfoTimeoutDet(curSel);
+    } else if (curSel == RIGHT_GUN_NUM && gAudiCustInfo->SelGunInfo.RightGun == SEL_GUN_CONFIRM) {
+        gAudiCustInfo->SelGunInfo.RightGun = SEL_GUN_ATHOR;
+        //printf("setSelGunWaitToAuthor right\r\n");
+        StopGunInfoTimeoutDet(curSel);
+    }
+}
+
+int getConfirmSelectedGun(uint8_t curSel)
+{
+#if !defined DD360Audi
+    return;
+#endif //!defined DD360Audi
+
+    if (((curSel == LEFT_GUN_NUM) && (gAudiCustInfo->SelGunInfo.LeftGun >= SEL_GUN_CONFIRM)) ||
+            ((curSel == RIGHT_GUN_NUM) && (gAudiCustInfo->SelGunInfo.RightGun >= SEL_GUN_CONFIRM))) {
+        return PASS;
+    }
+
+    return FAIL;
+}
+
+void confirmSelGun(uint8_t selGun)
+{
+#if !defined DD360Audi
+    return;
+#endif //!defined DD360Audi
+
+    if (selGun == LEFT_GUN_NUM) {
+        gAudiCustInfo->SelGunInfo.LeftGun = SEL_GUN_CONFIRM;
+        StopGunInfoTimeoutDet(selGun);
+        //printf("confirmSelGun left\r\n");
+    } else if (selGun == RIGHT_GUN_NUM) {
+        gAudiCustInfo->SelGunInfo.RightGun = SEL_GUN_CONFIRM;
+        StopGunInfoTimeoutDet(selGun);
+        //printf("confirmSelGun right\r\n");
+    }
+
+    changeLcmPage(_LCM_IDLE);
+
+    StartGunInfoTimeoutDet(selGun, Timeout_SelectGun);
+}
+
+static void checkGunOTPState(uint8_t _index)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_index);
+
+    switch (pDcChargingInfo->Type) {
+    case _Type_Chademo:
+        if (pDcChargingInfo->ConnectorTemp != UNDEFINED_TEMP) {
+            if (pDcChargingInfo->ConnectorTemp >= GUN_OTP_VALUE) {
+                RecordAlarmCode(_index, "012229");
+            } else if (pDcChargingInfo->ConnectorTemp != 0 &&
+                       pDcChargingInfo->ConnectorTemp < GUN_OTP_RECOVERY) {
+                ResetChargerAlarmCode(_index, "012229");
+            }
+        } else {
+            // 沒接上 Sensor or 異常
+            //RecordAlarmCode(_index, "011018");
+            ResetChargerAlarmCode(_index, "012229");
+        }
+        break;
+
+    case _Type_CCS_2:
+        // CCS 不管甚麼輸出都會有槍溫偵測!!~
+        if (pDcChargingInfo->ConnectorTemp != UNDEFINED_TEMP) {
+            ResetChargerAlarmCode(_index, "011019");
+
+            if (pDcChargingInfo->ConnectorTemp >= GUN_OTP_VALUE) {
+                RecordAlarmCode(_index, "012230");
+            } else if (pDcChargingInfo->ConnectorTemp != 0 &&
+                       pDcChargingInfo->ConnectorTemp < GUN_OTP_RECOVERY) {
+                ResetChargerAlarmCode(_index, "012230");
+            }
+
+            //ResetChargerAlarmCode(_index, "011019");
+        } else {
+            // 沒接上 Sensor or 異常
+            RecordAlarmCode(_index, "011019");
+            ResetChargerAlarmCode(_index, "012230");
+        }
+        break;
+
+    case _Type_GB:
+        if (pDcChargingInfo->ConnectorTemp != UNDEFINED_TEMP) {
+            if (pDcChargingInfo->ConnectorTemp >= GUN_OTP_VALUE) {
+                RecordAlarmCode(_index, "012231");
+            } else if (pDcChargingInfo->ConnectorTemp != 0 &&
+                       pDcChargingInfo->ConnectorTemp < GUN_OTP_RECOVERY) {
+                ResetChargerAlarmCode(_index, "012231");
+            }
+        } else {
+            // 沒接上 Sensor or 異常
+            RecordAlarmCode(_index, "011020");
+            ResetChargerAlarmCode(_index, "012231");
+        }
+        break;
+    }
+}
+
+static void collectError(uint8_t gunIndex)
+{
+    gEvBoardErr.GunErrMessage |= ShmDcCommonData->ConnectErrList[gunIndex].GunErrMessage;
+}
+
+static void checkGBTAlarmState(uint8_t gunType)
+{
+    // GFD Trip
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 0)) {
+        pAlarmCode->AlarmEvents.bits.GbGfdTrip = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.GbGfdTrip = NO;
+    }
+
+    // UVP
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 1)) {
+        pAlarmCode->AlarmEvents.bits.GbtOutputUVPFail = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.GbtOutputUVPFail = NO;
+    }
+
+    // OTP
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 2)) {
+        pAlarmCode->AlarmEvents.bits.GbConnectorOTP = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.GbConnectorOTP = NO;
+    }
+
+    // OVP
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 3)) {
+        pAlarmCode->AlarmEvents.bits.SystemGbOutputOVP = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.SystemGbOutputOVP = NO;
+    }
+
+    // GFD Warning
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 4)) {
+        pAlarmCode->AlarmEvents.bits.GbGroundfaultWarning = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.GbGroundfaultWarning = NO;
+    }
+
+    // Relay Welding
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 5)) {
+        pFaultCode->FaultEvents.bits.GbOutputRelayWelding = YES;
+    } else {
+        pFaultCode->FaultEvents.bits.GbOutputRelayWelding = NO;
+    }
+
+    // Relay Driving
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 6)) {
+        pFaultCode->FaultEvents.bits.GbOutputRelayDrivingFault = YES;
+    } else {
+        pFaultCode->FaultEvents.bits.GbOutputRelayDrivingFault = NO;
+    }
+
+    // Connect temp Sensor broken
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 7)) {
+        pFaultCode->FaultEvents.bits.GbConnectorTempSensorBroken = YES;
+    } else {
+        pFaultCode->FaultEvents.bits.GbConnectorTempSensorBroken = NO;
+    }
+}
+
+static void checkCCSAlarmState(uint8_t gunType)
+{
+    // GFD Trip
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 0)) {
+        pAlarmCode->AlarmEvents.bits.CcsGfdTrip = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.CcsGfdTrip = NO;
+    }
+
+    // UVP
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 1)) {
+        pAlarmCode->AlarmEvents.bits.CcsOutputUVPFail = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.CcsOutputUVPFail = NO;
+    }
+
+    // OTP
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 2)) {
+        pAlarmCode->AlarmEvents.bits.CcsConnectorOTP = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.CcsConnectorOTP = NO;
+    }
+
+    // OVP
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 3)) {
+        pAlarmCode->AlarmEvents.bits.SystemCcsOutputOVP = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.SystemCcsOutputOVP = NO;
+    }
+
+    // GFD Warning
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 4)) {
+        pAlarmCode->AlarmEvents.bits.CcsGroundfaultWarning = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.CcsGroundfaultWarning = NO;
+    }
+
+    // Relay Welding
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 5)) {
+        pFaultCode->FaultEvents.bits.CcsOutputRelayWelding = YES;
+    } else {
+        pFaultCode->FaultEvents.bits.CcsOutputRelayWelding = NO;
+    }
+
+    // Relay Driving
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 6)) {
+        pFaultCode->FaultEvents.bits.CcsOutputRelayDrivingFault = YES;
+    } else {
+        pFaultCode->FaultEvents.bits.CcsOutputRelayDrivingFault = NO;
+    }
+
+    // Connect temp Sensor broken
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 7)) {
+        pFaultCode->FaultEvents.bits.CcsConnectorTempSensorBroken = YES;
+    } else {
+        pFaultCode->FaultEvents.bits.CcsConnectorTempSensorBroken = NO;
+    }
+}
+
+static void checkChaDeMoAlarmState(uint8_t gunType)
+{
+    // GFD Trip
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 0)) {
+        pAlarmCode->AlarmEvents.bits.ChademoGfdTrip = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.ChademoGfdTrip = NO;
+    }
+
+    // UVP
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 1)) {
+        pAlarmCode->AlarmEvents.bits.ChademoOutputUVPFail = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.ChademoOutputUVPFail = NO;
+    }
+
+    // OTP
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 2)) {
+        pAlarmCode->AlarmEvents.bits.ChademoConnectorOTP = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.ChademoConnectorOTP = NO;
+    }
+
+    // OVP
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 3)) {
+        pAlarmCode->AlarmEvents.bits.SystemChademoOutputOVP = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.SystemChademoOutputOVP = NO;
+    }
+
+    // GFD Warning
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 4)) {
+        pAlarmCode->AlarmEvents.bits.ChademoGroundWarning = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.ChademoGroundWarning = NO;
+    }
+
+    // Relay Welding
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 5)) {
+        pFaultCode->FaultEvents.bits.ChademoOutputRelayWelding = YES;
+    } else {
+        pFaultCode->FaultEvents.bits.ChademoOutputRelayWelding = NO;
+    }
+
+    // Relay Driving
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 6)) {
+        pFaultCode->FaultEvents.bits.ChademoOutputRelayDrivingFault = YES;
+    } else {
+        pFaultCode->FaultEvents.bits.ChademoOutputRelayDrivingFault = NO;
+    }
+
+    // Connect temp Sensor broken
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 7)) {
+        pFaultCode->FaultEvents.bits.ChademoConnectorTempSensorBroken = YES;
+    } else {
+        pFaultCode->FaultEvents.bits.ChademoConnectorTempSensorBroken = NO;
+    }
+}
+
+static void checkEvBoardAlarmState(uint8_t gunType)
+{
+    switch (gunType) {
+    case _Type_Chademo:
+        checkChaDeMoAlarmState(gunType);
+        break;
+
+    case _Type_CCS_2:
+        checkCCSAlarmState(gunType);
+        break;
+
+    case _Type_GB:
+        checkGBTAlarmState(gunType);
+        break;
+    }
+}
+
+#if 0
+static uint8_t checkCabinetEthConnectState(LedConfig *ledConfig)
+{
+    uint8_t ret = NO;
+    LedConfig *pLedConfig = (LedConfig *)ledConfig;
+
+    if (pAlarmCode->AlarmEvents.bits.DisconnectedFromDo == YES) {
+        ret = YES;
+        if (pLedConfig->RedLED == YES) {
+            pLedConfig->RedLED = NO;
+        } else {
+            pLedConfig->RedLED = YES;
+        }
+    }
+
+    return ret;
+}
+
+static void PrimaryLedIndicatorCtrlFork(void)
+{
+#if !defined DD360ComBox
+    return;
+#endif //!defined DD360ComBox
+
+    pid_t pid = fork();
+    if (pid == 0) {
+        uint8_t totalGun = pSysConfig->TotalConnectorCount;
+        uint8_t gunIndex = 0;
+        int isContinue = 1;
+        LedConfig *pLedConfig = (LedConfig *)&ShmPrimaryMcuData->OutputDrv.OutputDrvValue[0];
+
+        while (isContinue) {
+            for (gunIndex = 0; gunIndex < totalGun; gunIndex++) {
+                pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+                //printf("led indicator status = %d\r\n", chargingInfo[gunIndex]->SystemStatus);
+                //printf("level = %d\r\n", pSysWarning->Level);
+                switch (pDcChargingInfo->SystemStatus) {
+                case S_BOOTING:
+                    if (pSysInfo->SelfTestSeq == _STEST_COMPLETE) {
+                        //Module_DoComm tcp disconnect
+                        if (pLedConfig->RedLED == YES ||
+                                pLedConfig->YellowLED == YES ||
+                                pLedConfig->GreenLED == YES) {
+                            pLedConfig->RedLED = NO;
+                            pLedConfig->YellowLED = NO;
+                            pLedConfig->GreenLED = NO;
+                        } else {
+                            pLedConfig->RedLED = YES;
+                            pLedConfig->YellowLED = YES;
+                            pLedConfig->GreenLED = YES;
+                        }
+                        break;
+                    }
+
+                    pLedConfig->RedLED = YES;
+                    pLedConfig->YellowLED = YES;
+                    pLedConfig->GreenLED = YES;
+                    break;
+
+                case S_IDLE:
+                    //Module_DoComm connected and system idle
+                    pLedConfig->RedLED = NO;
+                    pLedConfig->YellowLED = NO;
+                    pLedConfig->GreenLED = YES;
+                    break;
+
+                case S_RESERVATION:
+                case S_AUTHORIZING:
+                case S_REASSIGN_CHECK:
+                case S_REASSIGN:
+                case S_PREPARNING:
+                case S_PREPARING_FOR_EV:
+                case S_PREPARING_FOR_EVSE:
+                case S_CCS_PRECHARGE_ST0:
+                case S_CCS_PRECHARGE_ST1:
+                    //precharging status
+                    if (pLedConfig->GreenLED == YES) {
+                        pLedConfig->GreenLED = NO;
+                    } else {
+                        pLedConfig->GreenLED = YES;
+                    }
+                    break;
+
+                case S_CHARGING:
+                    pLedConfig->RedLED = NO;
+                    if (pLedConfig->YellowLED == YES) {
+                        pLedConfig->YellowLED = NO;
+                    } else {
+                        pLedConfig->YellowLED = YES;
+                    }
+                    pLedConfig->GreenLED = NO;
+                    break;
+
+                case S_ALARM:
+                    pLedConfig->YellowLED = NO;
+                    pLedConfig->GreenLED = NO;
+
+                    if (checkCabinetEthConnectState(pLedConfig) == YES) {
+                        break;
+                    }
+
+                    pLedConfig->RedLED = YES;
+                    break;
+
+                case S_TERMINATING:
+                case S_COMPLETE:
+                    if (pSysWarning->Level == 2) {
+                        pLedConfig->YellowLED = NO;
+                        pLedConfig->GreenLED = NO;
+                        if (checkCabinetEthConnectState(pLedConfig) == YES) {
+                            break;
+                        }
+
+                        pLedConfig->RedLED = YES;
+                    } else {
+                        pLedConfig->RedLED = NO;
+                        pLedConfig->YellowLED = YES;
+                        pLedConfig->GreenLED = NO;
+                    }
+                    break;
+
+                case S_MAINTAIN:
+                case S_FAULT:
+                    pLedConfig->YellowLED = NO;
+                    pLedConfig->GreenLED = NO;
+                    if (pSysWarning->Level == 2) {
+                        if (checkCabinetEthConnectState(pLedConfig) == YES) {
+                            break;
+                        }
+
+                        pLedConfig->RedLED = YES;
+                    }
+                    break;
+
+                case S_BOOKING:
+                case S_DEBUG:
+                case S_UPDATE:
+                case S_NONE:
+                    break;
+                }
+
+                usleep(500000);
+            }//switch
+        }//for
+    }//while
+}
+
+//================================================
+// initial can-bus
+//================================================
+int InitCanBus()
+{
+    int                     s0, nbytes;
+    struct timeval          tv;
+    struct ifreq            ifr0;
+    struct sockaddr_can     addr0;
+
+    system("/sbin/ip link set can0 down");
+    system("/sbin/ip link set can0 type can bitrate 500000 restart-ms 100");
+    system("/sbin/ip link set can0 up");
+
+    s0 = socket(PF_CAN, SOCK_RAW, CAN_RAW);
+
+    tv.tv_sec = 0;
+    tv.tv_usec = 10000;
+    if (setsockopt(s0, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct  timeval)) < 0) {
+#ifdef SystemLogMessage
+        log_error("Set SO_RCVTIMEO NG");
+#endif
+    }
+    nbytes = 40960;
+    if (setsockopt(s0, SOL_SOCKET,  SO_RCVBUF, &nbytes, sizeof(int)) < 0) {
+#ifdef SystemLogMessage
+        log_error("Set SO_RCVBUF NG");
+#endif
+    }
+    nbytes = 40960;
+    if (setsockopt(s0, SOL_SOCKET, SO_SNDBUF, &nbytes, sizeof(int)) < 0) {
+#ifdef SystemLogMessage
+        log_error("Set SO_SNDBUF NG");
+#endif
+    }
+
+    strcpy(ifr0.ifr_name, "can0" );
+    ioctl(s0, SIOCGIFINDEX, &ifr0); /* ifr.ifr_ifindex gets filled with that device's index */
+    addr0.can_family = AF_CAN;
+    addr0.can_ifindex = ifr0.ifr_ifindex;
+    bind(s0, (struct sockaddr *)&addr0, sizeof(addr0));
+    return s0;
+}
+
+//================================================
+// initial uart port
+//================================================
+char *_priPortName = "/dev/ttyS1";
+char *_485PortName = "/dev/ttyS5";
+
+int InitComPort(uint8_t target)
+{
+    int fd;
+    struct termios tios;
+
+    if (target == UPGRADE_PRI) {
+        fd = open(_priPortName, O_RDWR);
+    } else if (target == UPGRADE_FAN ||  target == UPGRADE_RB || target == UPGRADE_AC || target == UPGRADE_LED) {
+        fd = open(_485PortName, O_RDWR);
+    }
+
+    if (fd <= 0) {
+#ifdef SystemLogMessage
+        log_error("open 407 Communication port NG \n");
+#endif
+        return -1;
+    }
+    ioctl (fd, TCGETS, &tios);
+    tios.c_cflag = B115200 | CS8 | CLOCAL | CREAD;
+    tios.c_lflag = 0;
+    tios.c_iflag = 0;
+    tios.c_oflag = 0;
+    tios.c_cc[VMIN] = 0;
+    tios.c_cc[VTIME] = (uint8_t)1;
+    tios.c_lflag = 0;
+    tcflush(fd, TCIFLUSH);
+    ioctl (fd, TCSETS, &tios);
+
+    return fd;
+}
+
+//=================================
+// Common routine
+//=================================
+int StoreLogMsg_1(const char *fmt, ...)
+{
+    char Buf[4096 + 256];
+    char buffer[4096];
+    va_list args;
+    struct timeb  SeqEndTime;
+    struct tm *tm;
+
+    va_start(args, fmt);
+    int rc = vsnprintf(buffer, sizeof(buffer), fmt, args);
+    va_end(args);
+
+    memset(Buf, 0, sizeof(Buf));
+    ftime(&SeqEndTime);
+    SeqEndTime.time = time(NULL);
+    tm = localtime(&SeqEndTime.time);
+
+    if (pSysConfig->SwitchDebugFlag == YES) {
+        sprintf(Buf, "%02d:%02d:%02d:%03d - %s",
+                tm->tm_hour, tm->tm_min, tm->tm_sec, SeqEndTime.millitm, buffer);
+        printf("%s \n", Buf);
+    } else {
+        sprintf(Buf, "echo \"%04d-%02d-%02d %02d:%02d:%02d:%03d - %s\" >> /Storage/SystemLog/[%04d.%02d]SystemLog",
+                tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, SeqEndTime.millitm,
+                buffer,
+                tm->tm_year + 1900, tm->tm_mon + 1);
+        system(Buf);
+    }
+
+    return rc;
+}
+#endif //0
+
+unsigned long GetTimeoutValue(struct timeval _sour_time)
+{
+    struct timeval _end_time;
+    gettimeofday(&_end_time, NULL);
+
+    return 1000000 * (_end_time.tv_sec - _sour_time.tv_sec) + _end_time.tv_usec - _sour_time.tv_usec;
+}
+
+int DiffTimeb(struct timeb ST, struct timeb ET)
+{
+    //return milli-second
+    unsigned int StartTime, StopTime;
+
+    StartTime = (unsigned int)ST.time;
+    StopTime = (unsigned int)ET.time;
+    //return (StopTime-StartTime)*1000+ET.millitm-ST.millitm;
+    return (StopTime - StartTime);
+}
+
+bool CheckTimeOut(struct timeb ST)
+{
+    struct timeb ET;
+    unsigned int StartTime, StopTime;
+
+    ftime(&ET);
+    StartTime = (unsigned int) ST.time;
+    StopTime = (unsigned int) ET.time;
+    return (StopTime > StartTime) ? YES : NO;
+}
+
+void setChargerMode(uint8_t gun_index, uint8_t mode)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun_index);
+
+    pDcChargingInfo->SystemStatus = mode;
+}
+
+long long DiffTimebWithNow(struct timeb ST)
+{
+    //return milli-second
+    struct timeb ET;
+    long long StartTime, StopTime;
+
+    ftime(&ET);
+    StartTime = (long long)ST.time;
+    StopTime = (long long)ET.time;
+    return ((StopTime - StartTime) * 1000) + (ET.millitm - ST.millitm);
+}
+
+//==========================================
+// Log
+//==========================================
+void CheckFwSlotStatusLog()
+{
+    if (bd0_1_status == 0 && bd0_2_status == 1) {
+        log_info("Connector 1 : Chademo");
+    } else if (bd0_1_status == 1 && bd0_2_status == 0) {
+        log_info("Connector 1 : CCS");
+    } else if (bd0_1_status == 1 && bd0_2_status == 1) {
+        log_info("Connector 1 : GB");
+    }
+
+    if (bd1_1_status == 0 && bd1_2_status == 1) {
+        log_info("Connector 2 : Chademo");
+    } else if (bd1_1_status == 1 && bd1_2_status == 0) {
+        log_info("Connector 2 : CCS");
+    } else if (bd1_1_status == 1 && bd1_2_status == 1) {
+        log_info("Connector 2 : GB");
+    }
+}
+
+void CheckHwSlotStatusLog(uint8_t index)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+    if (pDcChargingInfo->Type == _Type_Chademo) {
+        log_info("Hw check : Connector %d, Type : Chademo, Evboard_id = %d \n",
+                 index, pDcChargingInfo->Evboard_id);
+    } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+        log_info("Hw check : Connector %d, Type : CCS, Evboard_id = %d \n",
+                 index, pDcChargingInfo->Evboard_id);
+    } else if (pDcChargingInfo->Type == _Type_GB) {
+        log_info("Hw check : Connector %d, Type : GB, Evboard_id = %d \n",
+                 index, pDcChargingInfo->Evboard_id);
+    }
+}
+
+//==========================================
+// Check interface status
+//==========================================
+int isInterfaceUp(const char *interface)
+{
+    int result = FAIL;
+
+    FILE *fp;
+    char cmd[256];
+    char buf[512];
+
+    strcpy(cmd, "ifconfig");
+    fp = popen(cmd, "r");
+    if (fp != NULL) {
+        while (fgets(buf, sizeof(buf), fp) != NULL) {
+            if (strstr(buf, interface) > 0) {
+                result = PASS;
+            }
+        }
+    }
+    pclose(fp);
+
+    return result;
+}
+
+#if 0
+//=================================
+// Create all share memory
+//=================================
+int CreateShareMemory()
+{
+    uint8_t rebootCount = 0;
+
+    int MeterSMId = FAIL;
+
+    if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo), IPC_CREAT | 0777)) < 0) {
+        return FAIL;
+    } else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0))  == (void *) - 1) {
+        return FAIL;
+    }
+    memset(ShmSysConfigAndInfo, 0, sizeof(struct SysConfigAndInfo));
+
+    if ((MeterSMId = shmget(ShmStatusCodeKey, sizeof(struct StatusCodeData), IPC_CREAT | 0777)) < 0) {
+        return FAIL;
+    } else if ((ShmStatusCodeData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+        return FAIL;
+    }
+
+    memset(ShmStatusCodeData, 0, sizeof(struct StatusCodeData));
+
+    //creat ShmPsuData
+    if ((MeterSMId = shmget(ShmPsuKey, sizeof(struct PsuData), IPC_CREAT | 0777)) < 0) {
+        return FAIL;
+    } else if ((ShmPsuData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+        return FAIL;
+    }
+    memset(ShmPsuData, 0, sizeof(struct PsuData));
+
+    if (CHAdeMO_QUANTITY > 0) {
+        if ((MeterSMId = shmget(ShmCHAdeMOCommKey, sizeof(struct CHAdeMOData),  IPC_CREAT | 0777)) < 0) {
+            return FAIL;
+        } else if ((ShmCHAdeMOData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+            return FAIL;
+        }
+        memset(ShmCHAdeMOData, 0, sizeof(struct CHAdeMOData));
+    }
+
+    if (GB_QUANTITY > 0) {
+        if ((MeterSMId = shmget(ShmGBTCommKey, sizeof(struct GBTData),  IPC_CREAT | 0777)) < 0) {
+            return FAIL;
+        } else if ((ShmGBTData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+            return FAIL;
+        }
+        memset(ShmGBTData, 0, sizeof(struct GBTData));
+    }
+
+    //creat ShmCcsData
+    if (CCS_QUANTITY > 0) {
+        if ((MeterSMId = shmget(ShmCcsCommKey, sizeof(struct CcsData),  IPC_CREAT | 0777)) < 0) {
+            return FAIL;
+        } else if ((ShmCcsData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+            return FAIL;
+        }
+        memset(ShmCcsData, 0, sizeof(struct CcsData));
+    }
+
+    //creat ShmPrimaryMcuData
+    if ((MeterSMId = shmget(ShmPrimaryMcuKey, sizeof(struct PrimaryMcuData), IPC_CREAT | 0777)) < 0) {
+        return FAIL;
+    } else if ((ShmPrimaryMcuData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+        return FAIL;
+    }
+    memset(ShmPrimaryMcuData, 0, sizeof(struct PrimaryMcuData));
+
+    //creat ShmFanModuleData
+    if ((MeterSMId = shmget(ShmFanBdKey, sizeof(struct FanModuleData),  IPC_CREAT | 0777)) < 0) {
+        return FAIL;
+    } else if ((ShmFanModuleData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+        return FAIL;
+    }
+    memset(ShmFanModuleData, 0, sizeof(struct FanModuleData));
+
+    //creat ShmRelayModuleData
+    if ((MeterSMId = shmget(ShmRelayBdKey, sizeof(struct RelayModuleData),  IPC_CREAT | 0777)) < 0) {
+        return FAIL;
+    } else if ((ShmRelayModuleData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+        return FAIL;
+    }
+    memset(ShmRelayModuleData, 0, sizeof(struct RelayModuleData));
+
+    if ((MeterSMId = shmget(ShmLedBdKey, sizeof(struct LedModuleData), IPC_CREAT | 0777)) < 0) {
+        return FAIL;
+    } else if ((ShmLedModuleData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+        return FAIL;
+    }
+    memset(ShmLedModuleData, 0, sizeof(struct LedModuleData));
+
+    //creat ShmOCPP16Data
+    if ((MeterSMId = shmget(ShmOcppModuleKey, sizeof(struct OCPP16Data), IPC_CREAT | 0777)) < 0) {
+        return FAIL;
+    } else if ((ShmOCPP16Data = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+        return FAIL;
+    }
+    // memset(ShmOCPP16Data,0,sizeof(struct OCPP16Data));
+
+#if defined DD360 ||defined DD360Audi || defined DD360ComBox
+    //creat Audi customization info
+    if ((MeterSMId = shmget(ShmSelectGunInfoKey, sizeof(SelectGunInfo), IPC_CREAT | 0777)) < 0) {
+        return FAIL;
+    } else if ((gAudiCustInfo = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+        return FAIL;
+    }
+    memset(gAudiCustInfo, 0, sizeof(SelectGunInfo));
+#endif //defined DD360Audi
+
+    if ((MeterSMId = shmget(ShmCommonKey, sizeof(DcCommonInfo), IPC_CREAT | 0777)) < 0) {
+        return FAIL;
+    } else if ((ShmDcCommonData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+        return FAIL;
+    }
+
+    if (ShmDcCommonData->RebootCount == 1) {
+        rebootCount = ShmDcCommonData->RebootCount;
+    }
+    memset(ShmDcCommonData, 0, sizeof(DcCommonInfo));
+
+    ShmDcCommonData->RebootCount = rebootCount;
+
+    return PASS;
+}
+
+#endif //0
+
+//=================================
+// LCM Page
+//=================================
+void ChangeLcmByIndex(uint8_t page_index)
+{
+    if (pSysWarning->Level != 2 ||
+            page_index == _LCM_COMPLETE || page_index == _LCM_FIX) {
+        pSysInfo->PageIndex = page_index;
+    }
+}
+
+//======================================================
+// Peripheral initial
+//======================================================
+void InitGPIO()
+{
+    /*****************0~3, 4 bank, bank x 32+ num*********************/
+    /***************************************************************/
+    /*************** GPIO 0 ***************************************/
+    /***************************************************************/
+    /* GPMC_AD8         =>  GPIO0_22 *//*ID BD1_1*/
+    system("echo 22 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio22/direction");
+    /* GPMC_AD9         =>  GPIO0_23 *//*ID BD1_2*/
+    system("echo 23 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio23/direction");
+    /* GPMC_AD10        =>  GPIO0_26 *//*IO BD1_1*/
+    system("echo 26 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio26/direction");
+    system("echo 1 > /sys/class/gpio/gpio26/value");
+    /* GPMC_AD11        =>  GPIO0_27 *//*IO BD1_2*/
+    system("echo 27 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio27/direction");
+    /* RMII1_REF_CLK        =>  GPIO0_29 *//*USB 0 OCP detection*/
+    system("echo 29 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio29/direction");
+    /*XDMA_EVENT_INTR0  =>  GPIO0_19 *//*AM_RFID_RST*/
+    system("echo 19 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio19/direction");
+    system("echo 1 > /sys/class/gpio/gpio19/value");
+    /*XDMA_EVENT_INTR1  =>  GPIO0_20 *//*AM_RFID_ICC*/
+    system("echo 20 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio20/direction");
+    /***************************************************************/
+    /*************** GPIO 1 ***************************************/
+    /***************************************************************/
+    /* GPMC_AD12    =>  GPIO1_12 *//*ID BD2_1*/
+    system("echo 44 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio44/direction");
+    /* GPMC_AD13    =>  GPIO1_13 *//*ID BD2_2*/
+    system("echo 45 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio45/direction");
+    /* GPMC_AD14    =>  GPIO1_14 *//*IO BD2_1*/
+    system("echo 46 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio46/direction");
+    system("echo 0 > /sys/class/gpio/gpio46/value");
+    /* GPMC_AD15    =>  GPIO1_15 *//*IO BD2_2*/
+    system("echo 47 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio47/direction");
+    /***************************************************************/
+    /*************** GPIO 2 ***************************************/
+    /***************************************************************/
+    /*LCD_AC_BIAS_EN    =>  GPIO2_25*//*RS-485 for module DE control*/
+    system("echo 89 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio89/direction");
+    system("echo 1 > /sys/class/gpio/gpio89/value");
+    /*LCD_HSYNC     =>  GPIO2_23*//*RS-485 for module RE control*/
+    system("echo 87 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio87/direction");
+    system("echo 0 > /sys/class/gpio/gpio87/value");
+    /*LCD_PCLK      =>  GPIO2_24*//*CCS communication board 1 proximity*/
+    system("echo 88 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio88/direction");
+    /*LCD_VSYNC     =>  GPIO2_22*//*CCS communication board 2 proximity*/
+    system("echo 86 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio86/direction");
+    /***************************************************************/
+    /*************** GPIO 3 ***************************************/
+    /***************************************************************/
+    /*MCASP0_FSX        =>  GPIO3_15*//*Emergency Stop button detect*/
+    system("echo 111 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio111/direction");
+    /*MCASP0_ACLKR  =>  GPIO3_18*//*USB1 OCP detect*/
+    system("echo 114 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio114/direction");
+    /*MCASP0_AHCLKR =>  GPIO3_17*//*Emergency IO for AM3352 and STM32F407*/
+    system("echo 113 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio113/direction");
+    /*MCASP0_ACLKX  =>  GPIO3_14*//*Ethernet PHY reset*/
+    system("echo 110 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio110/direction");
+    system("echo 0 > /sys/class/gpio/gpio110/value");
+    /* MCASP0_FSR       =>  GPIO3_19 *//*SMR Enable control_1 for Pskill_1*/
+    system("echo 115 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio115/direction");
+    system("echo 0 > /sys/class/gpio/gpio115/value");
+    /* MCASP0_AXR0  =>  GPIO3_16 *//*CSU board function OK indicator.*/
+    system("echo 112 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio112/direction");
+    system("echo 1 > /sys/class/gpio/gpio112/value");
+    /* MCASP0_AXR1  =>  GPIO3_20 *//*SMR Enable control_2 for Pskill_2*/
+    system("echo 116 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio116/direction");
+    system("echo 0 > /sys/class/gpio/gpio116/value");
+
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+    /* (C14) EMU0.gpio3[7] */  /*CP open/short feature enable/disable, pull low for default enable*/
+    system("echo 103 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio103/direction");
+    system("echo 0 > /sys/class/gpio/gpio103/value");
+    /* (B14) EMU1.gpio3[8] */  /*4G module reset, pull high to reset when entry kernel, after Application start, it should be pull low.*/
+    system("echo 104 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio104/direction");
+    system("echo 0 > /sys/class/gpio/gpio104/value");
+#endif //!defined DD360 && !defined DD360Audi
+
+    log_info("Initial GPIO OK");
+}
+
+int LoadSysConfigAndInfo(struct SysConfigData *ptr)
+{
+    int fd, wrd;
+    uint8_t *buf;
+    unsigned int ChkSum, ChkSumOrg;
+
+    if ((buf = malloc(MtdBlockSize)) == NULL) {
+        log_error("malloc buffer NG,rebooting..\r\n");
+        if (pAlarmCode != NULL) {
+            pAlarmCode->AlarmEvents.bits.CsuInitFailed = 1;
+        }
+        sleep(5);
+        system("reboot -f");
+        sleep(5);
+        system("reboot -f");
+    }
+    memset(buf, 0, MtdBlockSize);
+
+    //================================================
+    // Load configuration from mtdblock10
+    //================================================
+    fd = open("/dev/mtdblock10", O_RDWR);
+    if (fd < 0) {
+        free(buf);
+        log_error("open mtdblock10 NG,rebooting..\r\n");
+        if (pAlarmCode != NULL) {
+            pAlarmCode->AlarmEvents.bits.CsuInitFailed = 1;
+        }
+        sleep(5);
+        system("reboot -f");
+        sleep(5);
+        system("reboot -f");
+    }
+
+    wrd = read(fd, buf, MtdBlockSize);
+    close(fd);
+    if (wrd < MtdBlockSize) {
+        free(buf);
+        log_error("read SysConfigData data NG,rebooting..\r\n");
+        if (pAlarmCode != NULL) {
+            pAlarmCode->AlarmEvents.bits.CsuInitFailed = 1;
+        }
+        sleep(5);
+        system("reboot -f");
+        sleep(5);
+        system("reboot -f");
+    }
+    ChkSum = 0;
+    for (wrd = 0; wrd < MtdBlockSize - 4; wrd++) {
+        ChkSum += buf[wrd];
+    }
+    memcpy(&ChkSumOrg, buf + (0x00600000 - 4), sizeof(ChkSumOrg));
+
+    //================================================
+    // Load configuration from mtdblock11
+    //================================================
+    if (ChkSum != ChkSumOrg) {
+        log_error("Primary SysConfigData checksum NG, read backup\r\n");
+        fd = open("/dev/mtdblock11", O_RDWR);
+        if (fd < 0) {
+            free(buf);
+            log_error("open mtdblock11 (backup) NG,rebooting..\r\n");
+            if (pAlarmCode != NULL) {
+                pAlarmCode->AlarmEvents.bits.CsuInitFailed = 1;
+            }
+            sleep(5);
+            system("reboot -f");
+            sleep(5);
+            system("reboot -f");
+        }
+
+        memset(buf, 0, MtdBlockSize);
+        wrd = read(fd, buf, MtdBlockSize);
+        close(fd);
+        if (wrd < MtdBlockSize) {
+            free(buf);
+            log_error("read backup SysConfigData data NG,rebooting..\r\n");
+            if (pAlarmCode != NULL) {
+                pAlarmCode->AlarmEvents.bits.CsuInitFailed = 1;
+            }
+            sleep(5);
+            system("reboot -f");
+            sleep(5);
+            system("reboot -f");
+        }
+        ChkSum = 0;
+        for (wrd = 0; wrd < MtdBlockSize - 4; wrd++) {
+            ChkSum += buf[wrd];
+        }
+        memcpy(&ChkSumOrg, buf + (0x00600000 - 4), sizeof(ChkSumOrg));
+
+        //================================================
+        // Load configuration from mtdblock12 (Factory default)
+        //================================================
+        if (ChkSum != ChkSumOrg) {
+            log_error("backup SysConfigData checksum NG, read Factory default\r\n");
+            fd = open("/dev/mtdblock12", O_RDWR);
+            if (fd < 0) {
+                free(buf);
+                log_error("open mtdblock12 (Factory default) NG,rebooting..\r\n");
+                if (pAlarmCode != NULL) {
+                    pAlarmCode->AlarmEvents.bits.CsuInitFailed = 1;
+                }
+                sleep(5);
+                system("reboot -f");
+                sleep(5);
+                system("reboot -f");
+            }
+            memset(buf, 0, MtdBlockSize);
+            wrd = read(fd, buf, MtdBlockSize);
+            close(fd);
+            if (wrd < MtdBlockSize) {
+                free(buf);
+                log_error("read factory default  SysConfigData data NG,rebooting..\r\n");
+                if (pAlarmCode != NULL) {
+                    pAlarmCode->AlarmEvents.bits.CsuInitFailed = 1;
+                }
+                sleep(5);
+                system("reboot -f");
+                sleep(5);
+                system("reboot -f");
+            }
+            ChkSum = 0;
+            for (wrd = 0; wrd < MtdBlockSize - 4; wrd++) {
+                ChkSum += buf[wrd];
+            }
+            memcpy(&ChkSumOrg, buf + (0x00600000 - 4), sizeof(ChkSumOrg));
+            if (ChkSum != ChkSumOrg) {
+                log_error("factory default  SysConfigData checksum NG, restore factory default\r\n");
+                free(buf);
+                system("cd /root;./FactoryConfig -m");
+                system("sync");
+                sleep(5);
+                system("reboot -f");
+                sleep(5);
+                system("reboot -f");
+
+                return FAIL;
+            }
+        }
+    }
+
+    //load OK
+    memcpy((struct SysConfigData *)ptr, buf, sizeof(struct SysConfigData));
+    free(buf);
+    //log_info("Load SysConfigData OK\n");
+    return PASS;
+}
+
+#if 0
+int isRouteFail()
+{
+    int result = YES;
+    FILE *fp;
+    char buf[512];
+
+    fp = popen("route -n", "r");
+    if (fp != NULL) {
+        while (fgets(buf, sizeof(buf), fp) != NULL) {
+            if (strstr(buf, "eth0") != NULL) {
+                result = NO;
+            }
+        }
+    }
+    pclose(fp);
+
+    return result;
+}
+
+//static void eth0Down(void)
+//{
+//    char cmdbuf[256] = {0};
+//
+//    sprintf(cmdbuf, "/sbin/ifconfig eth0 down");
+//}
+
+//static void eth0Up(void)
+//{
+//    char cmdbuf[256] = {0};
+//
+//    sprintf(cmdbuf, "/sbin/ifconfig eth0 %s up", pSysConfig->Eth0Interface.EthIpAddress);
+//}
+
+int isReachableInternet()
+{
+    int result = FAIL;
+    FILE *fp;
+    char cmd[256];
+    char buf[512];
+    char tmp[512];
+
+    strcpy(cmd, "ifconfig eth0");
+    fp = popen(cmd, "r");
+
+    if (fp != NULL) {
+        while (fgets(buf, sizeof(buf), fp) != NULL) {
+            if (strstr(buf, "inet addr:") > 0) {
+                sscanf(buf, "%*s%s", tmp);
+                substr(tmp, tmp, strspn(tmp, "addr:"), strlen(buf) - strspn(tmp, "addr:"));
+
+                if (strcmp(tmp, (char *)pSysConfig->Eth0Interface.EthIpAddress) != EQUAL) {
+                    strcpy((char *) pSysConfig->Eth0Interface.EthIpAddress, tmp);
+                }
+            }
+        }
+    }
+    pclose(fp);
+
+#if defined DD360 ||defined DD360Audi || defined DD360ComBox
+    if (pAlarmCode->AlarmEvents.bits.DisconnectedFromDo == NORMAL) {
+        result = FAIL;
+    } else {
+        result = PASS;
+    }
+#else
+    memset(buf, 0x00, sizeof(buf));
+    for (int idx = 0; idx < ARRAY_SIZE(valid_Internet); idx++) {
+        sprintf(cmd, "ping -c 1 -w 3 -I eth0 %s", valid_Internet[idx]);
+        fp = popen(cmd, "r");
+        if (fp != NULL) {
+            while (fgets(buf, sizeof(buf), fp) != NULL) {
+                if (strstr(buf, "transmitted") > 0) {
+                    //sscanf(buf, "%*s%*s%*s%*s%*s%*s%s", tmp);
+
+                    if (strstr(buf, "100%") != NULL) {
+                    } else {
+                        result = PASS;
+                    }
+                    //DEBUG_INFO("%s",buf);
+                    //DEBUG_INFO("%s\n",tmp);
+                }
+            }
+        }
+        pclose(fp);
+    }
+
+#endif //defined DD360 || defined DD360Audi
+
+    return result;
+}
+
+void InitEthernet()
+{
+    char tmpbuf[256];
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+    bool ethResult = false;
+    uint8_t cnt_pingDNS_Fail = 0;
+#endif //!defined DD360 && !defined DD360Audi
+
+    system("ifconfig eth0 down");// eth0 down
+    system("ifconfig eth1 down");// eth1 down
+    sleep(2);
+
+    // /sbin/ifconfig eth0 192.168.1.10 netmask 255.255.255.0 down
+    system("echo 1 > /sys/class/gpio/gpio110/value");//reset PHY
+    sleep(2);
+    //Init Eth0 for internet
+    memset(tmpbuf, 0, 256);
+    sprintf(tmpbuf, "/sbin/ifconfig eth0 %s netmask %s up",
+            pSysConfig->Eth0Interface.EthIpAddress,
+            pSysConfig->Eth0Interface.EthSubmaskAddress);
+    //sprintf(tmpbuf,"/sbin/ifconfig eth0 192.168.100.10 netmask 255.255.255.0 up");
+    system(tmpbuf);
+
+    memset(tmpbuf, 0, 256);
+    sprintf(tmpbuf, "route add default gw %s eth0 ",
+            pSysConfig->Eth0Interface.EthGatewayAddress);
+    //sprintf(tmpbuf,"route add default gw 192.168.100.1 eth0 ");
+    system(tmpbuf);
+    //system("ifconfig lo up");
+    //  /sbin/ifconfig eth0 192.168.1.10 netmask 255.255.255.0 up
+    //Init Eth1 for administrator tool
+    memset(tmpbuf, 0, 256);
+    sprintf(tmpbuf, "/sbin/ifconfig eth1 %s netmask %s up",
+            pSysConfig->Eth1Interface.EthIpAddress,
+            pSysConfig->Eth1Interface.EthSubmaskAddress);
+    system(tmpbuf);
+
+    //Run DHCP client if enabled
+    system("killall udhcpc");
+    system("rm -rf /etc/resolv.conf");
+    system("echo nameserver 8.8.8.8 > /etc/resolv.conf");       //Google DNS server
+    system("echo nameserver 180.76.76.76 > /etc/resolv.conf");  //Baidu DNS server
+    //system("/sbin/ifconfig eth0 down;/sbin/ifconfig eth0 up");
+
+    if (pSysConfig->Eth0Interface.EthDhcpClient == 0) {
+        sprintf(tmpbuf, "/sbin/udhcpc -i eth0 -x hostname:CSU3_%s -s /root/dhcp_script/eth0.script > /dev/null &",
+                pSysConfig->SystemId);
+        system(tmpbuf);
+    }
+
+    //Upgrade system id to /etc/hostname
+    sprintf(tmpbuf, "echo %s > /etc/hostname", pSysConfig->SystemId);
+    system(tmpbuf);
+
+    pid_t pid = fork();
+    if (pid == 0) {
+        log_info("InitEthernet = %d\r\n", pid);
+        for (;;) {
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+            if (isRouteFail()) {
+                //log_info("eth0 not in route, restart eht0. \n");
+                system("/sbin/ifconfig eth0 down;/sbin/ifconfig eth0 up");
+
+                if (pSysConfig->Eth0Interface.EthDhcpClient == 0) {
+                    InitialDHCP();
+                }
+            }
+
+            if (isReachableInternet() == PASS) {
+                pSysInfo->ethInternetConn = YES;
+                cnt_pingDNS_Fail = 0;
+            } else {
+                if (++cnt_pingDNS_Fail > 3) {
+                    pSysInfo->ethInternetConn = NO;
+                }
+            }
+
+            ethResult = pSysInfo->ethInternetConn;
+
+            if (ethResult == YES) {
+                system("/sbin/ifmetric eth0 0");
+
+                if ((pSysConfig->ModelName[10] == 'W') ||
+                        (pSysConfig->ModelName[10] == 'D')) {
+                    system("/sbin/ifmetric mlan0 1");
+                }
+
+                if ((pSysConfig->ModelName[10] == 'T') ||
+                        (pSysConfig->ModelName[10] == 'D')) {
+                    system("/sbin/ifmetric ppp0 2");
+                }
+            }
+
+            if (!ethResult &&
+                    pSysConfig->AthInterface.WifiMode != _SYS_WIFI_MODE_DISABLE &&
+                    (pSysConfig->ModelName[10] == 'W' ||
+                     pSysConfig->ModelName[10] == 'D')) {
+                //ethResult = pSysConfig->AthInterface.WifiNetworkConn;
+                ethResult = pInfoCode->InfoEvents.bits.InternetDisconnectViaWiFi == YES ? NO : YES;
+
+                if (ethResult) {
+                    if ((pSysConfig->ModelName[10] == 'W') ||
+                            (pSysConfig->ModelName[10] == 'D')) {
+                        system("/sbin/ifmetric eth0 1");
+                        system("/sbin/ifmetric mlan0 0");
+                    }
+
+
+                    if ((pSysConfig->ModelName[10] == 'T') ||
+                            (pSysConfig->ModelName[10] == 'D')) {
+                        system("/sbin/ifmetric ppp0 2");
+                    }
+                }
+            }
+
+            if (!ethResult &&
+                    pSysConfig->TelecomInterface.TelcomEnabled == YES &&
+                    (pSysConfig->ModelName[10] == 'T' ||
+                     pSysConfig->ModelName[10] == 'D')) {
+                //ethResult = pSysConfig->TelecomInterface.TelcomNetworkConn;
+                ethResult = pInfoCode->InfoEvents.bits.InternetDisconnectVia4Gi == YES ? NO : YES;
+
+                if (ethResult) {
+                    if ((pSysConfig->ModelName[10] == 'W') ||
+                            (pSysConfig->ModelName[10] == 'D')) {
+                        system("/sbin/ifmetric mlan0 2");
+                    }
+
+                    if ((pSysConfig->ModelName[10] == 'T') ||
+                            (pSysConfig->ModelName[10] == 'D')) {
+                        system("/sbin/ifmetric eth0 1");
+                        system("/sbin/ifmetric ppp0 0");
+                    }
+                }
+            }
+
+            pSysInfo->InternetConn = ethResult;
+#else
+            isReachableInternet();
+#endif //!defined DD360 && !defined DD360
+
+            sleep(5);
+        }
+    }
+
+    log_info("Initial Ethernet OK\r\n");
+}
+
+int InitialRfidPort()
+{
+    int uartO2 = open(rfidPortName, O_RDWR);
+    struct termios tios;
+
+    if (uartO2 != FAIL) {
+        ioctl (uartO2, TCGETS, &tios);
+        tios.c_cflag = B19200 | CS8 | CLOCAL | CREAD;
+        tios.c_lflag = 0;
+        tios.c_iflag = 0;
+        tios.c_oflag = 0;
+        tios.c_cc[VMIN] = 0;
+        tios.c_cc[VTIME] = (uint8_t) 1;
+        tios.c_lflag = 0;
+        tcflush(uartO2, TCIFLUSH);
+        ioctl(uartO2, TCSETS, &tios);
+    }
+
+    if (uartO2 < 0) {
+        pAlarmCode->AlarmEvents.bits.RfidModuleCommFail = 1;
+    }
+
+    return uartO2;
+}
+
+void GetMacAddress()
+{
+    for (uint8_t index = 0; index < 2; index++) {
+        int fd;
+        struct ifreq ifr;
+        char tarEth[5];
+        char Mac[18];
+
+        sprintf(tarEth, "eth%d", index);
+        fd = socket(AF_INET, SOCK_DGRAM, 0);
+
+        ifr.ifr_addr.sa_family = AF_INET;
+        strncpy(ifr.ifr_name, tarEth, IFNAMSIZ - 1);
+
+        ioctl(fd, SIOCGIFHWADDR, &ifr);
+        close(fd);
+
+        sprintf(Mac, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
+                ifr.ifr_hwaddr.sa_data[0], ifr.ifr_hwaddr.sa_data[1], ifr.ifr_hwaddr.sa_data[2],
+                ifr.ifr_hwaddr.sa_data[3], ifr.ifr_hwaddr.sa_data[4], ifr.ifr_hwaddr.sa_data[5]);
+
+        if (index == 0) {
+            strcpy((char *) pSysConfig->Eth0Interface.EthMacAddress, Mac);
+        } else {
+            strcpy((char *) pSysConfig->Eth1Interface.EthMacAddress, Mac);
+        }
+    }
+}
+
+void GetFirmwareVersion()
+{
+    // Get CSU root file system version
+    sprintf((char *)pSysInfo->CsuRootFsFwRev, fwVersion);
+
+    uint8_t count = 0, chademo = 0, ccs = 0, gb = 0;
+    for (uint8_t idx = 0; idx < 3; idx++) {
+        if (pSysConfig->ModelName[7 + idx] == 'J') {
+            chademo++;
+            count++;
+        } else if (pSysConfig->ModelName[7 + idx] == 'G') {
+            gb++;
+            count++;
+        } else if (pSysConfig->ModelName[7 + idx] == 'U' ||
+                   pSysConfig->ModelName[7 + idx] == 'V' ||
+                   pSysConfig->ModelName[7 + idx] == 'E') {
+            ccs++;
+            count++;
+        }
+    }
+
+    if (count == 1) {
+        if (chademo > 0) {
+            pSysInfo->CsuRootFsFwRev[7] = '1';
+        } else if (ccs > 0) {
+            pSysInfo->CsuRootFsFwRev[7] = '2';
+        } else if (gb > 0) {
+            pSysInfo->CsuRootFsFwRev[7] = '3';
+        }
+    } else {
+        if (chademo > 0 && ccs > 0) {
+            pSysInfo->CsuRootFsFwRev[7] = '4';
+        } else if (chademo > 0 && gb > 0) {
+            pSysInfo->CsuRootFsFwRev[7] = '5';
+        } else if (ccs > 0 && gb > 0) {
+            pSysInfo->CsuRootFsFwRev[7] = '6';
+        }
+    }
+
+    // Get network option from model name
+    switch (pSysConfig->ModelName[10]) {
+    case 'B':
+    case 'U':
+        //Blue tooth
+        pSysInfo->CsuRootFsFwRev[9] = '3';
+        break;
+    case 'W':
+        // WIFI
+        pSysInfo->CsuRootFsFwRev[9] = '1';
+        break;
+    case 'T':
+        // 3G/4G
+        pSysInfo->CsuRootFsFwRev[9] = '2';
+        break;
+    case 'D': //DS60-120 add
+        pSysInfo->CsuRootFsFwRev[9] = '5';
+        break;
+    default:
+        // LAN
+        pSysInfo->CsuRootFsFwRev[9] = '0';
+        break;
+    }
+    // Get rating power from model name
+    memcpy(&pSysInfo->CsuRootFsFwRev[10], &pSysConfig->ModelName[4], 0x03);
+
+    // Get IEC or UL
+    char _buf[3] = {0};
+    memcpy(_buf, &pSysConfig->ModelName[2], 2);
+
+    if (strcmp(_buf, "YE") == EQUAL || strcmp(_buf, "YC") == EQUAL) {
+        pSysInfo->ChargerType = _CHARGER_TYPE_IEC;
+        log_info("IEC model");
+    } else if (strcmp(_buf, "WU") == EQUAL) {
+        pSysInfo->ChargerType = _CHARGER_TYPE_UL;
+        log_info("UL model");
+    }
+}
+
+//DS60-120 add
+void InitialGunIndexToUnUse()
+{
+    for (uint8_t index = 0; index < CHAdeMO_QUANTITY; index++) {
+        pSysInfo->ChademoChargingData[index].Index = NO_DEFINE;
+    }
+
+    for (uint8_t index = 0; index < CCS_QUANTITY; index++) {
+        pSysInfo->CcsChargingData[index].Index = NO_DEFINE;
+    }
+
+    for (uint8_t index = 0; index < GB_QUANTITY; index++) {
+        pSysInfo->GbChargingData[index].Index = NO_DEFINE;
+    }
+
+    for (uint8_t index = 0; index < AC_QUANTITY; index++) {
+        pSysInfo->AcChargingData[index].Index = NO_DEFINE;
+    }
+}
+
+void InitialShareMemoryInfo()
+{
+    FILE *fp;
+    char cmd[512];
+    char buf[512];
+
+    sprintf((char *)pSysConfig->TelecomInterface.TelcomApn, "Internet");
+    sprintf((char *)pSysConfig->TelecomInterface.TelcomChapPapId, " ");
+    sprintf((char *)pSysConfig->TelecomInterface.TelcomChapPapPwd, " ");
+
+    pSysConfig->TotalConnectorCount = 0;
+    pSysConfig->AcConnectorCount = 0;
+
+    pSysInfo->FactoryConfiguration = 0;
+    pSysInfo->InputVoltageR = 0;
+    pSysInfo->InputVoltageS = 0;
+    pSysInfo->InputVoltageT = 0;
+    pSysInfo->SystemFanRotaSpeed = 0;
+    pSysInfo->PsuFanRotaSpeed = 0;
+    pSysInfo->AuxPower5V = 0;
+    pSysInfo->AuxPower12V = 0;
+    pSysInfo->AuxPower24V = 0;
+    pSysInfo->AuxPower48V = 0;
+
+    sprintf((char *)pSysInfo->CsuHwRev, "REV:5.0");
+    memcpy(pSysInfo->CsuBootLoadFwRev, pSysConfig->CsuBootLoadFwRev, ARRAY_SIZE(pSysConfig->CsuBootLoadFwRev));
+
+    sprintf(cmd, "/bin/uname -r");
+    fp = popen(cmd, "r");
+    if (fp == NULL) {
+        sprintf((char *)pSysInfo->CsuKernelFwRev, "Unknown version");
+    } else {
+        while (fgets(buf, sizeof(buf), fp) != NULL) {
+            strcpy((char *)pSysInfo->CsuKernelFwRev, buf);
+        }
+    }
+
+    // 雙槍 CCS + Chademo
+    GetFirmwareVersion();
+    //sprintf((char *) pSysInfo->CsuRootFsFwRev, fwVersion);
+    sprintf((char *) pSysInfo->CsuPrimFwRev, " ");
+
+    sprintf((char *) pSysInfo->LcmHwRev, " ");
+    sprintf((char *) pSysInfo->LcmFwRev, " ");
+    sprintf((char *) pSysInfo->PsuHwRev, " ");
+    sprintf((char *) pSysInfo->PsuPrimFwRev, " ");
+    sprintf((char *) pSysInfo->PsuSecFwRev, " ");
+    sprintf((char *) pSysInfo->AuxPwrHwRev, " ");
+    sprintf((char *) pSysInfo->AuxPwrFwRev, " ");
+    sprintf((char *) pSysInfo->FanModuleHwRev, " ");
+    sprintf((char *) pSysInfo->FanModuleFwRev, " ");
+    sprintf((char *) pSysInfo->RelayModuleHwRev, " ");
+    sprintf((char *) pSysInfo->RelayModuleFwRev, " ");
+    sprintf((char *) pSysInfo->TelcomModemFwRev, " ");
+    pSysInfo->SystemAmbientTemp = 0;
+    pSysInfo->SystemCriticalTemp = 0;
+    pSysInfo->PsuAmbientTemp = 0;
+    pSysInfo->CcsConnectorTemp = 0;
+    pSysInfo->InternetConn = 0;
+    pSysInfo->OcppConnStatus = 0;
+    pSysInfo->OrderCharging = NO_DEFINE;
+
+    strcpy((char *) pSysConfig->UserId, "");
+
+    pAlarmCode->AlarmEvents.bits.RelayboardStestFail = NO;
+    pAlarmCode->AlarmEvents.bits.FanboardStestFail = NO;
+    pAlarmCode->AlarmEvents.bits.PrimaryStestFail = NO;
+    pAlarmCode->AlarmEvents.bits.LedboardStestFail = NO; //DS60-120 Add
+    pAlarmCode->AlarmEvents.bits.ChademoboardStestFail = NO;
+    pAlarmCode->AlarmEvents.bits.CCSboardStestFail = NO;
+    pAlarmCode->AlarmEvents.bits.AcContactStestFail = NO;
+    pAlarmCode->AlarmEvents.bits.PsuModuleStestFail = NO;
+    pAlarmCode->AlarmEvents.bits.PsuDipSwitchStestFail = NO; //DS60-120 Add
+    pSysConfig->QRCodeMadeMode = NO; //DS60-120 add
+
+    memset(pSysInfo->FanModuleFwRev, 0, ARRAY_SIZE(pSysInfo->FanModuleFwRev));
+    memset(pSysInfo->RelayModuleFwRev, 0, ARRAY_SIZE(pSysInfo->RelayModuleFwRev));
+    ShmPrimaryMcuData->SelfTest_Comp = NO;
+    ShmRelayModuleData->SelfTest_Comp = NO;
+    ShmFanModuleData->SelfTest_Comp = NO;
+    ShmLedModuleData->SelfTest_Comp = NO;
+#if defined DD360Audi
+    pSysInfo->SystemPage = _LCM_SELECT_GUN;
+#else
+    pSysInfo->SystemPage = _LCM_NONE;
+#endif //defined DD360Audi
+    pSysInfo->MainChargingMode = _MAIN_CHARGING_MODE_MAX;
+    pSysInfo->ReAssignedFlag = _REASSIGNED_NONE;
+    pSysInfo->CurGunSelectedByAc = NO_DEFINE;
+    pSysInfo->BootingStatus = BOOTTING; //DS60-120 add
+
+    ShmFanModuleData->TestFanSpeed = 0;
+
+    pAlarmCode->AlarmEvents.bits.ModelNameNoneMatchStestFail = NO;
+    pAlarmCode->AlarmEvents.bits.PsuNoResource = NO;
+
+    //--- DS60-120 remove -----
+    /*char EvsePower[2];
+
+    EvsePower[2] = '\0';
+    unsigned short buf_pow = 0;
+    if (strlen((char *) pSysConfig->ModelName) >= 6) {
+        strncpy(EvsePower, (char *)(pSysConfig->ModelName + 4), 2);
+        if (strcmp(EvsePower, "15") == EQUAL) {
+            buf_pow = 150;
+        } else if (strcmp(EvsePower, "30") == EQUAL) {
+            buf_pow = 30;
+        } else if (strcmp(EvsePower, "60") == EQUAL) {
+            buf_pow = 60;
+        } else if (strcmp(EvsePower, "12") == EQUAL) {
+            buf_pow = 120;
+        } else if (strcmp(EvsePower, "18") == EQUAL) {
+            buf_pow = 180;
+        } else if (strcmp(EvsePower, "36") == EQUAL) {
+            buf_pow = 360;
+        }
+
+        pSysConfig->RatingCurrent = (buf_pow / 30) * PSU_MIN_CUR;
+
+        if (pSysConfig->MaxChargingPower == 0 ||
+                pSysConfig->MaxChargingPower > buf_pow) {
+            pSysConfig->MaxChargingPower = buf_pow;
+        }
+    }
+    */
+    //--------------------------------------------------------------------------
+
+    InitialGunIndexToUnUse();//DS60-120 add
+
+    //ShmDcCommonData->CcsVersion = _CCS_VERSION_CHECK_TAG_V015S0;
+    //ShmDcCommonData->psuKeepCommunication = NO;
+    //ShmDcCommonData->acContactSwitch = NO;
+    ShmDcCommonData->ConnectErrList[0].GunErrMessage = 0;
+    ShmDcCommonData->ConnectErrList[1].GunErrMessage = 0;
+    //ShmDcCommonData->LcmFwVersion = 0;
+
+    pSysConfig->SwitchDebugFlag = NO;
+    pSysConfig->AlwaysGfdFlag = NO;
+
+    log_info("3InitialShareMemoryInfo done...\r\n");
+}
+#endif //0
+
+int Initialization()
+{
+    // 初始化卡號驗證的 Flag
+    ClearAuthorizedFlag();
+
+    // 初始化插槍驗證的 Flag
+    ClearDetectPluginFlag();
+
+    // UART 2 for Rfid
+    //rfidFd = InitialRfidPort();
+
+    int pinOut[2] = { 116, 115 };
+    for (uint8_t count = 0; count < pSysConfig->TotalConnectorCount; count++) {
+        pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(count);
+
+        pDcChargingInfo->RemoteStartFlag = NO;
+
+        if (pDcChargingInfo->Type == _Type_Chademo) {
+            gpio_set_value(pinOut[count], 0x00);
+            ShmCHAdeMOData->evse[pDcChargingInfo->type_index].SelfTest_Comp = NO;
+        } else if (pDcChargingInfo->Type == _Type_GB) {
+            gpio_set_value(pinOut[count], 0x00);
+            ShmGBTData->evse[pDcChargingInfo->type_index].SelfTest_Comp = NO;
+        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+            //if (ShmCcsData->CommProtocol == _CCS_COMM_V2GMessage_DIN70121) { //DS60-120 remove
+            if (pSysConfig->TotalConnectorCount == 1) {
+                gpio_set_value(pinOut[1], 0x01);
+            } else {
+                gpio_set_value(pinOut[count], 0x01);
+            }
+            ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].SelfTest_Comp = NO;
+            //}
+        }
+
+        strcpy((char *)ShmOCPP16Data->StatusNotification[count].ErrorCode, "NoError");
+    }
+
+    for (uint8_t count = 0; count < pSysConfig->AcConnectorCount; count++) {
+        pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(count);
+
+        pAcChargingInfo->RemoteStartFlag = NO;
+
+        if (pAcChargingInfo->Type == _Type_AC) {
+            pAcChargingInfo->SelfTest_Comp = NO;
+            strcpy((char *)ShmOCPP16Data->StatusNotification[count + pSysConfig->TotalConnectorCount].ErrorCode, "NoError");
+        }
+    }
+
+    //log_info("Initialization OK \n");
+    return PASS;
+}
+
+bool InitialSystemDefaultConfig()
+{
+    bool result = true;
+
+    LoadSysConfigAndInfo(pSysConfig);
+    InitGPIO();
+    InitEthernet();
+    GetMacAddress();
+
+//  system("echo 1 > /sys/class/gpio/gpio110/value"); //reset PHY
+//  sleep(3);
+//  system("/sbin/ifconfig eth0 192.168.1.10 netmask 255.255.255.0 down");
+//  sleep(1);
+//  system("/sbin/ifconfig eth1 192.168.0.10 netmask 255.255.255.0 up");
+
+    return result;
+}
+
+//顯示自檢錯誤原因,觸發對應的flag
+bool DisplaySelfTestFailReason()
+{
+    bool result = false;
+    uint8_t index = 0;
+
+    // RB、FB、407、EV 小板中有些板子無回應
+    if (ShmRelayModuleData->SelfTest_Comp == NO) {
+        pAlarmCode->AlarmEvents.bits.RelayboardStestFail = true;
+    }
+
+    if (ShmFanModuleData->SelfTest_Comp == NO) {
+        pAlarmCode->AlarmEvents.bits.FanboardStestFail = true;
+    }
+
+    if (ShmPrimaryMcuData->SelfTest_Comp == NO) {
+        pAlarmCode->AlarmEvents.bits.PrimaryStestFail = true;
+    }
+
+    if (ShmLedModuleData->SelfTest_Comp == NO) {
+        pAlarmCode->AlarmEvents.bits.LedboardStestFail = true;
+    }
+
+    for (index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+        pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+        if (pDcChargingInfo->Type == _Type_Chademo) {
+            if (ShmCHAdeMOData->evse[pDcChargingInfo->type_index].SelfTest_Comp == NO) {
+                pAlarmCode->AlarmEvents.bits.ChademoboardStestFail = true;
+            }
+        } else if (pDcChargingInfo->Type == _Type_GB) {
+            if (ShmGBTData->evse[pDcChargingInfo->type_index].SelfTest_Comp == NO) {
+                pAlarmCode->AlarmEvents.bits.GbtboardStestFail = true;
+            }
+        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+            if (ShmCcsData->CommProtocol == _CCS_COMM_V2GMessage_DIN70121) {
+                if (ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].SelfTest_Comp == NO) {
+                    pAlarmCode->AlarmEvents.bits.CCSboardStestFail = true;
+                }
+            }
+        }
+    }
+
+    for (index = 0; index < pSysConfig->AcConnectorCount; index++) {
+        pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(index);
+
+        // 先借 GBT 顯示
+        if (pAcChargingInfo->SelfTest_Comp == NO) {
+            pAlarmCode->AlarmEvents.bits.AcConnectorStestFail = true;
+        }
+    }
+
+    if (pSysInfo->AcContactorStatus == NO) {
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+        // AC Contact 未搭上
+        pAlarmCode->AlarmEvents.bits.AcContactStestFail = true;
+        result = true;
+#endif //!defined DD360 && !defined DD360Audi
+    }
+    //else if (pAlarmCode->AlarmEvents.bits.PsuDipSwitchStestFail == YES) { //DS60-120 add
+    //    result = true;
+    //}
+    else if (ShmPsuData->SystemAvailablePower <= 0 &&
+             ShmPsuData->SystemAvailableCurrent <= 0) {
+        // PSU 通訊問題
+        pAlarmCode->AlarmEvents.bits.PsuModuleStestFail = true;
+        result = true;
+    }
+
+    return result;
+}
+
+#if 0
+void SelfTestRun()
+{
+    bool evInitFlag = false;
+
+    StartSystemTimeoutDet(Timeout_SelftestChk);
+    pSysInfo->SelfTestSeq = _STEST_VERSION;
+
+    while (pSysInfo->SelfTestSeq != _STEST_COMPLETE //||
+            //GetTimeoutValue(pSysInfo->SystemTimeoutTimer) / uSEC_VAL <= 20 //DS60-120 add
+          ) {
+        if (pSysInfo->SelfTestSeq == _STEST_COMPLETE) {
+            return;
+        }
+
+        ChkPrimaryStatus();
+        if (pSysWarning->Level == 2 //||
+                //pAlarmCode->AlarmEvents.bits.PsuDipSwitchStestFail == YES //DS60-120 add
+           ) {
+            pSysInfo->SelfTestSeq = _STEST_FAIL;
+            return;
+        }
+
+        if (pSysConfig->TotalConnectorCount > 0) {
+            if (ShmPsuData->Work_Step == _NO_WORKING ||
+                    pSysInfo->SelfTestSeq == _STEST_FAIL) {
+                pSysInfo->SelfTestSeq = _STEST_FAIL;
+                return;
+            }
+
+            switch (pSysInfo->SelfTestSeq) {
+            case _STEST_VERSION: {
+                if ((strlen((char *)pSysInfo->RelayModuleFwRev) != 0 ||
+                        pSysInfo->RelayModuleFwRev[0] != '\0')
+                        && (ShmRelayModuleData->SelfTest_Comp != YES)
+                   ) {
+                    log_info("Relay Board FW Rev = %s", pSysInfo->RelayModuleFwRev);
+                    ShmRelayModuleData->SelfTest_Comp = YES;
+                }
+#if !defined NO_FAN_BOARD && !defined DD360ComBox
+                if ((strlen((char *)pSysInfo->FanModuleFwRev) != 0 ||
+                        pSysInfo->FanModuleFwRev[0] != '\0')
+                        && (ShmFanModuleData->SelfTest_Comp != YES)
+                   ) {
+                    log_info("Fan Board FW Rev = %s", pSysInfo->FanModuleFwRev);
+                    ShmFanModuleData->SelfTest_Comp = YES;
+                }
+#else
+                ShmFanModuleData->SelfTest_Comp = YES;
+#endif //NO_FAN_BOARD
+
+                if ((strlen((char *)ShmPrimaryMcuData->version) != 0 ||
+                        ShmPrimaryMcuData->version[0] != '\0')
+                        && (ShmPrimaryMcuData->SelfTest_Comp != YES)
+                   ) {
+                    log_info("Primary FW Rev = %s", pSysInfo->CsuPrimFwRev);
+                    ShmPrimaryMcuData->SelfTest_Comp = YES;
+                }
+#if 0 //DS60-120 remove
+                if ((strlen((char *)pSysInfo->LedModuleFwRev) != 0 ||
+                        pSysInfo->LedModuleFwRev[0] != '\0')
+                        && (ShmLedModuleData->SelfTest_Comp != YES)
+                   ) {
+                    log_info("LED Board FW Rev = %s", pSysInfo->LedModuleFwRev);
+                    ShmLedModuleData->SelfTest_Comp = YES;
+                }
+#endif //0
+
+                // EV 小板
+                if (!evInitFlag) {
+                    evInitFlag = YES;
+                    for (uint8_t index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+                        pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+                        //log_info("index = %d, charging index = %d, type = %d\r\n",
+                        //         index,
+                        //         chargingInfo[index]->type_index,
+                        //         chargingInfo[index]->Type);
+                        if (pDcChargingInfo->Type == _Type_Chademo) {
+                            if ((strlen((char *)ShmCHAdeMOData->evse[pDcChargingInfo->type_index].version) != 0 ||
+                                    ShmCHAdeMOData->evse[pDcChargingInfo->type_index].version[0] != '\0')
+                                    //&& (ShmCHAdeMOData->evse[pDcChargingInfo->type_index].SelfTest_Comp != YES)
+                               ) {
+                                log_info("CHAdeMO[%d] FW Rev = %s", pDcChargingInfo->type_index, ShmCHAdeMOData->evse[pDcChargingInfo->type_index].version);
+                                ShmCHAdeMOData->evse[pDcChargingInfo->type_index].SelfTest_Comp = YES;
+                            } else {
+                                //log_info("chademo fw lose...... %s \n", ShmCHAdeMOData->evse[pDcChargingInfo->type_index].version);
+                                evInitFlag = NO;
+                            }
+                        } else if (pDcChargingInfo->Type == _Type_GB) {
+                            if ((strlen((char *)ShmGBTData->evse[pDcChargingInfo->type_index].version) != 0 ||
+                                    ShmGBTData->evse[pDcChargingInfo->type_index].version[0] != '\0')
+                                    //&& (ShmGBTData->evse[pDcChargingInfo->type_index].SelfTest_Comp != YES)
+                               ) {
+                                log_info("GBT[%d] FW Rev = %s", pDcChargingInfo->type_index, ShmGBTData->evse[pDcChargingInfo->type_index].version);
+                                ShmGBTData->evse[pDcChargingInfo->type_index].SelfTest_Comp = YES;
+                            } else {
+                                //log_info("GBT fw lose...... %s \n", ShmCHAdeMOData->evse[pDcChargingInfo->type_index].version);
+                                evInitFlag = NO;
+                            }
+                        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                            if (ShmCcsData->CommProtocol == _CCS_COMM_V2GMessage_DIN70121) {
+                                if ((strlen((char *)ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].version) != 0 ||
+                                        ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].version[0] != '\0')
+                                        /*&&(ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].SelfTest_Comp != YES)*/
+                                   ) {
+                                    log_info("CCS[%d] FW Rev = %s",
+                                             pDcChargingInfo->type_index,
+                                             ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].version);
+                                    ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].SelfTest_Comp = YES;
+                                } else {
+                                    //log_info("CCS[%d] ccs fw lose...... %s \n",
+                                    //         chargingInfo[index]->type_index,
+                                    //         ShmCcsData->V2GMessage_DIN70121[chargingInfo[index]->type_index].version);
+                                    evInitFlag = NO;
+                                }
+                            }
+                        }
+                    }
+
+                    for (uint8_t index = 0; index < pSysConfig->AcConnectorCount; index++) {
+                        pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(index);
+
+                        if (pAcChargingInfo->Type == _Type_AC) {
+                            if ((strlen((char *)pAcChargingInfo->version) != 0 || pAcChargingInfo->version[0] != '\0')
+                                    && (pAcChargingInfo->SelfTest_Comp != YES)
+                               ) {
+                                log_info("AC connector[%d] FW Rev = %s", index, pAcChargingInfo->version);
+                                pAcChargingInfo->SelfTest_Comp = YES;
+                            } else {
+                                evInitFlag = NO;
+                            }
+                        }
+                    }
+                }
+
+                if ( ShmFanModuleData->SelfTest_Comp &&
+                        ShmRelayModuleData->SelfTest_Comp &&
+                        ShmPrimaryMcuData->SelfTest_Comp &&
+                        //ShmLedModuleData->SelfTest_Comp &&
+                        evInitFlag
+                   ) {
+                    pSysInfo->SelfTestSeq = _STEST_AC_CONTACTOR;
+                }
+            }
+            break;
+            case _STEST_AC_CONTACTOR: {
+                //ShmPsuData->Work_Step = _TEST_COMPLETE;
+                // 因為 30KW 以下沒有 Relay feedback 功能,所以暫時先直接跳過
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                if (pSysInfo->AcContactorStatus == YES) {
+                    pSysInfo->SelfTestSeq = _STEST_PSU_DETECT;
+                    log_info("AC contactor self test OK");
+                }
+#else
+                pSysInfo->SelfTestSeq = _STEST_PSU_DETECT;
+                log_info("Waiting for DO communication");
+#endif //!defined DD360 && !defined DD360Audi
+            }
+            break;
+            case _STEST_PSU_DETECT: {
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                if (ShmPsuData->Work_Step >= GET_SYS_CAP) {
+                    pSysInfo->SelfTestSeq = _STEST_PSU_CAP;
+                }
+#else
+                pSysInfo->SelfTestSeq = _STEST_PSU_CAP;
+#endif //defined DD360 && !defined DD360Audi
+            }
+            break;
+            case _STEST_PSU_CAP: {
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                // 此測試是要確認當前總輸出能力
+                // 如果沒有 PSU 模組請 bypass
+                if (ShmPsuData->Work_Step == BOOTING_COMPLETE) {
+                    sleep(1);
+                    pSysInfo->SelfTestSeq = _STEST_COMPLETE;
+                    pSysInfo->BootingStatus = BOOT_COMPLETE;
+                }
+#else
+                //check the power limit from DO
+                pSysInfo->SelfTestSeq = _STEST_COMPLETE;
+                pSysInfo->BootingStatus = BOOT_COMPLETE;
+                log_info("Successful Self Test");
+#endif //defined DD360 && !defined DD360Audi
+            }
+            break;
+            }
+        } else {
+            break;
+        }
+
+        usleep(100000);
+    }
+}
+#endif //0
+
+int SpawnTask()
+{
+    sleep(2);
+    system("/root/Module_EventLogging &");
+    system("/root/Module_PrimaryComm &");
+    system("/root/Module_EvComm &");
+    system("/root/Module_LcmControl &");
+    system("/root/Module_InternalComm &");
+    system("/root/Module_ProduceUtils &");
+
+#if defined DD360 ||defined DD360Audi || defined DD360ComBox
+    system("/root/Module_DoComm &");
+#else
+    system("/root/Module_PsuComm &");
+
+    if (strcmp((char *)pSysConfig->OcppServerURL, "") != EQUAL &&
+            strcmp((char *)pSysConfig->ChargeBoxId, "") != EQUAL) {
+        system("/root/OcppBackend &");
+    }
+
+    if (pSysConfig->ModelName[10] == 'T') {
+        system("/root/Module_4g &");
+    }
+
+    if (pSysConfig->ModelName[10] == 'W') {
+        system("/root/Module_Wifi &");
+    }
+
+    if (pSysConfig->ModelName[10] == 'D') {
+        system("/root/Module_4g &");
+        system("/root/Module_Wifi &");
+    }
+#endif //defined DD360 || defined DD360Audi
+
+    return PASS;
+}
+
+int StoreUsrConfigData(struct SysConfigData *UsrData)
+{
+    int result = PASS;
+    int fd, wrd;
+    unsigned int i, Chk;
+    uint8_t *ptr, *BufTmp;
+
+    Chk = 0;
+    ptr = (uint8_t *)UsrData;
+    if ((BufTmp = malloc(MtdBlockSize)) != NULL) {
+        memset(BufTmp, 0, MtdBlockSize);
+        memcpy(BufTmp, ptr, sizeof(struct SysConfigData));
+        for (i = 0; i < MtdBlockSize - 4; i++) {
+            Chk += *(ptr + i);
+        }
+
+        memcpy(BufTmp + MtdBlockSize - 4, &Chk, 4);
+        fd = open("/dev/mtdblock10", O_RDWR);
+        if (fd > 0) {
+            wrd = write(fd, BufTmp, MtdBlockSize);
+            close(fd);
+            if (wrd >= MtdBlockSize) {
+                fd = open("/dev/mtdblock11", O_RDWR);
+                if (fd > 0) {
+                    wrd = write(fd, BufTmp, MtdBlockSize);
+                    close(fd);
+                    if (wrd < MtdBlockSize) {
+                        log_error("write /dev/mtdblock11(backup) NG\r\n");
+                        result = FAIL;
+                    }
+                } else {
+                    log_error("open /dev/mtdblock11(backup) NG\r\n");
+                    result = FAIL;
+                }
+            } else {
+                log_error("write /dev/mtdblock10 NG\r\n");
+                result = FAIL;
+            }
+
+        } else {
+            log_error("open /dev/mtdblock10 NG\r\n");
+            result = FAIL;
+        }
+    } else {
+        log_error("alloc BlockSize NG\r\n");
+        result = FAIL;
+    }
+
+    if (BufTmp != NULL) {
+        free(BufTmp);
+    }
+
+    return result;
+}
+
+//===============================================
+// Common Detect Chk - Stop Charging ?
+//===============================================
+int isEvBoardStopChargeFlag(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    //printf("StopChargeFlag = %d\r\n", chargingInfo[gunIndex]->StopChargeFlag);
+    return pDcChargingInfo->StopChargeFlag;
+}
+
+bool isEvBoardNormalStopChargeFlag(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    return pDcChargingInfo->NormalStopChargeFlag;
+}
+
+//===============================================
+// 掃描插槍狀況
+//===============================================
+void ClearDetectPluginFlag()
+{
+    pSysInfo->WaitForPlugit = NO;
+
+    //DS60-120 add
+    for (uint8_t gun_index = 0; gun_index < pSysConfig->TotalConnectorCount; gun_index++) {
+        pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun_index);
+
+        if (pDcChargingInfo->RemoteStartFlag == YES) {
+            pDcChargingInfo->RemoteStartFlag = NO;
+        }
+    }
+
+    if (pSysInfo->OrderCharging != NO_DEFINE) {
+        pSysInfo->OrderCharging = NO_DEFINE;
+    }
+}
+
+void DetectPluginStart()
+{
+    pSysInfo->WaitForPlugit = YES;
+}
+
+bool isDetectPlugin()
+{
+    if (pSysInfo->WaitForPlugit == YES) {
+        return YES;
+    }
+
+    return NO;
+}
+
+//===============================================
+// Common Detect Chk - Chademo
+//===============================================
+bool isEvGunLocked_chademo(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    return (DetectBitValue(pDcChargingInfo->GunLocked , 0) == 0) ? NO : YES;
+}
+
+bool isEvContactorWelding_chademo(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    return DetectBitValue(ShmCHAdeMOData->ev[pDcChargingInfo->type_index].EvDetection, 3);
+}
+
+bool isEvStopReq_chademo(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    return DetectBitValue(ShmCHAdeMOData->ev[pDcChargingInfo->type_index].EvDetection, 4);
+}
+
+bool isEvStopCharging_chademo(uint8_t gunIndex)
+{
+    if (isEvGunLocked_chademo(gunIndex) == NO) {
+        // 無鎖槍 = 停止
+        log_info("gun locked none (%d) \n", gunIndex);
+        return YES;
+    }
+
+    return NO;
+}
+
+uint8_t isPrechargeStatus_chademo(uint8_t gunIndex)
+{
+    uint8_t result = 0x00;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    result = ShmCHAdeMOData->ev[pDcChargingInfo->type_index].PresentMsgFlowStatus;
+
+    return result;
+}
+//===============================================
+// Common Detect Chk - GB
+//===============================================
+bool isEvGunLocked_gb(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    return (DetectBitValue(pDcChargingInfo->GunLocked , 0) == 0) ? NO : YES;
+}
+
+bool isEvStopCharging_gb(uint8_t gunIndex)
+{
+    if (isEvGunLocked_gb(gunIndex) == NO) {
+        // 無鎖槍 = 停止
+        log_info("gun locked none. \n");
+        return YES;
+    }
+
+    return NO;
+}
+
+uint8_t isPrechargeStatus_gb(uint8_t gunIndex)
+{
+    uint8_t result = 0x00;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    result = ShmGBTData->ev[pDcChargingInfo->type_index].PresentMsgFlowStatus;
+
+    return result;
+}
+
+//===============================================
+// Common Detect Chk - CCS
+//===============================================
+bool isEvGunLocked_ccs(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    return (DetectBitValue(pDcChargingInfo->GunLocked , 0) == 0) ? NO : YES;
+}
+
+uint8_t isPrechargeStatus_ccs(uint8_t gunIndex)
+{
+    uint8_t result = 0x00;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (ShmCcsData->CommProtocol == _CCS_COMM_V2GMessage_DIN70121) {
+        result = ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].PresentMsgFlowStatus;
+    }
+
+    return result;
+}
+
+bool isEvStopCharging_ccs(uint8_t gunIndex)
+{
+    if (isEvGunLocked_ccs(gunIndex) == NO) {
+        // 無鎖槍 = 停止
+        log_info("gun locked none. \n");
+        return YES;
+    }
+
+    return NO;
+}
+
+//===============================================
+// Callback
+//===============================================
+void DisplayChargingInfo()
+{
+    log_info("*********** DisplayChargingInfo *********** \n");
+    for (uint8_t i = 0; i < pSysConfig->TotalConnectorCount; i++) {
+        pAcChargingInfo =  (struct ChargingInfoData *)GetAcChargingInfoData(i);
+
+        if (pAcChargingInfo->SystemStatus != S_IDLE &&
+                pAcChargingInfo->SystemStatus != S_RESERVATION) {
+            ChangeGunSelectByIndex(i);
+            return;
+        }
+    }
+
+    pAcChargingInfo =  (struct ChargingInfoData *)GetAcChargingInfoData(0);
+
+    if (pSysConfig->AcConnectorCount > 0 &&
+            pSysInfo->CurGunSelectedByAc == NO_DEFINE &&
+            pAcChargingInfo->SystemStatus >= S_PREPARNING &&
+            pAcChargingInfo->SystemStatus <= S_COMPLETE) {
+        pSysInfo->CurGunSelectedByAc = DEFAULT_AC_INDEX;
+    }
+
+    usleep(50000);
+#if defined DD360Audi
+    pSysInfo->SystemPage = _LCM_SELECT_GUN;
+#else
+    pSysInfo->SystemPage = _LCM_NONE;
+#endif //defined DD360Audi
+}
+
+void _AutoReturnTimeout()
+{
+    log_info("*********** _AutoReturnTimeout %d*********** \n", pSysInfo->PageIndex);
+    if (pSysInfo->PageIndex == _LCM_WAIT_FOR_PLUG) {
+        ClearDetectPluginFlag();
+    } else if (pSysInfo->PageIndex == _LCM_AUTHORIZ_COMP) {
+        DetectPluginStart();
+    }
+    usleep(50000);
+#if defined DD360Audi
+    pSysInfo->SystemPage = _LCM_SELECT_GUN;
+#else
+    pSysInfo->SystemPage = _LCM_NONE;
+#endif //defined DD360Audi
+}
+
+void _SelfTestTimeout()
+{
+    if (pSysInfo->BootingStatus != BOOT_COMPLETE) {
+        for (uint8_t gun_index = 0; gun_index < pSysConfig->TotalConnectorCount; gun_index++) {
+            setChargerMode(gun_index, MODE_ALARM);
+        }
+    }
+    ShmPsuData->Work_Step = _NO_WORKING;
+    pSysInfo->SelfTestSeq = _STEST_FAIL;
+    log_info("Self test timeout. \n");
+}
+
+void _AuthorizedTimeout()
+{
+    if (IsAuthorizingMode()) {
+        log_info("*********** _AuthorizedTimeout *********** \n");
+        //isCardScan = false;
+        SetIsCardScan(false);
+
+        //gAudiCustInfo->PricesInfo[pSysInfo->CurGunSelected].Balance = 0.0; //Jerry add
+        pSysInfo->SystemPage = _LCM_AUTHORIZ_FAIL;
+        //ChangeLcmByIndex(_LCM_AUTHORIZ_FAIL);
+        strcpy((char *)pSysConfig->UserId, "");
+        ClearAuthorizedFlag();
+    }
+}
+
+void _DetectPlugInTimeout()
+{
+    log_info("*********** _DetectPlugInTimeout *********** \n");
+    strcpy((char *)pSysConfig->UserId, "");
+    ClearDetectPluginFlag();
+    //usleep(50000);
+    sleep(1); //Jerry add
+#if defined DD360Audi
+    pSysInfo->SystemPage = _LCM_SELECT_GUN;
+#else
+    pSysInfo->SystemPage = _LCM_NONE;
+#endif //defined DD360Audi
+}
+
+void _DetectEvChargingEnableTimeout(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (pDcChargingInfo->Type == _Type_Chademo) {
+        if (!isEvGunLocked_chademo(gunIndex)) {
+            log_info("*********** _DetectEvChargingEnableTimeout (chademo) ***********\n");
+        }
+    } else if (pDcChargingInfo->Type == _Type_GB) {
+        if (!isEvGunLocked_ccs(gunIndex)) {
+            log_info("*********** _DetectEvChargingEnableTimeout (gb) ***********\n");
+        }
+    } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+        if (!isEvGunLocked_ccs(gunIndex)) {
+            log_info("*********** _DetectEvChargingEnableTimeout (ccs) ***********\n");
+        }
+    }
+    ChargingTerminalProcess(gunIndex);
+    _AutoReturnTimeout();
+}
+
+void _DetectEvseChargingEnableTimeout(uint8_t gunIndex)
+{
+    log_info("*********** _DetectEvseChargingEnableTimeout (GFD timeout) ***********\n");
+    //if (chargingInfo[gunIndex]->GroundFaultStatus != GFD_PASS)
+    {
+        setChargerMode(gunIndex, MODE_IDLE);
+        _AutoReturnTimeout();
+    }
+}
+
+void _PrepareTimeout(uint8_t gunIndex)
+{
+    log_info("*********** _PrepareTimeout ***********\n");
+    setChargerMode(gunIndex, MODE_IDLE);
+    pAlarmCode->AlarmEvents.bits.PsuNoResource = YES;
+    _AutoReturnTimeout();
+}
+
+void _CcsPrechargeTimeout(uint8_t gunIndex)
+{
+    log_info("*********** _CcsPrechargeTimeout ***********\n");
+    setChargerMode(gunIndex, MODE_IDLE);
+}
+
+//===============================================
+// 取得卡號與卡號驗證
+//===============================================
+#if 0
+bool canStartCharging()
+{
+    char buf2[16] = "";
+    memset(buf2, 0, ARRAY_SIZE(buf2));
+
+    for (uint8_t index = 0; index < strlen((char *)ShmOCPP16Data->Authorize.ResponseIdTagInfo.Status); index++) {
+        sprintf(buf2 + (index - 1) * 2, "%02X", ShmOCPP16Data->Authorize.ResponseIdTagInfo.Status[index]);
+    }
+    sprintf(buf2, "%s", ShmOCPP16Data->Authorize.ResponseIdTagInfo.Status);
+
+    // 因為無法得知實際的長度,所以只能用搜尋的方式
+    if (strcmp(buf2, "Accepted") == EQUAL) {
+        return true;
+    } else {
+
+    }
+
+    return false;
+}
+#endif //0
+
+void AuthorizingStart()
+{
+    ShmOCPP16Data->SpMsg.bits.AuthorizeReq = YES;
+    pSysInfo->AuthorizeFlag = YES;
+}
+
+void ClearAuthorizedFlag()
+{
+    ShmOCPP16Data->SpMsg.bits.AuthorizeConf = NO;
+    pSysInfo->AuthorizeFlag = NO;
+}
+
+bool isAuthorizedComplete()
+{
+    if (pSysInfo->AuthorizeFlag == YES) {
+        return false;
+    }
+    return true;
+}
+
+bool IsAuthorizingMode()
+{
+    if (pSysInfo->AuthorizeFlag == NO) {
+        return false;
+    }
+
+    return true;
+}
+
+//===============================================
+// 紀錄 Alarm Code
+//===============================================
+void ResetChargerAlarmCode(uint8_t gunIndex, char *code)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (strcmp(code, "012229") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaConnectOTP = NO; }
+    else if (strcmp(code, "012230") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSConnectOTP = NO; }
+    else if (strcmp(code, "012231") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTConnectOTP = NO; }
+    else if (strcmp(code, "011011") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaRelayWeldingFault = NO; }
+    else if (strcmp(code, "011013") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSRelayWeldingFault = NO; }
+    else if (strcmp(code, "011015") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTRelayWeldingFault = NO; }
+    else if (strcmp(code, "011012") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaRelayDrivingFault = NO; }
+    else if (strcmp(code, "011014") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSRelayDrivingFault = NO; }
+    else if (strcmp(code, "011016") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTRelayDrivingFault = NO; }
+    else if (strcmp(code, "011018") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaConnectTempSensorFail = NO; }
+    else if (strcmp(code, "011019") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSConnectTempSensorFail = NO; }
+    else if (strcmp(code, "011020") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTConnectTempSensorFail = NO; }
+
+    if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "", 6) != EQUAL) {
+        if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012229", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012230", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012231", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "011011", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "011013", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "011015", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "011012", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "011014", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "011016", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "011018", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "011019", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "011020", 6) == EQUAL) {
+            strncpy((char *)pDcChargingInfo->ConnectorAlarmCode, "", 6);
+        }
+    }
+}
+
+void RecordAlarmCode(uint8_t gunIndex, char *code)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "", 6) == EQUAL) {
+        memcpy(pDcChargingInfo->ConnectorAlarmCode, code, 6);
+    }
+
+    //if (strcmp(code, "012234") == EQUAL) { pAlarmCode->AlarmEvents.bits.ChademoGfdTrip = YES; }
+    //if (strcmp(code, "012235") == EQUAL) { pAlarmCode->AlarmEvents.bits.CcsGfdTrip = YES; }
+    //if (strcmp(code, "012236") == EQUAL) { pAlarmCode->AlarmEvents.bits.GbGfdTrip = YES; }
+    //if (strcmp(code, "012288") == EQUAL) { pAlarmCode->AlarmEvents.bits.CcsOutputUVPFail = YES; }
+    //if (strcmp(code, "012289") == EQUAL) { pAlarmCode->AlarmEvents.bits.ChademoOutputUVPFail = YES; }
+    //if (strcmp(code, "012290") == EQUAL) { pAlarmCode->AlarmEvents.bits.GbtOutputUVPFail = YES; }
+
+    if (strcmp(code, "012234") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaGfdTrip = YES; }
+    else if (strcmp(code, "012235") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSGfdTrip = YES; }
+    else if (strcmp(code, "012236") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTGfdTrip = YES; }
+    else if (strcmp(code, "012288") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSUvpFail = YES; }
+    else if (strcmp(code, "012289") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaUvpFail = YES; }
+    else if (strcmp(code, "012290") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTUvpFail = YES; }
+
+    else if (strcmp(code, "012229") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaConnectOTP = YES; }
+    else if (strcmp(code, "012230") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSConnectOTP = YES; }
+    else if (strcmp(code, "012231") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTConnectOTP = YES; }
+    else if (strcmp(code, "012296") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaGfdWarning = YES; }
+    else if (strcmp(code, "012297") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSGfdWarning = YES; }
+    else if (strcmp(code, "012298") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTGfdWarning = YES; }
+    else if (strcmp(code, "011011") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaRelayWeldingFault = YES; }
+    else if (strcmp(code, "011013") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSRelayWeldingFault = YES; }
+    else if (strcmp(code, "011015") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTRelayWeldingFault = YES; }
+    else if (strcmp(code, "011012") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaRelayDrivingFault = YES; }
+    else if (strcmp(code, "011014") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSRelayDrivingFault = YES; }
+    else if (strcmp(code, "011016") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTRelayDrivingFault = YES; }
+    else if (strcmp(code, "011018") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaConnectTempSensorFail = YES; }
+    else if (strcmp(code, "011019") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSConnectTempSensorFail = YES; }
+    else if (strcmp(code, "011020") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTConnectTempSensorFail = YES; }
+}
+
+void RecordWarningCode(uint8_t gunIndex, char *code)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    memcpy(pDcChargingInfo->ConnectorWarningCode, code, 6);
+
+    if (strcmp(code, "012296") == EQUAL) { pAlarmCode->AlarmEvents.bits.ChademoGroundWarning = YES; }
+    if (strcmp(code, "012297") == EQUAL) { pAlarmCode->AlarmEvents.bits.CcsGroundfaultWarning = YES; }
+    if (strcmp(code, "012298") == EQUAL) { pAlarmCode->AlarmEvents.bits.GbGroundfaultWarning = YES; }
+}
+
+void ReleaseAlarmCode(uint8_t gunIndex)
+{
+#if 0
+    bool isCleanCheck = false;
+    char code[7];
+
+    if (chargingInfo[gunIndex]->Type == _Type_Chademo) {
+        if (strncmp((char *)chargingInfo[gunIndex]->ConnectorAlarmCode, "012234", 6) == EQUAL &&
+                pAlarmCode->AlarmEvents.bits.ChademoGfdTrip == YES) {
+            memcpy(code, "012234", 6);
+            memcpy(chargingInfo[gunIndex]->ConnectorAlarmCode, "", 6);
+            isCleanCheck = true;
+        } else if (strncmp((char *)chargingInfo[gunIndex]->ConnectorAlarmCode, "012289", 6) == EQUAL &&
+                   pAlarmCode->AlarmEvents.bits.ChademoOutputUVPFail == YES) {
+            memcpy(code, "012289", 6);
+            memcpy(chargingInfo[gunIndex]->ConnectorAlarmCode, "", 6);
+            isCleanCheck = true;
+        } else if (pAlarmCode->AlarmEvents.bits.ChademoGroundWarning == YES) {
+            ReleaseWarningCodeByString(gunIndex, "012296");
+        } else if (pAlarmCode->AlarmEvents.bits.SystemChademoOutputOVP == YES) {
+            memcpy(code, "012217", 6);
+            memcpy(chargingInfo[gunIndex]->ConnectorAlarmCode, "", 6);
+            isCleanCheck = true;
+        }
+    } else if (chargingInfo[gunIndex]->Type == _Type_GB) {
+        if (strncmp((char *)chargingInfo[gunIndex]->ConnectorAlarmCode, "012236", 6) == EQUAL &&
+                pAlarmCode->AlarmEvents.bits.GbGfdTrip == YES) {
+            memcpy(code, "012236", 6);
+            memcpy(chargingInfo[gunIndex]->ConnectorAlarmCode, "", 6);
+            isCleanCheck = true;
+        } else if (strncmp((char *)chargingInfo[gunIndex]->ConnectorAlarmCode, "012290", 6) == EQUAL &&
+                   pAlarmCode->AlarmEvents.bits.GbtOutputUVPFail == YES) {
+            memcpy(code, "012290", 6);
+            memcpy(chargingInfo[gunIndex]->ConnectorAlarmCode, "", 6);
+            isCleanCheck = true;
+        } else if (pAlarmCode->AlarmEvents.bits.GbGroundfaultWarning == YES) {
+            ReleaseWarningCodeByString(gunIndex, "012298");
+        } else if (pAlarmCode->AlarmEvents.bits.SystemGbOutputOVP == YES) {
+            memcpy(code, "012221", 6);
+            memcpy(chargingInfo[gunIndex]->ConnectorAlarmCode, "", 6);
+            isCleanCheck = true;
+        }
+    } else if (chargingInfo[gunIndex]->Type == _Type_CCS_2) {
+        if (strncmp((char *)chargingInfo[gunIndex]->ConnectorAlarmCode, "012235", 6) == EQUAL &&
+                pAlarmCode->AlarmEvents.bits.CcsGfdTrip == YES) {
+            memcpy(code, "012235", 6);
+            memcpy(chargingInfo[gunIndex]->ConnectorAlarmCode, "", 6);
+            isCleanCheck = true;
+        } else if (strncmp((char *)chargingInfo[gunIndex]->ConnectorAlarmCode, "012288", 6) == EQUAL &&
+                   pAlarmCode->AlarmEvents.bits.CcsOutputUVPFail == YES) {
+            memcpy(code, "012288", 6);
+            memcpy(chargingInfo[gunIndex]->ConnectorAlarmCode, "", 6);
+            isCleanCheck = true;
+        } else if (pAlarmCode->AlarmEvents.bits.CcsGroundfaultWarning == YES) {
+            ReleaseWarningCodeByString(gunIndex, "012297");
+        } else if (pAlarmCode->AlarmEvents.bits.SystemCcsOutputOVP == YES) {
+            memcpy(code, "012219", 6);
+            memcpy(chargingInfo[gunIndex]->ConnectorAlarmCode, "", 6);
+            isCleanCheck = true;
+        }
+    }
+
+    if (isCleanCheck) {
+        for (uint8_t index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+            if (index != gunIndex || pSysConfig->TotalConnectorCount == 1) {
+                if (strncmp((char *)chargingInfo[index]->ConnectorAlarmCode, code, 6) != EQUAL) {
+                    if (strncmp(code, "012234", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.ChademoGfdTrip = NO; }
+                    if (strncmp(code, "012289", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.ChademoOutputUVPFail = NO; }
+                    if (strncmp(code, "012217", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.SystemChademoOutputOVP = NO; }
+
+                    if (strncmp(code, "012236", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.GbGfdTrip = NO; }
+                    if (strncmp(code, "012290", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.GbtOutputUVPFail = NO; }
+                    if (strncmp(code, "012221", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.SystemGbOutputOVP = NO; }
+
+                    if (strncmp(code, "012235", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.CcsGfdTrip = NO; }
+                    if (strncmp(code, "012288", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.CcsOutputUVPFail = NO; }
+                    if (strncmp(code, "012219", 6) == EQUAL) {pAlarmCode->AlarmEvents.bits.SystemCcsOutputOVP = NO;}
+                }
+            }
+        }
+    }
+#endif //0
+
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    // 回 idle 後主要清除  GFD Trip、UVP、OVP、GFD Warning
+    if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "", 6) != EQUAL) {
+        if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012251", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012252", 6) == EQUAL) {
+            memcpy(pDcChargingInfo->ConnectorAlarmCode, "", 6);
+        }
+    }
+
+    if (pDcChargingInfo->Type == _Type_Chademo) {
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaGfdTrip = NO;
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaUvpFail = NO;
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaConnectOVP = NO;
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaGfdWarning = NO;
+
+        if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "", 6) != EQUAL) {
+            if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012234", 6) == EQUAL ||
+                    strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012289", 6) == EQUAL ||
+                    strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012217", 6) == EQUAL ||
+                    strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012296", 6) == EQUAL) {
+                memcpy(pDcChargingInfo->ConnectorAlarmCode, "", 6);
+            }
+        }
+    } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSGfdTrip = NO;
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSUvpFail = NO;
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSConnectOVP = NO;
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSGfdWarning = NO;
+
+        if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "", 6) != EQUAL) {
+            if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012235", 6) == EQUAL ||
+                    strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012288", 6) == EQUAL ||
+                    strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012219", 6) == EQUAL ||
+                    strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012297", 6) == EQUAL) {
+                memcpy(pDcChargingInfo->ConnectorAlarmCode, "", 6);
+            }
+        }
+    } else if (pDcChargingInfo->Type == _Type_GB) {
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTGfdTrip = NO;
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTUvpFail = NO;
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTConnectOVP = NO;
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTGfdWarning = NO;
+
+        if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "", 6) != EQUAL) {
+            if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012236", 6) == EQUAL ||
+                    strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012290", 6) == EQUAL ||
+                    strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012221", 6) == EQUAL ||
+                    strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012298", 6) == EQUAL) {
+                memcpy(pDcChargingInfo->ConnectorAlarmCode, "", 6);
+            }
+        }
+    }
+
+    if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012251", 6) == EQUAL ||
+            strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012252", 6) == EQUAL ||
+            strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012238", 6) == EQUAL ||
+            strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012304", 6) == EQUAL
+       ) {
+        memset(pDcChargingInfo->ConnectorAlarmCode, 0, sizeof(pDcChargingInfo->ConnectorAlarmCode));
+    }
+}
+
+void ReleaseWarningCodeByString(uint8_t gunIndex, char *code)
+{
+    bool isCleanCheck = false;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (strncmp((char *)pDcChargingInfo->ConnectorWarningCode, code, 6) == EQUAL &&
+            pAlarmCode->AlarmEvents.bits.ChademoGroundWarning == YES) {
+        memcpy(pDcChargingInfo->ConnectorWarningCode, "", 6);
+        isCleanCheck = true;
+    } else if (strncmp((char *)pDcChargingInfo->ConnectorWarningCode, code, 6) == EQUAL &&
+               pAlarmCode->AlarmEvents.bits.CcsGroundfaultWarning == YES) {
+        memcpy(pDcChargingInfo->ConnectorWarningCode, "", 6);
+        isCleanCheck = true;
+    } else if (strncmp((char *)pDcChargingInfo->ConnectorWarningCode, code, 6) == EQUAL &&
+               pAlarmCode->AlarmEvents.bits.GbGroundfaultWarning == YES) {
+        memcpy(pDcChargingInfo->ConnectorWarningCode, "", 6);
+        isCleanCheck = true;
+    }
+
+    if (isCleanCheck) {
+        for (uint8_t index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+            if (index != gunIndex || pSysConfig->TotalConnectorCount == 1) {
+                if (strncmp((char *)pDcChargingInfo->ConnectorWarningCode, code, 6) != EQUAL) {
+                    if (strncmp(code, "012296", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.ChademoGroundWarning = NO; }
+                    if (strncmp(code, "012297", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.CcsGroundfaultWarning = NO; }
+                    if (strncmp(code, "012298", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.GbGroundfaultWarning = NO; }
+                }
+            }
+        }
+    }
+}
+//===============================================
+// EmergencyStop and Charging Stop
+//===============================================
+void ChargingTerminalProcess(uint8_t gunIndex)
+{
+    setChargerMode(gunIndex, MODE_TERMINATING);
+}
+
+void ChargingAlarmProcess(uint8_t gunIndex)
+{
+    setChargerMode(gunIndex, MODE_ALARM);
+}
+
+void AcChargingTerminalProcess(void)
+{
+    pAcChargingInfo =  (struct ChargingInfoData *)GetAcChargingInfoData(0);
+
+    pAcChargingInfo->SystemStatus = MODE_TERMINATING;
+}
+
+void StopChargingProcessByString(uint8_t level)
+{
+    if (level > pSysWarning->Level) {
+        pSysWarning->Level = level;
+    }
+}
+
+void ReleaseChargingProcessByString(uint8_t level)
+{
+    if (level >= pSysWarning->Level) {
+        pSysWarning->Level = 0;
+    }
+}
+
+// 一般錯誤停止充電處理函式
+void BoardErrOccurByString(uint8_t index, char *code)
+{
+    uint8_t level = 1;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+    if ((pDcChargingInfo->SystemStatus > S_IDLE && pDcChargingInfo->SystemStatus < S_TERMINATING) ||
+            (pDcChargingInfo->SystemStatus >= S_CCS_PRECHARGE_ST0 && pDcChargingInfo->SystemStatus <= S_CCS_PRECHARGE_ST1)) {
+        if (strncmp(code, "023730", 6) == EQUAL && pInfoCode->InfoEvents.bits.ChademoChargerGetEmergencyStop == NO) {
+            pInfoCode->InfoEvents.bits.ChademoChargerGetEmergencyStop = YES;
+        }
+        ChargingTerminalProcess(index);
+    }
+
+    StopChargingProcessByString(level);
+}
+
+void ReleaseBoardErrOccurByString(uint8_t index, char *code)
+{
+    bool isTrigger = false;
+    uint8_t level = 1;
+
+    if (strncmp(code, "023730", 6) == 0 && pInfoCode->InfoEvents.bits.ChademoChargerGetEmergencyStop == YES) {
+        isTrigger = true;
+        pInfoCode->InfoEvents.bits.ChademoChargerGetEmergencyStop = NO;
+    }
+
+    if (isTrigger) {
+        ReleaseChargingProcessByString(level);
+    }
+}
+
+// 急停狀況的停止充電處理函式
+void EmcOccureByString(char *code)
+{
+    uint8_t level = 2;
+    // 嚴重的急停有以下幾種 : EMC 按鈕、Mainbreak、Dooropen
+    // 其錯誤等級為 2
+
+#if defined DD360 ||defined DD360Audi || defined DD360ComBox
+    //DS60-120 remove
+    if (strncmp(code, "012251", 6) == EQUAL ||
+            strncmp(code, "012252", 6) == EQUAL ||
+            strncmp(code, "012238", 6) == EQUAL ||
+            strncmp(code, "042251", 6) == EQUAL ||
+            strncmp(code, "042252", 6) == EQUAL ||
+            strncmp(code, "012304", 6) == EQUAL ||
+            strncmp(code, "042200", 6) == EQUAL ||
+            strncmp(code, "042201", 6) == EQUAL ||
+            strncmp(code, "042202", 6) == EQUAL ||
+            strncmp(code, "042267", 6) == EQUAL)
+#endif //defined DD360 || defined DD360Audi
+    {
+        for (uint8_t gun = 0; gun < pSysConfig->TotalConnectorCount; gun++) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun);
+
+            //strncpy((char *)ShmOCPP16Data->StatusNotification[gun].VendorErrorCode, code, 6);
+
+            if ((pDcChargingInfo->SystemStatus > S_IDLE &&
+                    pDcChargingInfo->SystemStatus < S_TERMINATING) ||
+                    (pDcChargingInfo->SystemStatus >= S_CCS_PRECHARGE_ST0 &&
+                     pDcChargingInfo->SystemStatus <= S_CCS_PRECHARGE_ST1)) {
+                //ChargingTerminalProcess(gun);
+                ChargingAlarmProcess(gun);
+            }
+        }
+#if defined DD360 ||defined DD360Audi || defined DD360ComBox
+        StopChargingProcessByString(level);
+        InformOcppErrOccur(4);
+#endif //defined DD360 || defined DD360Audi
+    }
+}
+
+void ReleaseEmsOccureByString(uint8_t index, char *code)
+{
+    bool isTrigger = false;
+    uint8_t level = 2;
+
+    if (strncmp(code, "042251", 6) == 0 ) {
+        isTrigger = true;
+    } else if (strncmp(code, "012251", 6) == 0 &&
+               pAlarmCode->AlarmEvents.bits.EmergencyStopTrip == YES) {
+        isTrigger = true;
+        pAlarmCode->AlarmEvents.bits.EmergencyStopTrip = NO;
+    } else if (strncmp(code, "012252", 6) == 0 &&
+               pAlarmCode->AlarmEvents.bits.DoorOpen == YES) {
+        isTrigger = true;
+        pAlarmCode->AlarmEvents.bits.DoorOpen = NO;
+    } else if (strncmp(code, "012237", 6) == 0 &&
+               pAlarmCode->AlarmEvents.bits.SpdTrip == YES) {
+        isTrigger = true;
+        pAlarmCode->AlarmEvents.bits.SpdTrip = NO;
+    } else if (strncmp(code, "012238", 6) == 0 &&
+               pAlarmCode->AlarmEvents.bits.MainPowerBreakerTrip == YES) {
+        isTrigger = true;
+        pAlarmCode->AlarmEvents.bits.MainPowerBreakerTrip = NO;
+    }
+
+    if (isTrigger) {
+        ReleaseChargingProcessByString(level);
+        InformOcppErrOccur(6);
+    }
+}
+
+#if 0
+//===============================================
+// 確認硬體 (按鈕) 狀態
+//===============================================
+bool leftBtnPush = false;
+bool rightBtnPush = false;
+
+void ChkPrimaryStatus()
+{
+    uint8_t Rtn;
+
+    if (pSysWarning->WarningCount > 0) {
+        Rtn = 0;
+        for (uint8_t i = 0; i < pSysWarning->WarningCount; i++) {
+            if (memcmp(&pSysWarning->WarningCode[i][0], "042251", 6) == 0) {
+                EmcOccureByString("042251");
+                Rtn = 1;
+            } else if (memcmp(&pSysWarning->WarningCode[i][0], "042252", 6) == 0) {
+                EmcOccureByString("042252");
+                Rtn = 1;
+            } else if (memcmp(&pSysWarning->WarningCode[i][0], "042200", 6) == 0) {
+                EmcOccureByString("042200");
+                Rtn = 1;
+            } else if (memcmp(&pSysWarning->WarningCode[i][0], "042201", 6) == 0) {
+                EmcOccureByString("042201");
+                Rtn = 1;
+            } else if (memcmp(&pSysWarning->WarningCode[i][0], "042202", 6) == 0) {
+                EmcOccureByString("042202");
+                Rtn = 1;
+            } else if (memcmp(&pSysWarning->WarningCode[i][0], "012304", 6) == 0) {
+                EmcOccureByString("012304");
+                Rtn = 1;
+            }
+        }
+        if (Rtn == 0) {
+            ReleaseEmsOccureByString(0, "042251");
+            ReleaseEmsOccureByString(0, "042252");
+            ReleaseEmsOccureByString(0, "042200");
+            ReleaseEmsOccureByString(0, "042201");
+            ReleaseEmsOccureByString(0, "042202");
+            ReleaseEmsOccureByString(0, "012304");
+        }
+    } else {
+        ReleaseEmsOccureByString(0, "042251");
+        ReleaseEmsOccureByString(0, "042252");
+        ReleaseEmsOccureByString(0, "042200");
+        ReleaseEmsOccureByString(0, "042201");
+        ReleaseEmsOccureByString(0, "042202");
+        ReleaseEmsOccureByString(0, "012304");
+    }
+
+    if (ShmPrimaryMcuData->InputDet.bits.EmergencyButton == ABNORMAL) {
+        pAlarmCode->AlarmEvents.bits.EmergencyStopTrip = YES;
+        EmcOccureByString("012251");
+    } else {
+        ReleaseEmsOccureByString(0, "012251");
+    }
+
+    if (ShmPrimaryMcuData->InputDet.bits.AcMainBreakerDetec == ABNORMAL) {
+        pAlarmCode->AlarmEvents.bits.MainPowerBreakerTrip = YES;
+        EmcOccureByString("012238");
+    } else {
+        ReleaseEmsOccureByString(0, "012238");
+    }
+
+    if (ShmPrimaryMcuData->InputDet.bits.SpdDetec == ABNORMAL) {
+        pAlarmCode->AlarmEvents.bits.SpdTrip = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.SpdTrip = NO;
+    }
+
+    if (ShmPrimaryMcuData->InputDet.bits.DoorOpen == ABNORMAL) {
+        pAlarmCode->AlarmEvents.bits.DoorOpen = YES;
+        EmcOccureByString("012252");
+    } else {
+        ReleaseEmsOccureByString(0, "012252");
+    }
+
+    //DS60-120 add
+    //if (ShmPrimaryMcuData->InputDet.bits.Button1 == BTN_PRESS &&
+    //        ShmPrimaryMcuData->InputDet.bits.Button2 == BTN_PRESS) {
+    //    pSysConfig->ShowInformation = YES;
+    //} else {
+    //    pSysConfig->ShowInformation = NO;
+    //}
+
+    if (ShmPrimaryMcuData->InputDet.bits.Button1 == BTN_PRESS &&
+            !leftBtnPush
+#if defined DD360Audi
+            &&
+            getCurLcmPage() != _LCM_AUTHORIZING &&
+            getCurLcmPage() != _LCM_AUTHORIZ_COMP &&
+            getCurLcmPage() != _LCM_AUTHORIZ_FAIL
+#endif //defined DD360Audi
+       ) {
+        pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(pSysInfo->CurGunSelected);
+
+        if (!leftBtnPush) {
+            leftBtnPush = true;
+            log_info("left btn down...............................%x\n",
+                     pDcChargingInfo->SystemStatus);
+            if (pSysInfo->CurGunSelectedByAc != NO_DEFINE) {
+                pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(0);
+
+                switch (pAcChargingInfo->SystemStatus) {
+                case S_IDLE: {
+                    if (isDetectPlugin()) {
+                        _DetectPlugInTimeout();
+                        StopSystemTimeoutDet();
+                    }
+                }
+                break;
+                case S_REASSIGN_CHECK:
+                case S_REASSIGN:
+                case S_PREPARNING:
+                case S_PREPARING_FOR_EV:
+                case S_PREPARING_FOR_EVSE:
+                case S_CCS_PRECHARGE_ST0:
+                case S_CCS_PRECHARGE_ST1: {
+                    // 取消充電
+                    AcChargingTerminalProcess();
+                }
+                break;
+                case S_CHARGING: {
+                    if (pSysConfig->AuthorisationMode == AUTH_MODE_DISABLE) {
+                        // 停止充電
+                        AcChargingTerminalProcess();
+                    }
+                }
+                break;
+                case S_COMPLETE:
+                {}
+                break;
+                }
+            }
+
+            switch (pDcChargingInfo->SystemStatus) {
+            case S_IDLE: {
+                if (isDetectPlugin()) {
+                    _DetectPlugInTimeout();
+                    StopSystemTimeoutDet();
+                    destroySelGun(pSysInfo->CurGunSelected);
+                }
+#if defined DD360Audi
+                else {
+                    if (getConfirmSelectedGun(pSysInfo->CurGunSelected) == PASS) {
+                        //printf("destroy gun = %d\r\n", pSysInfo->CurGunSelected);
+                        destroySelGun(pSysInfo->CurGunSelected);
+                    } else {
+                        confirmSelGun(pSysInfo->CurGunSelected);
+                        log_info("confirm select gun ............................... %d \n",
+                                 pSysInfo->CurGunSelected);
+                    }
+                }
+#endif //defined DD360Audi
+            }
+            break;
+            case S_REASSIGN_CHECK:
+            case S_REASSIGN:
+            case S_PREPARNING:
+            case S_PREPARING_FOR_EV:
+            case S_PREPARING_FOR_EVSE:
+            case S_CCS_PRECHARGE_ST0:
+            case S_CCS_PRECHARGE_ST1: {
+                // 取消充電
+                if (pSysInfo->CurGunSelectedByAc != NO_DEFINE) {
+                    AcChargingTerminalProcess();
+                } else {
+                    ChargingTerminalProcess(pSysInfo->CurGunSelected);
+                }
+            }
+            break;
+            case S_CHARGING: {
+                if (pSysConfig->StopChargingByButton == YES ||
+                        pSysConfig->AuthorisationMode == AUTH_MODE_DISABLE) {
+                    // 停止充電
+                    ChargingTerminalProcess(pSysInfo->CurGunSelected);
+                }
+            }
+            break;
+            case S_COMPLETE: {
+                // 回 IDLE
+                //log_info("right btn down.................S_COMPLETE \n");
+                //pDcChargingInfo->SystemStatus = S_IDLE;
+            }
+            break;
+            }
+        }
+    } else if (ShmPrimaryMcuData->InputDet.bits.Button1 == BTN_RELEASE) {
+        if (leftBtnPush) {
+            leftBtnPush = false;
+            //log_info("left btn up............................... \n");
+        }
+    }
+
+    if (ShmPrimaryMcuData->InputDet.bits.Button2 == BTN_PRESS &&
+            !rightBtnPush
+#if defined DD360Audi
+            &&
+            getCurLcmPage() != _LCM_IDLE &&
+            getCurLcmPage() != _LCM_AUTHORIZING &&
+            getCurLcmPage() != _LCM_AUTHORIZ_COMP &&
+            getCurLcmPage() != _LCM_AUTHORIZ_FAIL &&
+            getCurLcmPage() != _LCM_WAIT_FOR_PLUG
+#endif //defined DD360Audi
+       ) {
+        if (!rightBtnPush) {
+            rightBtnPush = true;
+            //log_info("right btn down............................... %d \n", pSysInfo->CurGunSelected);
+            if (pSysInfo->CurGunSelected + 1 < pSysConfig->TotalConnectorCount &&
+                    pSysInfo->IsAlternatvieConf == NO) {
+                pSysInfo->CurGunSelected++;
+                ChangeGunSelectByIndex(pSysInfo->CurGunSelected);
+            } else if (pSysConfig->AcConnectorCount > 0 &&
+                       pSysInfo->CurGunSelectedByAc == NO_DEFINE) {
+                pSysInfo->CurGunSelectedByAc = DEFAULT_AC_INDEX;
+            } else if (pSysInfo->IsAlternatvieConf == YES) {
+                for (uint8_t _index = 0; _index < pSysConfig->TotalConnectorCount; _index++) {
+                    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_index);
+
+                    if (pDcChargingInfo->SystemStatus != S_BOOTING &&
+                            pDcChargingInfo->SystemStatus != S_IDLE &&
+                            pDcChargingInfo->SystemStatus != S_RESERVATION) {
+                        pSysInfo->CurGunSelected = _index;
+                        ChangeGunSelectByIndex(pSysInfo->CurGunSelected);
+                        return;
+                    }
+                }
+                pSysInfo->CurGunSelected = 0;
+                ChangeGunSelectByIndex(pSysInfo->CurGunSelected);
+            } else {
+                pSysInfo->CurGunSelected = 0;
+                ChangeGunSelectByIndex(pSysInfo->CurGunSelected);
+            }
+        }
+        log_info("current select gun ............................... %d \n",
+                 pSysInfo->CurGunSelected);
+    } else if (ShmPrimaryMcuData->InputDet.bits.Button2 == BTN_RELEASE) {
+        if (rightBtnPush) {
+            rightBtnPush = false;
+            //log_info("right btn up............................... \n");
+        }
+    }
+}
+#endif //0
+
+//===============================================
+// 確認各小板偵測的錯誤狀況
+//===============================================
+void CheckErrorOccurStatus(uint8_t index)
+{
+#if 0
+    // 小板
+    if (chargingInfo[index]->Type == _Type_Chademo) {
+        if (pFaultCode->FaultEvents.bits.ChademoOutputRelayDrivingFault == YES) {
+            BoardErrOccurByString(index, "011012");
+        }
+//      else if (pAlarmCode->AlarmEvents.bits.ChademoGfdTrip == YES)
+//          BoardErrOccurByString(index, "012234");
+    } else if (chargingInfo[index]->Type == _Type_GB) {
+        if (pFaultCode->FaultEvents.bits.GbOutputRelayDrivingFault == YES) {
+            BoardErrOccurByString(index, "011016");
+        }
+//      else if (pAlarmCode->AlarmEvents.bits.GbGfdTrip == YES)
+//          BoardErrOccurByString(index, "012236");
+    } else if (chargingInfo[index]->Type == _Type_CCS_2) {
+        if (pFaultCode->FaultEvents.bits.CcsOutputRelayDrivingFault == YES) {
+            BoardErrOccurByString(index, "011014");
+        }
+//      else if (pAlarmCode->AlarmEvents.bits.CcsGfdTrip == YES)
+//          BoardErrOccurByString(index, "012235");
+    }
+#endif //0
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+    // RB
+    if (pSysConfig->PhaseLossPolicy == YES) {
+        if (pAlarmCode->AlarmEvents.bits.SystemL1InputUVP == YES ||
+                pAlarmCode->AlarmEvents.bits.SystemL2InputUVP == YES ||
+                pAlarmCode->AlarmEvents.bits.SystemL3InputUVP == YES) {
+            if (pSysWarning->ExtraErrProcess == _EXTRA_ERR_PROCESS_NONE) {
+                pSysWarning->ExtraErrProcess = _EXTRA_ERR_PROCESS_INUVP;
+                StopChargingProcessByString(2);
+                InformOcppErrOccur(13);
+            }
+
+            //DS60-120 add -----
+            if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "", 6) == EQUAL) {
+                if (pAlarmCode->AlarmEvents.bits.SystemL1InputUVP == YES) {
+                    memcpy(pDcChargingInfo->ConnectorAlarmCode, "012203", 6);
+                } else if (pAlarmCode->AlarmEvents.bits.SystemL2InputUVP == YES) {
+                    memcpy(pDcChargingInfo->ConnectorAlarmCode, "012204", 6);
+                } else if (pAlarmCode->AlarmEvents.bits.SystemL3InputUVP == YES) {
+                    memcpy(pDcChargingInfo->ConnectorAlarmCode, "012205", 6);
+                }
+            }
+            //log_info("1 CheckErrorOccurStatus\r\n");
+            pDcChargingInfo->StopChargeFlag = YES;
+            //------------------------------------------------------------------
+        } else {
+            if (pSysWarning->ExtraErrProcess == _EXTRA_ERR_PROCESS_INUVP) {
+                pSysWarning->ExtraErrProcess = _EXTRA_ERR_PROCESS_NONE;
+                ReleaseChargingProcessByString(2);
+                InformOcppErrOccur(6);
+            }
+        }
+    } else {
+        if (pSysWarning->ExtraErrProcess == _EXTRA_ERR_PROCESS_INUVP) {
+            pSysWarning->ExtraErrProcess = _EXTRA_ERR_PROCESS_NONE;
+            ReleaseChargingProcessByString(2);
+            InformOcppErrOccur(6);
+        }
+    }
+
+    if (pAlarmCode->AlarmEvents.bits.SystemL1InputOVP == YES ||
+            pAlarmCode->AlarmEvents.bits.SystemL2InputOVP == YES ||
+            pAlarmCode->AlarmEvents.bits.SystemL3InputOVP == YES) {
+        if (pSysWarning->ExtraErrProcess == _EXTRA_ERR_PROCESS_NONE) {
+            pSysWarning->ExtraErrProcess = _EXTRA_ERR_PROCESS_INOVP;
+            StopChargingProcessByString(2);
+            InformOcppErrOccur(14);
+        }
+
+        //DS60-120 -----
+        if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "", 6) == EQUAL) {
+            if (pAlarmCode->AlarmEvents.bits.SystemL1InputOVP == YES) {
+                memcpy(pDcChargingInfo->ConnectorAlarmCode, "012200", 6);
+            } else if (pAlarmCode->AlarmEvents.bits.SystemL2InputOVP == YES) {
+                memcpy(pDcChargingInfo->ConnectorAlarmCode, "012201", 6);
+            } else if (pAlarmCode->AlarmEvents.bits.SystemL3InputOVP == YES) {
+                memcpy(pDcChargingInfo->ConnectorAlarmCode, "012202", 6);
+            }
+        }
+        //log_info("2 CheckErrorOccurStatus\r\n");
+        pDcChargingInfo->StopChargeFlag = YES;
+        //----------------------------------------------------------------------
+    } else {
+        if (pSysWarning->ExtraErrProcess == _EXTRA_ERR_PROCESS_INOVP) {
+            pSysWarning->ExtraErrProcess = _EXTRA_ERR_PROCESS_NONE;
+            ReleaseChargingProcessByString(2);
+            InformOcppErrOccur(6);
+        }
+    }
+
+    //DS60-120 ----
+    //if (chargingInfo[index]->Type == _Type_Chademo) {
+    //    if (pFaultCode->FaultEvents.bits.ChademoOutputRelayWelding == YES) {
+    //        memcpy(chargingInfo[index]->ConnectorAlarmCode, "011011", 6);
+    //    } else if (pFaultCode->FaultEvents.bits.ChademoOutputRelayDrivingFault == YES) {
+    //        memcpy(chargingInfo[index]->ConnectorAlarmCode, "011012", 6);
+    //    } else if (pAlarmCode->AlarmEvents.bits.SystemChademoOutputOVP == YES) {
+    //        memcpy(chargingInfo[index]->ConnectorAlarmCode, "012217", 6);
+    //    }
+    //} else if (chargingInfo[index]->Type == _Type_GB) {
+    //    if (pFaultCode->FaultEvents.bits.GbOutputRelayWelding == YES) {
+    //        memcpy(chargingInfo[index]->ConnectorAlarmCode, "011015", 6);
+    //    } else if (pFaultCode->FaultEvents.bits.GbOutputRelayDrivingFault == YES) {
+    //        memcpy(chargingInfo[index]->ConnectorAlarmCode, "011016", 6);
+    //    } else if (pAlarmCode->AlarmEvents.bits.SystemGbOutputOVP == YES) {
+    //        memcpy(chargingInfo[index]->ConnectorAlarmCode, "012221", 6);
+    //    }
+    //} else if (chargingInfo[index]->Type == _Type_CCS_2) {
+    //    if (pFaultCode->FaultEvents.bits.CcsOutputRelayWelding == YES) {
+    //        memcpy(chargingInfo[index]->ConnectorAlarmCode, "011013", 6);
+    //    } else if (pFaultCode->FaultEvents.bits.CcsOutputRelayDrivingFault == YES) {
+    //        memcpy(chargingInfo[index]->ConnectorAlarmCode, "011014", 6);
+    //    } else if (pAlarmCode->AlarmEvents.bits.SystemCcsOutputOVP == YES) {
+    //        memcpy(chargingInfo[index]->ConnectorAlarmCode, "012219", 6);
+    //    }
+    //}
+
+    //--------------------------------------------------------------------------
+    if (strlen((char *)pDcChargingInfo->ConnectorAlarmCode) == 0) {
+        //Primary
+        if (pAlarmCode->AlarmEvents.bits.EmergencyStopTrip == YES) {
+            memcpy(pDcChargingInfo->ConnectorAlarmCode, "012251", 6);
+        } else if (pAlarmCode->AlarmEvents.bits.DoorOpen == YES) {
+            memcpy(pDcChargingInfo->ConnectorAlarmCode, "012252", 6);
+        } else if (pAlarmCode->AlarmEvents.bits.MainPowerBreakerTrip == YES) {
+            memcpy(pDcChargingInfo->ConnectorAlarmCode, "012238", 6);
+        } else if (pAlarmCode->AlarmEvents.bits.DisconnectedFromDo == YES) {
+            memcpy(pDcChargingInfo->ConnectorAlarmCode, "012304", 6);
+        }
+    }
+}
+
+//===============================================
+// 確認 GPIO 狀態
+//===============================================
+void gpio_set_value(unsigned int gpio, unsigned int value)
+{
+    int fd;
+    char buf[MAX_BUF];
+
+    snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);
+    fd = open(buf, O_WRONLY);
+    if (fd < 0) {
+        perror("gpio/set-value");
+        return;
+    }
+
+    if (value) {
+        write(fd, "1", 2);
+    } else {
+        write(fd, "0", 2);
+    }
+
+    close(fd);
+}
+
+int gpio_get_value(unsigned int gpio, unsigned int *value)
+{
+    int fd;
+    char buf[MAX_BUF];
+    char ch;
+
+    snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);
+
+    fd = open(buf, O_RDONLY);
+    if (fd < 0) {
+        perror("gpio/get-value");
+        return fd;
+    }
+
+    read(fd, &ch, 1);
+
+    if (ch != '0') {
+        *value = 1;
+    } else {
+        *value = 0;
+    }
+
+    close(fd);
+    return 0;
+}
+
+void CheckGunTypeFromHw()
+{
+    uint8_t i = 0;
+    int pinIn[4] = {22, 23, 44, 45};
+    unsigned int gpioValue = 0;
+    uint8_t tmp[2] = {0};
+
+    log_info("ModelName = %s", pSysConfig->ModelName);
+    for (i = 0; i < ARRAY_SIZE(pinIn); i++) {
+        gpio_get_value(pinIn[i], &gpioValue);
+        switch (pinIn[i]) {
+        //right slot
+        case 22:
+            bd1_1_status = gpioValue;
+            break;
+        case 23:
+            bd1_2_status = gpioValue;
+            break;
+
+        //left slot
+        case 44:
+            bd0_1_status = gpioValue;
+            break;
+        case 45:
+            bd0_2_status = gpioValue;
+            break;
+        }
+    }
+
+#if 1 //DS60-120 remove
+    //BD1(Left-CCS-CND1-SMR2-左槍), BD2(Right-CHADEMO-CND2-SMR1-右槍), CCS: 10 , CHAdeMO: 01 , GBT: 11
+    //CcsChargingData [0至1] 分別為 Right至Left
+    //model name 槍順序左至右分別為Right至Left
+    tmp[1] = (bd0_1_status << 4 | bd0_2_status);
+    tmp[0] = (bd1_1_status << 4 | bd1_2_status);
+    for (i = 0; i < 2; i++) {
+        switch (tmp[i]) {
+        case 0x01:
+            log_info("BD%d(%s) = %s ", i + 1, i == 0 ? "Left" : "Right", "CHAdeMO");
+            break;
+
+        case 0x10:
+            log_info("BD%d(%s) = %s ", i + 1, i == 0 ? "Left" : "Right", "CCS");
+            break;
+
+        case 0x11:
+            log_info("BD%d(%s) = %s ", i + 1, i == 0 ? "Left" : "Right", "GBT");
+            break;
+
+        case 0x00:
+            log_info("BD%d(%s) = %s ", i + 1, i == 0 ? "Left" : "Right", "None");
+            break;
+        }
+    }
+#endif //0
+}
+
+void CheckGpioInStatus()
+{
+    int pinIn[2] = { 27, 47 };//{IO BD1_2, IO BD2_2}
+    unsigned int gpioValue = 0;
+
+    for (int i = 0; i < ARRAY_SIZE(pinIn); i++) {
+        gpio_get_value(pinIn[i], &gpioValue);
+        if (gpioValue == 0x01) {
+            switch (pinIn[i]) {
+            // 小板緊急停止
+            case 47: {
+                for (int i = 0; i < pSysConfig->TotalConnectorCount; i++) {
+                    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(i);
+
+                    if (pDcChargingInfo->slotsIndex == 1) {
+                        if (pDcChargingInfo->Type == _Type_Chademo) {
+                            BoardErrOccurByString(i, "023730");
+                        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                            BoardErrOccurByString(i, "013627");
+                        }
+                        break;
+                    }
+                }
+            }
+            break;
+            case 27: {
+                for (int i = 0; i < pSysConfig->TotalConnectorCount; i++) {
+                    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(i);
+
+                    if (pDcChargingInfo->slotsIndex == 3) {
+                        if (pDcChargingInfo->Type == _Type_Chademo) {
+                            BoardErrOccurByString(i, "023730");
+                        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                            BoardErrOccurByString(i, "013627");
+                        }
+                        break;
+                    }
+                }
+            }
+            break;
+            }
+        } else {
+            switch (pinIn[i]) {
+            // 小板解除緊急停止
+            case 47: {
+                for (int i = 0; i < pSysConfig->TotalConnectorCount; i++) {
+                    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(i);
+
+                    if (pDcChargingInfo->slotsIndex == 1) {
+                        if (pDcChargingInfo->Type == _Type_Chademo) {
+                            ReleaseBoardErrOccurByString(i, "023730");
+                        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                            ReleaseBoardErrOccurByString(i, "013627");
+                        }
+                        break;
+                    }
+                }
+            }
+            break;
+            case 27: {
+                for (int i = 0; i < pSysConfig->TotalConnectorCount; i++) {
+                    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(i);
+
+                    if (pDcChargingInfo->slotsIndex == 3) {
+                        if (pDcChargingInfo->Type == _Type_Chademo) {
+                            ReleaseBoardErrOccurByString(i, "023730");
+                        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                            ReleaseBoardErrOccurByString(i, "013627");
+                        }
+                        break;
+                    }
+                }
+            }
+            break;
+            }
+        }
+    }
+}
+
+//===============================================
+// Main process
+//===============================================
+// 檢查 uint8_t 中某個 Bit 的值
+// _byte : 欲改變的 byte
+// _bit : 該 byte 的第幾個 bit
+uint8_t DetectBitValue(uint8_t _byte, uint8_t _bit)
+{
+    return ( _byte & mask_table[_bit] ) != 0x00;
+}
+
+// 設定 Byte 中某個 Bit的值
+// _byte : 欲改變的 byte
+// _bit : 該 byte 的第幾個 bit
+// value : 修改的值為 0 or 1
+void SetBitValue(uint8_t *_byte, uint8_t _bit, uint8_t value)
+{
+    if (value == 1) {
+        *_byte |= (1 << _bit);
+    } else if (value == 0) {
+        *_byte ^= (1 << _bit);
+    }
+}
+
+#if 0
+void UserScanFunction()
+{
+    bool idleReq = false;
+    uint8_t stopReq = 255;
+    pAcChargingInfo =  (struct ChargingInfoData *)GetAcChargingInfoData(0);
+
+    // 當前非驗證的狀態
+    if (!IsAuthorizingMode()) {
+#if defined DD360Audi
+        //當前沒有選槍
+        if (getConfirmSelectedGun(pSysInfo->CurGunSelected) == FAIL) { //Jerry add
+            strcpy((char *)pSysConfig->UserId, "");
+            return;
+        }
+#endif //defined DD360Audi
+
+        // 先判斷現在是否可以提供刷卡
+        // 1. 如果當前沒有槍是閒置狀態,則無提供刷卡功能
+        // 2. 停止充電
+        if (pSysInfo->PageIndex == _LCM_FIX) {
+            strcpy((char *)pSysConfig->UserId, "");
+            return;
+        }
+
+        for (uint8_t i = 0; i < pSysConfig->TotalConnectorCount; i++) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(i);
+
+            if (pDcChargingInfo->SystemStatus == S_CHARGING) {
+                stopReq = i;
+            }
+            if ((pDcChargingInfo->SystemStatus == S_IDLE &&
+                    pDcChargingInfo->IsAvailable) == YES ||
+                    (_acgunIndex > 0 && pAcChargingInfo->SystemStatus ==
+                     S_IDLE && pAcChargingInfo->IsAvailable)
+               ) {
+                idleReq = true;
+            }
+        }
+
+        if (_acgunIndex > 0 && pSysInfo->CurGunSelectedByAc == DEFAULT_AC_INDEX &&
+                pAcChargingInfo->SystemStatus == S_CHARGING) {
+            stopReq = DEFAULT_AC_INDEX;
+        }
+
+        if (strlen((char *)pSysConfig->UserId) > 0) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(pSysInfo->CurGunSelected);
+
+            if (_acgunIndex > 0 && stopReq == DEFAULT_AC_INDEX &&
+                    pSysInfo->CurGunSelectedByAc == DEFAULT_AC_INDEX) {
+                char value[32];
+
+                log_info("ac stop charging \n");
+                log_info("index = %d, card number = %s, UserId = %s \n", pSysInfo->CurGunSelectedByAc,
+                         pAcChargingInfo->StartUserId, pSysConfig->UserId);
+                memcpy(value, (uint8_t *)pAcChargingInfo->StartUserId,
+                       ARRAY_SIZE(pAcChargingInfo->StartUserId));
+                if (strcmp((char *)pSysConfig->UserId, value) == EQUAL) {
+                    AcChargingTerminalProcess();
+                }
+                strcpy((char *)pSysConfig->UserId, "");
+            } else if (stopReq < pSysConfig->TotalConnectorCount &&
+                       pDcChargingInfo->SystemStatus == S_CHARGING &&
+                       (_acgunIndex <= 0 || (_acgunIndex > 0 && pSysInfo->CurGunSelectedByAc == NO_DEFINE))) {
+                char value[32];
+
+                log_info("stop charging \n");
+                log_info("index = %d, card number = %s, UserId = %s \n",
+                         pSysInfo->CurGunSelected,
+                         pDcChargingInfo->StartUserId,
+                         pSysConfig->UserId);
+                memcpy(value, (uint8_t *)pDcChargingInfo->StartUserId,
+                       ARRAY_SIZE(pDcChargingInfo->StartUserId));
+
+                // 同一張卡直接停掉
+                if (strcmp((char *)pSysConfig->UserId, value) == EQUAL) {
+                    ChargingTerminalProcess(pSysInfo->CurGunSelected);
+                    strcpy((char *)pSysConfig->UserId, "");
+                } else {
+                    // 進驗證
+                    if (_acgunIndex > 0 && pSysInfo->CurGunSelectedByAc == DEFAULT_AC_INDEX) {
+                        _authorizeIndex = pSysInfo->CurGunSelectedByAc;
+                    } else {
+                        _authorizeIndex = pSysInfo->CurGunSelected;
+                    }
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                    StartSystemTimeoutDet(Timeout_AuthorizingForStop);
+                    AuthorizingStart();
+#else
+                    strcpy((char *)pSysConfig->UserId, "");
+#endif //!defined DD360 && !defined DD360Audi
+                }
+            } else if (idleReq) {
+                if (pSysConfig->TotalConnectorCount > 1 &&
+                        stopReq != 255 &&
+                        pSysInfo->IsAlternatvieConf == YES) {
+                    idleReq = false;
+                    strcpy((char *)pSysConfig->UserId, "");
+                } else if ((_acgunIndex > 0 && pSysInfo->CurGunSelectedByAc == DEFAULT_AC_INDEX) ||
+                           pDcChargingInfo->SystemStatus == S_IDLE) {
+                    log_info("// LCM => Authorizing \n");
+#if defined DD360Audi
+                    setSelGunWaitToAuthor(pSysInfo->CurGunSelected); //Jerry add
+#endif //defined DD360Audi
+                    // LCM => Authorizing
+                    pSysInfo->SystemPage = _LCM_AUTHORIZING;
+                    // 進入確認卡號狀態
+                    AuthorizingStart();
+                } else {
+                    strcpy((char *)pSysConfig->UserId, "");
+                }
+            } else {
+                strcpy((char *)pSysConfig->UserId, "");
+            }
+        }
+    } else {
+        // 透過後臺停止充電的判斷
+        if (isAuthorizedComplete()
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                || (pSysInfo->OcppConnStatus == NO &&
+                    pSysConfig->OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING)
+#endif //!defined DD360 && !defined DD360Audi
+           ) {
+            // 判斷後台回覆狀態
+            if (canStartCharging()
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                    || (pSysInfo->OcppConnStatus == NO &&
+                        pSysConfig->OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING)
+#endif //!defined DD360 && !defined DD360Audi
+               ) {
+                if (_authorizeIndex != NO_DEFINE) {
+                    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_authorizeIndex);
+
+                    // 先找 AC
+                    if (_authorizeIndex == DEFAULT_AC_INDEX) {
+                        if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST &&
+                                strcmp((char *)pDcChargingInfo->StartUserId, "") != EQUAL) {
+                            AcChargingTerminalProcess();
+                        }
+                    } else {
+                        if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST &&
+                                strcmp((char *)pDcChargingInfo->StartUserId, "") != EQUAL) {
+                            ChargingTerminalProcess(_authorizeIndex);
+                        }
+                    }
+                    strcpy((char *)pSysConfig->UserId, "");
+                    _authorizeIndex = NO_DEFINE;
+                }
+            } else {
+                strcpy((char *)pSysConfig->UserId, "");
+            }
+            ClearAuthorizedFlag();
+        } else if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST) {
+            // 白名單驗證
+            for (int i = 0; i < 10; i++) {
+                if (strcmp((char *)pSysConfig->LocalWhiteCard[i], "") != EQUAL) {
+                    if (strcmp((char *)pSysConfig->LocalWhiteCard[i], (char *)pSysConfig->UserId) == EQUAL) {
+                        ChargingTerminalProcess(_authorizeIndex);
+                        strcpy((char *)pSysConfig->UserId, "");
+                        ClearAuthorizedFlag();
+                        break;
+                    }
+                }
+            }
+        }
+    }
+}
+#endif //0
+
+uint8_t isModeChange(uint8_t gun_index)
+{
+    uint8_t result = NO;
+
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun_index);
+
+    if (pDcChargingInfo->SystemStatus != pDcChargingInfo->PreviousSystemStatus) {
+        result = YES;
+        pDcChargingInfo->PreviousSystemStatus = pDcChargingInfo->SystemStatus;
+        ShmDcCommonData->SystemModeChange = YES;
+    }
+
+    return result;
+}
+
+#if 0
+void ScannerCardProcess()
+{
+    if (!isDetectPlugin() && !isCardScan && pSysWarning->Level != 2 &&
+            pSysConfig->AuthorisationMode == AUTH_MODE_ENABLE) {
+        isCardScan = true;
+        // 處理刷卡及驗證卡號的動作
+        UserScanFunction();
+    }
+
+    if (pSysInfo->PageIndex == _LCM_AUTHORIZING) {
+        StartSystemTimeoutDet(Timeout_Authorizing);
+
+        // 確認驗證卡號完成沒
+        if (isAuthorizedComplete()
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                || pSysConfig->OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING
+#else
+                && gAudiCustInfo->PricesInfo[pSysInfo->CurGunSelected].Balance != FAIL_BALANCE_PRICES
+#endif //!defined DD360 && !defined DD360Audi
+           ) {
+            StopSystemTimeoutDet();
+            // 判斷後台回覆狀態
+            if (canStartCharging()
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                    || pSysConfig->OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING
+#endif //!defined DD360 && !defined DD360Audi
+               ) {
+                // LCM => Authorize complete
+                pSysInfo->SystemPage = _LCM_AUTHORIZ_COMP;
+            } else {
+                // LCM => Authorize fail
+                pSysInfo->SystemPage = _LCM_AUTHORIZ_FAIL;
+                strcpy((char *)pSysConfig->UserId, "");
+            }
+            ClearAuthorizedFlag();
+        } else if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST) {
+            // 白名單驗證
+            for (int i = 0; i < 10; i++) {
+                if (strcmp((char *)pSysConfig->LocalWhiteCard[i], "") != EQUAL) {
+                    if (strcmp((char *)pSysConfig->LocalWhiteCard[i], (char *)pSysConfig->UserId) == EQUAL) {
+                        pSysInfo->SystemPage = _LCM_AUTHORIZ_COMP;
+                        ClearAuthorizedFlag();
+                        break;
+                    }
+                }
+            }
+        }
+    } else if (pSysInfo->PageIndex == _LCM_AUTHORIZ_FAIL) {
+        StartSystemTimeoutDet(Timeout_VerifyFail);
+        isCardScan = false;
+    } else if (pSysInfo->PageIndex == _LCM_AUTHORIZ_COMP) {
+        StartSystemTimeoutDet(Timeout_VerifyComp);
+    } else if (pSysInfo->PageIndex == _LCM_WAIT_FOR_PLUG) {
+        StartSystemTimeoutDet(Timeout_WaitPlug);
+    } else {
+        isCardScan = false;
+    }
+}
+
+bool AddGunInfoByConnector(uint8_t typeValue, uint8_t slots)
+{
+    bool result = true;
+
+    switch (typeValue) {
+    case '0': // none
+        break;
+    case '1': // IEC 62196-2 Type 1/SAE J1772 Plug
+        break;
+    case '2': // IEC 62196-2 Type 1/SAE J1772 Socket
+        break;
+    case '3': // IEC 62196-2 Type 2 Plug
+    case '4': // IEC 62196-2 Type 2 Socket
+        if (AC_QUANTITY > _ac_Index) {
+            pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(_acgunIndex);
+
+            pAcChargingInfo = &pSysInfo->AcChargingData[_ac_Index];
+
+            // AC 固定 index
+            pAcChargingInfo->Index = 0;
+            pAcChargingInfo->ReservationId = -1;
+            pAcChargingInfo->SystemStatus = S_IDLE;
+            pAcChargingInfo->Type = _Type_AC;
+            pAcChargingInfo->IsAvailable = YES;
+            pAcChargingInfo->schedule.isTriggerStart = NO; //DS60-120 add
+            pAcChargingInfo->schedule.isTriggerStop = NO;  //DS60-120 add
+            _ac_Index++;
+            _acgunIndex++;
+        } else {
+            result = false;
+        }
+        break;
+    case '5': // GB/T AC Plug
+        break;
+    case '6': // GB/T AC Socket
+        break;
+    case 'J':
+    case 'K': { // CHAdeMO
+        if (CHAdeMO_QUANTITY > _chademoIndex) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_gunIndex);
+
+            pDcChargingInfo = &pSysInfo->ChademoChargingData[_chademoIndex];
+            pDcChargingInfo->Index = _gunIndex;
+            pDcChargingInfo->ReservationId = -1;
+            pDcChargingInfo->slotsIndex = slots;
+            pDcChargingInfo->SystemStatus = S_BOOTING;
+            pDcChargingInfo->Type = _Type_Chademo;
+            pDcChargingInfo->type_index = _chademoIndex;
+            pDcChargingInfo->IsAvailable = YES;
+
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_acgunIndex);
+            pDcChargingInfo->schedule.isTriggerStart = NO; //DS60-120 add
+            pDcChargingInfo->schedule.isTriggerStop = NO;  //DS60-120 add
+            _chademoIndex++;
+            _gunIndex++;
+        } else {
+            result = false;
+        }
+    }
+    break;
+
+    case 'T': //Rema CCS1
+    case 'D': //Rema CCS2
+    case 'U': // CCS1 combo
+    case 'E': // CCS2 combo
+    case 'V': // Liquid CCS1 combo
+    case 'F': { // Liquid CCS2 combo
+        if (CCS_QUANTITY > _ccsIndex) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_gunIndex);
+
+            pDcChargingInfo = &pSysInfo->CcsChargingData[_ccsIndex];
+
+            pDcChargingInfo->Index = _gunIndex;
+            pDcChargingInfo->ReservationId = -1;
+            pDcChargingInfo->slotsIndex = slots;
+            pDcChargingInfo->SystemStatus = S_BOOTING;
+            pDcChargingInfo->Type = _Type_CCS_2;
+            pDcChargingInfo->type_index = _ccsIndex;
+            pDcChargingInfo->IsAvailable = YES;
+
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_acgunIndex);
+            pDcChargingInfo->schedule.isTriggerStart = NO;//DS60-120 add
+            pDcChargingInfo->schedule.isTriggerStop = NO; //DS60-120 add
+            // 現階段預設為走 DIN70121
+            ShmCcsData->CommProtocol = _CCS_COMM_V2GMessage_DIN70121;
+            _ccsIndex++;
+            _gunIndex++;
+        } else {
+            result = false;
+        }
+    }
+    break;
+    case 'G': { // GBT DC
+        if (GB_QUANTITY > _gb_Index) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_gunIndex);
+
+            pDcChargingInfo = &pSysInfo->GbChargingData[_gb_Index];
+
+            pDcChargingInfo->Index = _gunIndex;
+            pDcChargingInfo->ReservationId = -1;
+            pDcChargingInfo->slotsIndex = slots;
+            pDcChargingInfo->SystemStatus = S_BOOTING;
+            pDcChargingInfo->Type = _Type_GB;
+            pDcChargingInfo->type_index = _gb_Index;
+            pDcChargingInfo->IsAvailable = YES;
+
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_acgunIndex);
+            pDcChargingInfo->schedule.isTriggerStart = NO;//DS60-120 add
+            pDcChargingInfo->schedule.isTriggerStop = NO; //DS60-120 add
+            _gb_Index++;
+            _gunIndex++;
+        } else {
+            result = false;
+        }
+    }
+    break;
+
+        //case 'D': // GBT DC x 2
+        //    break;
+    }
+    return result;
+}
+#endif //0
+
+static int checkSlotGpioMappingGunType(uint8_t gunIndex, uint8_t gunType)
+{
+    uint8_t slot1 = 0, slot2 = 0;
+
+    if (gunIndex == 0) {
+        slot1 = bd0_1_status;
+        slot2 = bd0_2_status;
+    } else if (gunIndex == 1) {
+        slot1 = bd1_1_status;
+        slot2 = bd1_2_status;
+    }
+
+    log_info("slot %d gpio1 = %d, gpio2 = %d, type = %d\r\n", gunIndex, slot1, slot2, gunType);
+    switch (gunType) {
+    case _Type_Chademo:
+        if (slot1 != NO && slot2 != YES) {
+            return FAIL;
+        }
+        break;
+
+    case _Type_CCS_2:
+        if (slot1 != YES && slot2 != NO) {
+            return FAIL;
+        }
+        break;
+
+    case _Type_GB:
+        if (slot1 != YES && slot2 != YES) {
+            return FAIL;
+        }
+        break;
+    }
+
+    return PASS;
+}
+
+bool CheckConnectorTypeStatus()
+{
+    bool result = true;
+
+    uint8_t gunIndex = 0;
+    struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
+    struct ChargingInfoData *pDcChargingInfo = NULL;
+
+    if (!MappingGunChargingInfo("CSU Task")) {
+        log_error("CheckConnectorTypeStatus MappingGunChargingInfo failed\r\n");
+        return false;
+    }
+
+    // 偵測槍屬於哪個 slot : 可知道插在板上的Slot 0 或 1 是 Chademo 還是 CCS
+    for (gunIndex = 0; gunIndex < pSysConfig->TotalConnectorCount; gunIndex++) {
+        pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+        if (checkSlotGpioMappingGunType(gunIndex, pDcChargingInfo->Type) == FAIL) {
+            return false;
+        }
+
+        switch (gunIndex) {
+        case 0:
+            if (pSysConfig->TotalConnectorCount == 1) {
+                if ((bd0_1_status == YES || bd0_2_status == YES) &&
+                        (bd1_1_status == NO && bd1_2_status == NO)) {
+                    pDcChargingInfo->Evboard_id = 0x01;
+                }
+
+                if ((bd0_1_status == NO && bd0_2_status == NO) &&
+                        (bd1_1_status == YES || bd1_2_status == YES)
+                   ) {
+                    pDcChargingInfo->Evboard_id = 0x02;
+                }
+                break;
+            }
+
+            pDcChargingInfo->Evboard_id = 0x01;
+            break;
+
+        case 1:
+            pDcChargingInfo->Evboard_id = 0x02;
+            break;
+        }
+
+        CheckHwSlotStatusLog(gunIndex);
+
+        if (pDcChargingInfo->Evboard_id == 0x00) {
+            return false;
+        }
+    }
+
+    AdjustChargerCurrent();
+
+#if 0
+    //log_info("bd0_1_status = %d, bd0_2_status = %d, bd1_1_status = %d, bd1_2_status = %d \n",
+    //            bd0_1_status,
+    //            bd0_2_status,
+    //            bd1_1_status,
+    //            bd1_2_status);
+
+    if (strlen((char *) pSysConfig->ModelName) >= 9) {
+        //printf("1 CheckConnectorTypeStatus\r\n");
+        uint8_t slots = 1;
+        for (uint8_t typeIndex = 7; typeIndex <= 9; typeIndex++) {
+            if (!AddGunInfoByConnector(pSysConfig->ModelName[typeIndex], slots)) {
+                return false;
+            }
+
+            slots++;
+        }
+
+        // AC index 接在 DC 後面
+        //if (AC_QUANTITY > 0) {
+        if (_ac_Index > 0) { //DS60-120 add
+            ac_chargingInfo[0]->Index += _gunIndex;
+        }
+
+        pSysConfig->TotalConnectorCount = _gunIndex;
+        pSysConfig->AcConnectorCount = _acgunIndex;
+        log_info("DC connector Quality = %d, AC connector Quality = %d",
+                 pSysConfig->TotalConnectorCount,
+                 pSysConfig->AcConnectorCount);
+        log_info("Type 0~3 = CHAdeMO, CCS, GB, AC");
+        if (pSysConfig->TotalConnectorCount == 0 &&
+                pSysConfig->AcConnectorCount == 0) {
+            result = false;
+        }
+
+        if (pSysConfig->TotalConnectorCount == 1) {
+            //DS60-120 add
+            bool isFind = false;
+            if (chargingInfo[0]->Type == _Type_Chademo) {
+                if ((bd0_1_status == 0 && bd0_2_status == 1) ||
+                        (bd1_1_status == 0 && bd1_2_status == 1)) {
+                    isFind = true;
+                }
+            } else if (chargingInfo[0]->Type == _Type_CCS_2) {
+                if ((bd0_1_status == 1 && bd0_2_status == 0) ||
+                        (bd1_1_status == 1 && bd1_2_status == 0)) {
+                    isFind = true;
+                }
+            } else if (chargingInfo[0]->Type == _Type_GB) {
+                if ((bd0_1_status == 1 && bd0_2_status == 1) ||
+                        (bd1_1_status == 1 && bd1_2_status == 1)) {
+                    isFind = true;
+                }
+            }
+
+            if (isFind) {
+                //if (strncmp((char *)&pSysConfig->ModelName[7], "0", 1) != 0) {
+                //    if (bd0_1_status == 1 || bd0_2_status == 1) {
+                //        chargingInfo[0]->Evboard_id = 0x01;
+                //    } else if (bd1_1_status == 1 || bd1_2_status == 1) {
+                //        chargingInfo[0]->Evboard_id = 0x02;
+                //    }
+                //} else if (strncmp((char *)&pSysConfig->ModelName[9], "0", 1) != 0) {
+                //    if (bd0_1_status == 1 || bd0_2_status == 1) {
+                //        chargingInfo[0]->Evboard_id = 0x01;
+                //    } else if (bd1_1_status == 1 || bd1_2_status == 1) {
+                //        chargingInfo[0]->Evboard_id = 0x02;
+                //    }
+                //} else {
+                //    chargingInfo[0]->Evboard_id = 0x01;
+                //}
+
+                if (bd0_1_status == 1 || bd0_2_status == 1) {
+                    chargingInfo[0]->Evboard_id = 0x01;
+                }
+
+                if (bd1_1_status == 1 || bd1_2_status == 1) {
+                    chargingInfo[0]->Evboard_id = 0x02;
+                }
+                CheckHwSlotStatusLog(0);
+            } else {
+                result = false;
+            }
+            //chargingInfo[0]->Evboard_id = 0x01;
+            log_info("index = %d, Type = %d, Evboard_id = %d", 0, chargingInfo[0]->Type, chargingInfo[0]->Evboard_id);
+        } else {
+            char type = NO_DEFINE; //DS60-120 add
+
+            // 偵測槍屬於哪個 slot : 可知道插在板上的Slot 0 或 1 是 Chademo 還是 CCS
+            for (uint8_t gunIndex = 0; gunIndex < pSysConfig->TotalConnectorCount; gunIndex++) {
+                if (gunIndex == 0 && bd0_1_status == 0 && bd0_2_status == 1) {
+                    // 與硬體相同 type : Chademo
+                    if (chargingInfo[gunIndex]->Type == _Type_Chademo) {
+                        chargingInfo[gunIndex]->Evboard_id = 0x01;
+                    }
+                } else if (gunIndex == 0 && bd0_1_status == 1 && bd0_2_status == 0) {
+                    // 與硬體相同 type : CCS
+                    if (chargingInfo[gunIndex]->Type == _Type_CCS_2) {
+                        chargingInfo[gunIndex]->Evboard_id = 0x01;
+                    }
+                } else if (gunIndex == 0 && bd0_1_status == 1 && bd0_2_status == 1) {
+                    // 與硬體相同 type : GB
+                    if (chargingInfo[gunIndex]->Type == _Type_GB) {
+                        chargingInfo[gunIndex]->Evboard_id = 0x01;
+                    }
+                }
+
+                if (gunIndex == 1 && bd1_1_status == 0 && bd1_2_status == 1) {
+                    // 與硬體相同 type : Chademo
+                    if (chargingInfo[gunIndex]->Type == _Type_Chademo) {
+                        chargingInfo[gunIndex]->Evboard_id = 0x02;
+                    }
+
+                    if (pSysConfig->TotalConnectorCount == 1) {
+                        chargingInfo[gunIndex]->Evboard_id = 0x01;
+                    }
+                } else if (gunIndex == 1 && bd1_1_status == 1 && bd1_2_status == 0) {
+                    // 與硬體相同 type : CCS
+                    if (chargingInfo[gunIndex]->Type == _Type_CCS_2) {
+                        chargingInfo[gunIndex]->Evboard_id = 0x02;
+                    }
+
+                    if (pSysConfig->TotalConnectorCount == 1) {
+                        chargingInfo[gunIndex]->Evboard_id = 0x01;
+                    }
+                } else if (gunIndex == 1 && bd1_1_status == 1 && bd1_2_status == 1) {
+                    // 與硬體相同 type : GB
+                    if (chargingInfo[gunIndex]->Type == _Type_GB) {
+                        chargingInfo[gunIndex]->Evboard_id = 0x02;
+                    }
+
+                    if (pSysConfig->TotalConnectorCount == 1) {
+                        chargingInfo[gunIndex]->Evboard_id = 0x01;
+                    }
+                }
+
+                log_info("index = %d, Type = %d, Evboard_id = %d",
+                         gunIndex,
+                         chargingInfo[gunIndex]->Type,
+                         chargingInfo[gunIndex]->Evboard_id);
+                CheckHwSlotStatusLog(gunIndex);
+
+                if (type == NO_DEFINE) {
+                    type = chargingInfo[gunIndex]->Type;
+                }
+
+                if (chargingInfo[gunIndex]->Evboard_id == 0x00) {
+                    result = false;
+                }
+            }
+        }
+    } else {
+        // Module Name 不正確 - 告警
+        result = false;
+    }
+#endif //0
+    return result;
+}
+
+void KillTask()
+{
+    ChangeLcmByIndex(_LCM_FIX);
+    system("killall Module_EventLogging");
+    system("killall Module_PrimaryComm");
+    system("killall Module_EvComm");
+    system("killall Module_LcmControl");
+    system("killall Module_InternalComm");
+    //system("killall Module_DoComm");
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+    system("killall Module_PsuComm");
+    system("killall OcppBackend &");
+    system("killall Module_4g &");
+    system("killall Module_Wifi &");
+#endif //!defined DD360 && !defined DD360Audi
+}
+
+void KillTaskExceptPrimary()
+{
+    ChangeLcmByIndex(_LCM_FIX);
+    system("killall Module_EvComm");
+    system("killall Module_InternalComm");
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+    system("killall Module_PsuComm");
+    system("killall Module_4g &");
+    system("killall Module_Wifi &");
+#endif //!defined DD360 && !defined DD360Audi
+}
+
+void KillAllTask()
+{
+    ChangeLcmByIndex(_LCM_FIX);
+    system("killall Module_EventLogging");
+    system("killall Module_PrimaryComm");
+    system("killall Module_EvComm");
+    system("killall Module_LcmControl");
+    system("killall Module_InternalComm");
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+    system("killall Module_PsuComm");
+    system("killall OcppBackend &");
+    system("killall Module_4g &");
+    system("killall Module_Wifi &");
+#else
+    system("killall Module_DoComm");
+#endif //!defined DD360 && !defined DD360Audi
+}
+
+#if 0
+int CheckUpdateProcess(void)
+{
+    //bool isPass = true;
+    uint8_t retSucc = 0;
+    uint8_t retFail = 0;
+    uint8_t index = 0;
+    uint8_t target = 0;
+    char Buf[256];
+    char *new_str = NULL;
+    uint8_t *ptr = NULL;
+    int fd = 0;
+    int CanFd = 0;
+    int uartFd = 0;
+    unsigned int Type = 0;
+    long int MaxLen = 48 * 1024 * 1024, ImageLen = 0;
+    DIR *d;
+    struct dirent *dir;
+
+    d = opendir("/mnt/");
+    if (d) {
+        while ((dir = readdir(d)) != NULL) {
+            if (strcmp(dir->d_name, ".") == 0 || strcmp(dir->d_name, "..") == 0) {
+                continue;
+            }
+
+            new_str = calloc(strlen("/mnt/") + strlen(dir->d_name) + 1, sizeof(char));
+            //new_str[0] = '\0';
+            strcat(new_str, "/mnt/");
+            strcat(new_str, dir->d_name);
+            log_info("%s%s\r\n", "/mnt/", dir->d_name);
+            fd = open(new_str, O_RDONLY);
+            if (fd < 0) {
+                return FAIL;
+            }
+
+            ptr = calloc(MaxLen, sizeof(char)); //-48 is take out the header
+            //memset(ptr, 0xFF, MaxLen);  //-48 is take out the header
+
+            //get the image length
+            ImageLen = read(fd, ptr, MaxLen);
+            for (uint8_t i = 0; i < 16; i++) {
+                if (pSysConfig->ModelName[i] != ptr[i]) {
+                    return FAIL;
+                }
+            }
+
+            log_info("model name check pass. \n");
+            if (ImageLen > 20) {
+                Type = (((unsigned int)ptr[16]) << 24 |
+                        ((unsigned int)ptr[17]) << 16 |
+                        ((unsigned int)ptr[18]) << 8  |
+                        ((unsigned int)ptr[19]));
+                log_info("Typed...%x \r\n", Type);
+
+                switch (Type) {
+                case 0x10000001:
+                case 0x10000002:
+                case 0x10000003:
+                case 0x10000004:
+                case 0x10000005:
+                    if (Upgrade_Flash(Type, new_str, (char *)pSysConfig->ModelName) == PASS) {
+                        //return PASS;
+                        retSucc++;
+                    } else {
+                        log_info("Upgrade %x Failed\r\n", Type);
+                        //return FAIL;
+                        retFail++;
+                    }
+                    break;
+
+                case 0x10000007:
+                case 0x10000008:
+                case 0x10000009:
+                case 0x1000000A:
+                    CanFd = InitCanBus();
+                    if (CanFd > 0) {
+                        for (index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+                            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+                            if (pDcChargingInfo->Type == _Type_CCS_2) {
+                                uint8_t targetID = pDcChargingInfo->Evboard_id;
+
+                                if (pSysConfig->TotalConnectorCount == 1 &&
+                                        ShmDcCommonData->CcsVersion == _CCS_VERSION_CHECK_TAG_V015S0) {
+                                    targetID += 1;
+                                }
+
+                                system("echo 3 > /proc/sys/vm/drop_caches");
+                                sleep(2);
+                                log_info("Upgrade CCS Processing..target id = %d \n", targetID);
+                                if (Upgrade_CCS(CanFd, Type, targetID, new_str, (char *)pSysConfig->ModelName) == FAIL) {
+                                    log_info("Upgrade CCS Failed \n");
+                                    retFail++;
+                                } else {
+                                    retSucc++;
+                                }
+                            }
+                        }
+                        close(CanFd);
+                    }
+                    memset(Buf, 0, sizeof(Buf));
+                    sprintf(Buf, "rm -rvf /mnt/%s", new_str);
+                    system(Buf);
+                    //isPass = true;
+#if 0
+                    CanFd = InitCanBus();
+                    if (CanFd > 0) {
+                        for (index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+                            //if (!isPass) {
+                            //    break;
+                            //}
+                            if (chargingInfo[index]->Type == _Type_CCS_2) {
+                                if (Upgrade_CCS(CanFd, Type, chargingInfo[index]->Evboard_id, new_str, (char *)pSysConfig->ModelName) == FAIL) {
+                                    //isPass = false;
+                                    log_info("Upgrade %x Failed\r\n", Type);
+                                    retFail++;
+                                }
+                            }
+                        }
+                    } else {
+                        log_error("Upgrade CCS open CAN FD fail.\n");
+                        //isPass = false;
+                        return FAIL;
+                    }
+
+                    if (retFail != 0) {
+                        break;
+                    } else {
+                        retSucc++;
+                    }
+                    //return isPass;
+#endif //0
+                    break;
+
+                case 0x10000006:
+                case 0x1000000D:
+                case 0x1000000E:
+                case 0x20000002:
+                case 0x10000014:
+                    // CSU_PRIMARY_CONTROLLER : 0x10000006
+                    target = 0x00;
+
+                    if (Type == 0x10000006) {
+                        target = UPGRADE_PRI;
+                    } else if (Type == 0x1000000D) {
+                        target = UPGRADE_RB;
+                    } else if (Type == 0x1000000E) {
+                        target = UPGRADE_FAN;
+                    } else if (Type == 0x20000002) {
+                        target = UPGRADE_AC;
+                    } else if (Type == 0x10000014) {
+                        target = UPGRADE_LED;
+                    }
+
+                    uartFd = InitComPort(target);
+
+                    if (Upgrade_UART(uartFd, Type, target, new_str, (char *)pSysConfig->ModelName) == PASS) {
+                        //return PASS;
+                        retSucc++;
+                    } else {
+                        log_info("Upgrade %x Failed\r\n", Type);
+                        //return FAIL;
+                        return FAIL;
+                    }
+
+                    if (uartFd > 0) {
+                        close(uartFd);
+                    }
+                    break;
+
+                case 0x1000000B:
+                case 0x1000000C:
+                    // CHAdeMO_BOARD : 0x1000000B, GBT : 0x1000000C
+                    //bool isPass = true;
+                    CanFd = InitCanBus();
+                    if (CanFd > 0) {
+                        for (index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+                            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+                            //if (!isPass) {
+                            //    break;
+                            //}
+
+                            if ((Type == 0x1000000B && pDcChargingInfo->Type == _Type_Chademo) ||
+                                    (Type == 0x1000000C && pDcChargingInfo->Type == _Type_GB)) {
+                                if (Upgrade_CAN(CanFd, Type, pDcChargingInfo->Evboard_id, new_str, (char *)pSysConfig->ModelName) == PASS) {
+                                    //isPass = PASS;
+                                    retSucc++;
+                                } else {
+                                    log_info("Upgrade %x Failed\r\n", Type);
+                                    //isPass = FAIL;
+                                    retFail++;
+                                }
+                            }
+                        }
+                    } else {
+                        log_info("Upgrad FD fail. \n");
+                        //isPass = false;
+                        return FAIL;
+                    }
+
+                    //return isPass;
+                    break;
+                }
+            }
+            free(new_str);
+            free(ptr);
+        }
+    }
+    free(dir);
+    closedir(d);
+
+    if (retFail != 0) {
+        return FAIL;
+    }
+
+    return PASS;
+}
+
+void CreateRfidFork()
+{
+    pid_t rfidRecPid;
+
+    rfidRecPid = fork();
+    log_info("CreateRfidFork = %d\r\n", rfidRecPid);
+    if (rfidRecPid == 0) {
+        while (true) {
+            // 刷卡判斷
+            RFID rfid;
+            if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_NO_CHARGING ||
+                    !pSysConfig->isRFID)
+            {}
+            else if (getRequestCardSN(rfidFd, 0, &rfid)) {
+                //log_info("Get Card..-%s- \n", pSysConfig->UserId);
+                if (strlen((char *)pSysConfig->UserId) == 0) {
+                    if (pSysConfig->RfidCardNumEndian == RFID_ENDIAN_LITTLE) {
+                        switch (rfid.snType) {
+                        case RFID_SN_TYPE_6BYTE:
+                            sprintf((char *) pSysConfig->UserId,
+                                    "%02X%02X%02X%02X%02X%02X",
+                                    rfid.currentCard[0], rfid.currentCard[1],
+                                    rfid.currentCard[2], rfid.currentCard[3],
+                                    rfid.currentCard[4], rfid.currentCard[5]);
+                            break;
+                        case RFID_SN_TYPE_7BYTE:
+                            sprintf((char *) pSysConfig->UserId,
+                                    "%02X%02X%02X%02X%02X%02X%02X",
+                                    rfid.currentCard[0], rfid.currentCard[1],
+                                    rfid.currentCard[2], rfid.currentCard[3],
+                                    rfid.currentCard[4], rfid.currentCard[5],
+                                    rfid.currentCard[6]);
+                            break;
+                        case RFID_SN_TYPE_10BYTE:
+                            sprintf((char *) pSysConfig->UserId,
+                                    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
+                                    rfid.currentCard[0], rfid.currentCard[1],
+                                    rfid.currentCard[2], rfid.currentCard[3],
+                                    rfid.currentCard[4], rfid.currentCard[5],
+                                    rfid.currentCard[6], rfid.currentCard[7],
+                                    rfid.currentCard[8], rfid.currentCard[9]);
+                            break;
+                        case RFID_SN_TYPE_4BYTE:
+                            sprintf((char *) pSysConfig->UserId,
+                                    "%02X%02X%02X%02X",
+                                    rfid.currentCard[0], rfid.currentCard[1],
+                                    rfid.currentCard[2], rfid.currentCard[3]);
+                            break;
+                        }
+                    } else if (pSysConfig->RfidCardNumEndian == RFID_ENDIAN_BIG) {
+                        switch (rfid.snType) {
+                        case RFID_SN_TYPE_6BYTE:
+                            sprintf((char *) pSysConfig->UserId,
+                                    "%02X%02X%02X%02X%02X%02X",
+                                    rfid.currentCard[5], rfid.currentCard[4],
+                                    rfid.currentCard[3], rfid.currentCard[2],
+                                    rfid.currentCard[1], rfid.currentCard[0]);
+                            break;
+                        case RFID_SN_TYPE_7BYTE:
+                            sprintf((char *) pSysConfig->UserId,
+                                    "%02X%02X%02X%02X%02X%02X%02X",
+                                    rfid.currentCard[6], rfid.currentCard[5],
+                                    rfid.currentCard[4], rfid.currentCard[3],
+                                    rfid.currentCard[2], rfid.currentCard[1],
+                                    rfid.currentCard[0]);
+                            break;
+                        case RFID_SN_TYPE_10BYTE:
+                            sprintf((char *) pSysConfig->UserId,
+                                    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
+                                    rfid.currentCard[9], rfid.currentCard[8],
+                                    rfid.currentCard[7], rfid.currentCard[6],
+                                    rfid.currentCard[5], rfid.currentCard[4],
+                                    rfid.currentCard[3], rfid.currentCard[2],
+                                    rfid.currentCard[1], rfid.currentCard[0]);
+                            break;
+                        case RFID_SN_TYPE_4BYTE:
+                            sprintf((char *) pSysConfig->UserId,
+                                    "%02X%02X%02X%02X",
+                                    rfid.currentCard[3], rfid.currentCard[2],
+                                    rfid.currentCard[1], rfid.currentCard[0]);
+                            break;
+                        }
+                    }
+                    log_info("card number = %s\n", pSysConfig->UserId);
+                }
+            }
+            usleep(500000);
+        }
+    }
+}
+#endif //0
+
+void StartSystemTimeoutDet(uint8_t flag)
+{
+    if (pSysInfo->SystemTimeoutFlag != flag) {
+        gettimeofday(&pSysInfo->SystemTimeoutTimer, NULL);
+    }
+    pSysInfo->SystemTimeoutFlag = flag;
+}
+
+void StopSystemTimeoutDet()
+{
+    gettimeofday(&pSysInfo->SystemTimeoutTimer, NULL);
+    pSysInfo->SystemTimeoutFlag = Timeout_None;
+}
+
+void StartGunInfoTimeoutDet(uint8_t gunIndex, uint8_t flag)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (gunIndex < pSysConfig->TotalConnectorCount) {
+        if (pDcChargingInfo->TimeoutFlag != flag) {
+            gettimeofday(&pDcChargingInfo->TimeoutTimer, NULL);
+        }
+        pDcChargingInfo->TimeoutFlag = flag;
+    }
+}
+
+void StopGunInfoTimeoutDet(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (gunIndex < pSysConfig->TotalConnectorCount) {
+        pDcChargingInfo->TimeoutFlag = Timeout_None;
+    }
+}
+
+void CheckConnectionTimeout(void)
+{
+#if defined DD360 || defined DD360Audi || defined DD360ComBox
+    if (gAudiCustInfo->RemoteSetup.ConnectionTimeout != 0) { //Jerry add
+        _connectionTimeout = gAudiCustInfo->RemoteSetup.ConnectionTimeout;
+    } else {
+        _connectionTimeout = CONN_PLUG_TIME_OUT;
+    }
+
+    return;
+#endif //defined DD360 || defined DD360Audi || defined DD360ComBox
+
+    if (system("pidof -s OcppBackend > /dev/null") != 0) {
+        _connectionTimeout = CONN_PLUG_TIME_OUT;
+    } else {
+        if (strcmp((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[ConnectionTimeOut].ItemData, "") != 0) {
+            _connectionTimeout = atoi((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[ConnectionTimeOut].ItemData);
+            if (_connectionTimeout <= 0) {
+                _connectionTimeout = CONN_PLUG_TIME_OUT;
+            }
+        } else {
+            _connectionTimeout = CONN_PLUG_TIME_OUT;
+        }
+    }
+}
+
+void CreateTimeoutFork()
+{
+    pid_t timeoutPid;
+
+    timeoutPid = fork();
+    log_info("CreateTimeoutFork = %d\r\n", timeoutPid);
+    if (timeoutPid == 0) {
+        gettimeofday(&_cmdSubPriority_time, NULL);
+        CheckConnectionTimeout();
+
+        while (1) {
+            if ((GetTimeoutValue(_cmdSubPriority_time) / 1000) > 5000) {
+                CheckConnectionTimeout();
+                gettimeofday(&_cmdSubPriority_time, NULL);
+            }
+
+            //printf("Timeout ***********SystemTimeoutFlag = %d, ********\n", pSysInfo->SystemTimeoutFlag);
+            // 系統
+            switch (pSysInfo->SystemTimeoutFlag) {
+            case Timeout_SelftestChk:
+                if (GetTimeoutValue(pSysInfo->SystemTimeoutTimer) / uSEC_VAL >= SELFTEST_TIMEOUT) {
+                    _SelfTestTimeout();
+                    StopSystemTimeoutDet();
+                    destroySelGun(DESTROY_ALL_SEL); //jerry add
+                }
+                break;
+
+            case Timeout_Authorizing:
+                if (GetTimeoutValue(pSysInfo->SystemTimeoutTimer) / uSEC_VAL >= AUTHORIZE_TIMEOUT) {
+                    _AuthorizedTimeout();
+                    StopSystemTimeoutDet();
+                    destroySelGun(pSysInfo->CurGunSelected);
+                    if (gAudiCustInfo->AuthorStateFromCabinet[pSysInfo->CurGunSelected] == YES) { //DoComm no ask cabinet balance
+                        gAudiCustInfo->AuthorStateFromCabinet[pSysInfo->CurGunSelected] = NO;
+                        pAlarmCode->AlarmEvents.bits.DisconnectedFromDo = ABNORMAL;
+                        log_error("Author timeout restart DoComm\r\n");
+                        system("killall Module_DoComm");
+                        sleep(1);
+                        system("/root/Module_DoComm &");
+                    }
+                }
+                break;
+
+            case Timeout_VerifyFail:
+                if (GetTimeoutValue(pSysInfo->SystemTimeoutTimer) / uSEC_VAL >= AUTHORIZE_FAIL_TIMEOUT) {
+                    _AutoReturnTimeout();
+                    StopSystemTimeoutDet();
+                    destroySelGun(pSysInfo->CurGunSelected);
+                    if (gAudiCustInfo->AuthorStateFromCabinet[pSysInfo->CurGunSelected] == YES) { //DoComm no ask cabinet balance
+                        gAudiCustInfo->AuthorStateFromCabinet[pSysInfo->CurGunSelected] = NO;
+                        pAlarmCode->AlarmEvents.bits.DisconnectedFromDo = ABNORMAL;
+                        log_error("Author timeout restart DoComm\r\n");
+                        system("killall Module_DoComm");
+                        sleep(1);
+                        system("/root/Module_DoComm &");
+                    }
+                }
+                break;
+
+            case Timeout_VerifyComp:
+                if (GetTimeoutValue(pSysInfo->SystemTimeoutTimer) / uSEC_VAL >= AUTHORIZE_COMP_TIMEOUT) {
+                    _AutoReturnTimeout();
+                    StopSystemTimeoutDet();
+                }
+                break;
+
+            case Timeout_WaitPlug:
+                if (GetTimeoutValue(pSysInfo->SystemTimeoutTimer) / uSEC_VAL >= _connectionTimeout) {
+                    _DetectPlugInTimeout();
+                    StopSystemTimeoutDet();
+                    destroySelGun(pSysInfo->CurGunSelected);
+                }
+                break;
+
+            case Timeout_ReturnToChargingGunDet:
+                if (GetTimeoutValue(pSysInfo->SystemTimeoutTimer) / uSEC_VAL >= RETURN_TO_CHARGING_PAGE) {
+#if defined DD360Audi
+                    if (getCurLcmPage() != _LCM_PRE_CHARGE &&
+                            getCurLcmPage() != _LCM_CHARGING &&
+                            getCurLcmPage() != _LCM_COMPLETE) {
+                        destroySelGun(pSysInfo->CurGunSelected); //jerry add
+
+                    }
+#endif //defined DD360Audi
+                    DisplayChargingInfo();
+                    StopSystemTimeoutDet();
+                }
+                break;
+
+            case Timeout_AuthorizingForStop:
+                if (GetTimeoutValue(pSysInfo->SystemTimeoutTimer) / uSEC_VAL >= AUTHORIZE_STOP_TIMEOUT) {
+                    strcpy((char *)pSysConfig->UserId, "");
+                    ClearAuthorizedFlag();
+                    StopSystemTimeoutDet();
+                }
+                break;
+
+            }
+            // 各槍
+            for (uint8_t gun_index = 0; gun_index < pSysConfig->TotalConnectorCount; gun_index++) {
+                pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun_index);
+
+                //printf("Timeout ***********TimeoutFlag = %d, ********\n", chargingInfo[gun_index]->TimeoutFlag);
+                switch (pDcChargingInfo->TimeoutFlag) {
+                case Timeout_Preparing:
+                    if (GetTimeoutValue(pDcChargingInfo->TimeoutTimer) / uSEC_VAL >= GUN_PREPARE_TIMEOUT) {
+                        _PrepareTimeout(gun_index);
+                        StopGunInfoTimeoutDet(gun_index);
+                        destroySelGun(gun_index); //jerry add
+                    }
+                    break;
+
+                case Timeout_EvChargingDet:
+                    if (GetTimeoutValue(pDcChargingInfo->TimeoutTimer) / uSEC_VAL >= GUN_EV_WAIT_TIMEOUT) {
+                        _DetectEvChargingEnableTimeout(gun_index);
+                        StopGunInfoTimeoutDet(gun_index);
+                        destroySelGun(gun_index); //jerry add
+                    }
+                    break;
+
+                case Timeout_EvseChargingDet:
+                    if (GetTimeoutValue(pDcChargingInfo->TimeoutTimer) / uSEC_VAL >= GUN_EVSE_WAIT_TIMEOUT) {
+                        _DetectEvseChargingEnableTimeout(gun_index);
+                        StopGunInfoTimeoutDet(gun_index);
+                        destroySelGun(gun_index); //jerry add
+                    }
+                    break;
+
+                case Timeout_EvseCompleteDet:
+                    if (GetTimeoutValue(pDcChargingInfo->TimeoutTimer) / uSEC_VAL >= GUN_COMP_WAIT_TIMEOUT) {
+                        StopGunInfoTimeoutDet(gun_index);
+                        destroySelGun(gun_index); //jerry add
+                    }
+                    break;
+
+                case Timeout_ForCcsPrechargeDet:
+                    if (GetTimeoutValue(pDcChargingInfo->TimeoutTimer) / uSEC_VAL >= GUN_PRECHARGING_TIMEOUT) {
+                        _CcsPrechargeTimeout(gun_index);
+                        StopGunInfoTimeoutDet(gun_index);
+                        destroySelGun(gun_index); //jerry add
+                    }
+                    break;
+
+                case Timeout_SelectGun: //Jerry add
+                    if (GetTimeoutValue(pDcChargingInfo->TimeoutTimer) / uSEC_VAL >= SEL_GUN_TIMEOUT) {
+                        log_info("Timeout_SelectGun\r\n");
+                        StopGunInfoTimeoutDet(gun_index);
+                        destroySelGun(gun_index); //jerry add
+                    }
+                    break;
+                }
+            }
+            sleep(1);
+        }
+    }
+}
+
+#if 0
+void GetSystemTime()
+{
+    struct timeb csuTime;
+    struct tm *tmCSU;
+
+    ftime(&csuTime);
+    tmCSU = localtime(&csuTime.time);
+    log_info("Time : %04d-%02d-%02d %02d:%02d:%02d \n", tmCSU->tm_year + 1900,
+             tmCSU->tm_mon + 1, tmCSU->tm_mday, tmCSU->tm_hour, tmCSU->tm_min,
+             tmCSU->tm_sec);
+
+//  uint8_t date[14];
+//
+//
+//       //sprintf(&date, "%d", );
+//
+//       date[0] = '0' + ((tmCSU->tm_year + 1900) / 1000 % 10);
+
+//  date[0] = (tmCSU->tm_year + 1900) / 1000 % 10;
+//  date[1] = (tmCSU->tm_year + 1900) / 100 % 10;
+//  date[2] = (tmCSU->tm_year + 1900) / 10 % 10;
+//  date[3] = (tmCSU->tm_year + 1900) / 1 % 10;
+//
+//  date[4] = (tmCSU->tm_mon + 1) / 10 % 10;
+//  date[5] = (tmCSU->tm_mon + 1) / 1 % 10;
+//
+//  date[6] = (tmCSU->tm_mday) / 10 % 10;
+//  date[7] = (tmCSU->tm_mday) / 1 % 10;
+//
+//  date[8] = (tmCSU->tm_hour) / 10 % 10;
+//  date[9] = (tmCSU->tm_hour) / 1 % 10;
+//
+//  date[10] = (tmCSU->tm_min) / 10 % 10;
+//  date[11] = (tmCSU->tm_min) / 1 % 10;
+//
+//  date[12] = (tmCSU->tm_sec) / 10 % 10;
+//  date[13] = (tmCSU->tm_sec) / 1 % 10;
+
+//  log_info("%x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x \n", date[0], date[1], date[2], date[3],
+//          date[4], date[5], date[6], date[7],
+//          date[8], date[9], date[10], date[11],
+//          date[12], date[13]);
+}
+#endif //0
+
+void CheckFactoryConfigFunction(void)
+{
+    char Buf[256] = {0};
+
+    if (pSysInfo->FactoryConfiguration) {
+        sprintf(Buf, "cd /root;./FactoryConfig -m %s %s",
+                pSysConfig->ModelName,
+                pSysConfig->SerialNumber);
+        system(Buf);
+
+        system("rm -f /Storage/OCPP/OCPPConfiguration");
+        system("sync");
+        sleep(5);
+        system("reboot -f");
+        sleep(5);
+        system("reboot -f");
+    }
+}
+
+#if 0
+void CheckFwUpdateFunction()
+{
+    //log_info("pSysInfo->FirmwareUpdate = %d \n", pSysInfo->FirmwareUpdate);
+    if (pSysInfo->FirmwareUpdate == YES) {
+        log_info("ftp : update start. \n");
+        for (uint8_t gun_index = 0; gun_index < pSysConfig->TotalConnectorCount; gun_index++) {
+            setChargerMode(gun_index, MODE_UPDATE);
+        }
+
+        uint8_t updateResult = CheckUpdateProcess();
+
+        if (updateResult == PASS) {
+            log_info("ftp : update complete. \n");
+        } else if (updateResult == MODELNAME_FAIL) {
+            log_info("ftp : model name is none match. \n");
+            KillAllTask();
+            pSysInfo->FirmwareUpdate = NO;
+            sleep(5);
+            system("/usr/bin/run_evse_restart.sh");
+            return;
+        } else {
+            log_info("ftp : update fail. \n");
+        }
+
+        pSysInfo->FirmwareUpdate = NO;
+        sleep(5);
+        system("reboot -f");
+    } else if (ShmOCPP16Data->MsMsg.bits.UpdateFirmwareReq == YES) {
+        ShmOCPP16Data->MsMsg.bits.UpdateFirmwareReq = NO;
+
+        if (strcmp((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "Downloaded") == EQUAL) {
+            log_info("Backend : update start. \n");
+            strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "");
+            strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "Installing");
+            ShmOCPP16Data->SpMsg.bits.FirmwareStatusNotificationReq = YES;
+            KillTask();
+
+            for (uint8_t _index = 0; _index < pSysConfig->TotalConnectorCount; _index++) {
+                setChargerMode(_index, MODE_UPDATE);
+            }
+
+            for (uint8_t _index = 0; _index < pSysConfig->AcConnectorCount; _index++) {
+                pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(_index);
+
+                pAcChargingInfo->SystemStatus = MODE_UPDATE;
+            }
+
+            uint8_t updateResult = CheckUpdateProcess();
+
+            if (updateResult == PASS) {
+                log_info("Backend : update complete. \n");
+                strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "Installed");
+            } else if (updateResult == MODELNAME_FAIL) {
+                log_info("Backend : model name is none match. \n");
+                KillAllTask();
+                strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "InstallationFailed");
+                ShmOCPP16Data->SpMsg.bits.FirmwareStatusNotificationReq = YES;
+                sleep(5);
+                system("/usr/bin/run_evse_restart.sh");
+                return;
+            } else {
+                log_info("Backend : update fail. \n");
+                strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "InstallationFailed");
+            }
+
+            strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "Installed");
+            ShmOCPP16Data->SpMsg.bits.FirmwareStatusNotificationReq = YES;
+            sleep(5);
+            system("reboot -f");
+        }
+    }
+}
+#endif //0
+
+//===============================================
+// Check reservation date is expired
+//===============================================
+int isReservationExpired(uint8_t gun_index)
+{
+    int result = NO;
+    struct tm expiredDate;
+    struct timeb expiredTime;
+
+    if (sscanf((char *) ShmOCPP16Data->ReserveNow[gun_index].ExpiryDate,
+               "%4d-%2d-%2dT%2d:%2d:%2d", &expiredDate.tm_year,
+               &expiredDate.tm_mon, &expiredDate.tm_mday, &expiredDate.tm_hour,
+               &expiredDate.tm_min, &expiredDate.tm_sec) == 6) {
+        expiredDate.tm_year -= 1900;
+        expiredDate.tm_mon -= 1;
+
+        expiredTime.time = mktime(&expiredDate);
+        if (!CheckTimeOut(expiredTime)) {
+            result = YES;
+        }
+    }
+
+    return result;
+}
+
+//===============================================
+// OCPP
+//===============================================
+void CheckOcppStatus(void)
+{
+    bool canReset = true;
+    //bool canHardReset = true; //DS60-120 add
+
+    if (ShmOCPP16Data->SpMsg.bits.BootNotificationConf == YES) {
+        ShmOCPP16Data->SpMsg.bits.BootNotificationConf = NO;
+    }
+
+    if (ShmOCPP16Data->MsMsg.bits.ResetReq == YES) {
+        if (pSysWarning->Level != 2) {
+            for (uint8_t _index = 0; _index < pSysConfig->TotalConnectorCount; _index++) {
+                pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_index);
+
+                if (pDcChargingInfo->SystemStatus != S_IDLE &&
+                        pDcChargingInfo->SystemStatus != S_RESERVATION &&
+                        pDcChargingInfo->SystemStatus != S_MAINTAIN) {
+                    canReset = false;
+                    if (pDcChargingInfo->SystemStatus >= S_REASSIGN &&
+                            pDcChargingInfo->SystemStatus < S_TERMINATING) {
+                        //canHardReset = false;
+                        ChargingTerminalProcess(_index);
+                        //restartFlag = 1;
+                    }
+                }
+            }
+        }
+
+        if (canReset) {
+            ShmOCPP16Data->MsMsg.bits.ResetReq = NO;
+            sprintf((char *)ShmOCPP16Data->Reset.ResponseStatus, "Accepted");
+            if (strcmp((char *)ShmOCPP16Data->Reset.Type, "Hard") == EQUAL) {
+                log_error("****** Hard Reboot ****** \n");
+                ShmOCPP16Data->MsMsg.bits.ResetConf = YES;
+                sleep(3);
+                system("reboot -f");
+            } else if (strcmp((char *)ShmOCPP16Data->Reset.Type, "Soft") == EQUAL) {
+                log_error("****** Soft Reboot ****** \n");
+                ShmOCPP16Data->MsMsg.bits.ResetConf = YES;
+                sleep(3);
+                system("killall OcppBackend &");
+                KillAllTask();
+                system("/usr/bin/run_evse_restart.sh");
+            }
+        }
+    }
+}
+
+void OcppStartTransation(uint8_t gunIndex)
+{
+    uint8_t _OcppGunIndex = gunIndex;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    // 如果有 AC 槍,而現在是 DC 第二把槍進入充電
+    if (pSysConfig->AcConnectorCount == 1 && gunIndex == 1) {
+        _OcppGunIndex = 2;
+    }
+
+    if (strcmp((char *)pDcChargingInfo->StartUserId, "") == EQUAL) {
+        strcpy((char *)ShmOCPP16Data->StartTransaction[_OcppGunIndex].IdTag, (char *)ShmOCPP16Data->StartTransaction[_OcppGunIndex].IdTag);
+    } else {
+        strcpy((char *)ShmOCPP16Data->StartTransaction[_OcppGunIndex].IdTag, (char *)pDcChargingInfo->StartUserId);
+    }
+
+    log_info("IdTag = %s \n", ShmOCPP16Data->StartTransaction[_OcppGunIndex].IdTag);
+    ShmOCPP16Data->CpMsg.bits[_OcppGunIndex].StartTransactionReq = YES;
+}
+
+void OcppStopTransation(uint8_t gunIndex)
+{
+    uint8_t _OcppGunIndex = gunIndex;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    // 如果有 AC 槍,而現在是 DC 第二把槍進入充電
+    if (pSysConfig->AcConnectorCount == 1 && gunIndex == 1) {
+        _OcppGunIndex = 2;
+    }
+
+    if (strcmp((char *)pDcChargingInfo->StartUserId, "") == EQUAL) {
+        strcpy((char *)ShmOCPP16Data->StopTransaction[_OcppGunIndex].IdTag, (char *)ShmOCPP16Data->StopTransaction[_OcppGunIndex].IdTag);
+    } else {
+        strcpy((char *)ShmOCPP16Data->StopTransaction[_OcppGunIndex].IdTag, (char *)pDcChargingInfo->StartUserId);
+    }
+
+    log_info("IdTag = %s \n", ShmOCPP16Data->StopTransaction[_OcppGunIndex].IdTag);
+    ShmOCPP16Data->CpMsg.bits[_OcppGunIndex].StopTransactionReq = YES;
+}
+
+bool OcppRemoteStop(uint8_t gunIndex)
+{
+    uint8_t acDirIndex = pSysConfig->AcConnectorCount;
+
+    // 有 AC 槍的話
+    if (acDirIndex > 0 && gunIndex > 0) {
+        gunIndex += acDirIndex;
+    }
+
+    bool result = ShmOCPP16Data->CsMsg.bits[gunIndex].RemoteStopTransactionReq;
+
+    if (ShmOCPP16Data->CsMsg.bits[gunIndex].RemoteStopTransactionReq == YES) {
+        strcpy((char *)ShmOCPP16Data->StopTransaction[gunIndex].StopReason, "Remote");
+        ShmOCPP16Data->CsMsg.bits[gunIndex].RemoteStopTransactionReq = NO;
+    }
+
+    return result;
+}
+
+bool WifiScheduleStop(uint8_t gunIndex)
+{
+    bool result = false;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    result = pDcChargingInfo->schedule.isTriggerStop;
+    pDcChargingInfo->schedule.isTriggerStop = NO;
+
+    return result;
+}
+
+void OcppRemoteStartChk()
+{
+    if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_NO_CHARGING)
+    {}
+    else if (!isDetectPlugin()) {
+        // 如果有 AC 槍,則固定是第 2 把槍,所以索引固定為 1
+        uint8_t acDirIndex = pSysConfig->AcConnectorCount;
+
+        for (uint8_t ac_index = 0; ac_index < pSysConfig->AcConnectorCount; ac_index++) {
+            pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(ac_index);
+
+            if (ShmOCPP16Data->CsMsg.bits[acDirIndex].RemoteStartTransactionReq == YES) {
+                if (pAcChargingInfo->SystemStatus == S_IDLE ||
+                        pAcChargingInfo->SystemStatus == S_RESERVATION) {
+                    ShmOCPP16Data->CsMsg.bits[acDirIndex].RemoteStartTransactionReq = NO;
+                    pAcChargingInfo->RemoteStartFlag = YES;
+                    pSysInfo->OrderCharging = YES;
+                    //pSysInfo->OrderCharging = DEFAULT_AC_INDEX;
+                    ShmOCPP16Data->CsMsg.bits[pSysConfig->TotalConnectorCount + ac_index].RemoteStartTransactionReq = NO;
+                    DetectPluginStart();
+                    return;
+                }
+                ShmOCPP16Data->CsMsg.bits[acDirIndex].RemoteStartTransactionReq = NO;
+            }
+        }
+
+        uint8_t threeGunIndex = 0;
+        uint8_t dcIndex = 0;
+        bool isGunUsingStatus = false;
+
+        for (uint8_t _index = 0; _index < pSysConfig->TotalConnectorCount; _index++) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_index);
+
+            // 如果有 AC 槍,且 DC 槍也有兩把
+            if (acDirIndex == 1 && _index == 1) {
+                threeGunIndex = 1;
+            }
+
+            if (ShmOCPP16Data->CsMsg.bits[_index + threeGunIndex].RemoteStartTransactionReq == YES) {
+                dcIndex = _index;
+            }
+
+            if (pDcChargingInfo->SystemStatus != S_IDLE) {
+                isGunUsingStatus = true;
+            }
+        }
+
+        // 如果是雙槍單模,只認閒置狀態的槍,如果有預約~ 則預約也算被使用
+        if (isGunUsingStatus && pSysInfo->IsAlternatvieConf) {
+            if (dcIndex == 0) {
+                threeGunIndex = 0;
+            }
+
+            ShmOCPP16Data->CsMsg.bits[dcIndex + threeGunIndex].RemoteStartTransactionReq = NO;
+            return;
+        }
+
+        if (dcIndex == 0) {
+            threeGunIndex = 0;
+        }
+
+        pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(dcIndex);
+
+        if (ShmOCPP16Data->CsMsg.bits[dcIndex + threeGunIndex].RemoteStartTransactionReq == YES) {
+            if (pDcChargingInfo->SystemStatus == S_IDLE ||
+                    pDcChargingInfo->SystemStatus == S_RESERVATION) {
+                pDcChargingInfo->RemoteStartFlag = YES;
+                pSysInfo->OrderCharging = YES;
+                //pSysInfo->OrderCharging = gun_index;
+                ShmOCPP16Data->CsMsg.bits[dcIndex + threeGunIndex].RemoteStartTransactionReq = NO;
+                DetectPluginStart();
+#if defined DD360Audi
+                setSelGunWaitToAuthor(dcIndex); //Jerry add
+#endif //defined DD360Audi
+            }
+            ShmOCPP16Data->CsMsg.bits[dcIndex + threeGunIndex].RemoteStartTransactionReq = NO;
+        }
+    }
+}
+
+void ChkOcppStatus(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (pDcChargingInfo->SystemStatus == S_IDLE &&
+            ShmOCPP16Data->CsMsg.bits[gunIndex].ReserveNowReq == YES) {
+        ShmOCPP16Data->CsMsg.bits[gunIndex].ReserveNowReq = NO;
+        if (isReservationExpired(gunIndex)) {
+            log_info("***************ChkOcppStatus : OcppReservedStatus******************** \n");
+            log_error("***************ChkOcppStatus : OcppReservedStatus******************** \n");
+            pDcChargingInfo->ReservationId = ShmOCPP16Data->ReserveNow[gunIndex].ReservationId;
+            pDcChargingInfo->SystemStatus = S_RESERVATION;
+        }
+        ShmOCPP16Data->CsMsg.bits[gunIndex].ReserveNowConf = YES;
+    }
+
+    if (pDcChargingInfo->SystemStatus == S_RESERVATION &&
+            ShmOCPP16Data->CsMsg.bits[gunIndex].CancelReservationReq == YES) {
+        ShmOCPP16Data->CsMsg.bits[gunIndex].CancelReservationReq = NO;
+        if (isReservationExpired(gunIndex)) {
+            log_info("***************ChkOcppStatus : Cancel OcppReservedStatus******************** \n");
+            log_error("***************ChkOcppStatus : Cancel OcppReservedStatus******************** \n");
+            pDcChargingInfo->ReservationId = 0;
+            pDcChargingInfo->SystemStatus = S_IDLE;
+        }
+        ShmOCPP16Data->CsMsg.bits[gunIndex].CancelReservationConf = YES;
+    }
+
+    if (ShmOCPP16Data->CsMsg.bits[gunIndex].ChangeAvailabilityReq == YES) {
+        log_info("***************ChkOcppStatus : OcppChangeAvailability******************** \n");
+        log_error("***************ChkOcppStatus : OcppChangeAvailability******************** \n");
+        ShmOCPP16Data->CsMsg.bits[gunIndex].ChangeAvailabilityReq = NO;
+        if (strcmp((char *)ShmOCPP16Data->ChangeAvailability[gunIndex].Type, "Operative") == EQUAL) {
+            if (isDb_ready) {
+                DB_Update_Operactive(gunIndex, true);
+            }
+
+            pDcChargingInfo->IsAvailable = YES;
+            if (pDcChargingInfo->SystemStatus == S_IDLE ||
+                    pDcChargingInfo->SystemStatus == S_RESERVATION ||
+                    pDcChargingInfo->SystemStatus == S_MAINTAIN) {
+                setChargerMode(gunIndex, MODE_IDLE);
+            }
+        } else if (strcmp((char *)ShmOCPP16Data->ChangeAvailability[gunIndex].Type, "Inoperative") == EQUAL) {
+            if (isDb_ready) {
+                DB_Update_Operactive(gunIndex, false);
+            }
+
+            pDcChargingInfo->IsAvailable = NO;
+            if (pDcChargingInfo->SystemStatus == S_IDLE ||
+                    pDcChargingInfo->SystemStatus == S_RESERVATION ||
+                    pDcChargingInfo->SystemStatus == S_MAINTAIN) {
+                setChargerMode(gunIndex, MODE_MAINTAIN);
+            }
+        }
+    }
+
+    if (ShmOCPP16Data->CsMsg.bits[gunIndex].UnlockConnectorReq == YES) {
+        ShmOCPP16Data->CsMsg.bits[gunIndex].UnlockConnectorReq = NO;
+        if (pDcChargingInfo->SystemStatus >= S_REASSIGN_CHECK && // DS60-120 add ||
+                pDcChargingInfo->SystemStatus <= S_CHARGING) {
+            // 充電中,需停止充電
+            strcpy((char *)ShmOCPP16Data->StopTransaction[gunIndex].StopReason, "UnlockCommand");
+            ChargingTerminalProcess(gunIndex);
+        }
+        strcpy((char *)ShmOCPP16Data->UnlockConnector[gunIndex].ResponseStatus, "Unlocked");
+        ShmOCPP16Data->CsMsg.bits[gunIndex].UnlockConnectorConf = YES;
+    }
+}
+
+bool CheckBackendChargingTimeout(uint8_t gunIndex)
+{
+    bool result = false;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (pSysConfig->AuthorisationMode == AUTH_MODE_ENABLE) {
+        if (pSysConfig->MaxChargingDuration > 0) {
+            if (pDcChargingInfo->PresentChargedDuration > (pSysConfig->MaxChargingDuration * 60)) {
+                result = true;
+            }
+        }
+    } else if (pSysConfig->AuthorisationMode == AUTH_MODE_DISABLE) {
+        // 隨插即充電的要看 offline
+        if (pSysConfig->OfflineMaxChargeDuration > 0) {
+            if (pDcChargingInfo->PresentChargedDuration > (pSysConfig->OfflineMaxChargeDuration * 60)) {
+                result = true;
+            }
+        }
+    }
+
+    return result;
+}
+
+bool CheckBackendChargingEnergy(uint8_t gunIndex)
+{
+    bool result = false;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (pSysConfig->AuthorisationMode == AUTH_MODE_ENABLE) {
+        if (pSysConfig->MaxChargingEnergy > 0) {
+            if (pDcChargingInfo->PresentChargedEnergy > pSysConfig->MaxChargingEnergy) {
+                result = true;
+            }
+        }
+    } else if (pSysConfig->AuthorisationMode == AUTH_MODE_DISABLE) {
+        // 隨插即充電的要看 offline
+        if (pSysConfig->OfflineMaxChargeEnergy > 0) {
+            if (pDcChargingInfo->PresentChargedEnergy > (pSysConfig->OfflineMaxChargeEnergy)) {
+                result = true;
+            }
+        }
+    }
+
+    return result;
+}
+
+void InformOcppErrOccur(uint8_t codeType)
+{
+    char _error[25];
+
+    switch (codeType) {
+    case 4: strcpy(_error, "InternalError"); break;
+    case 6: strcpy(_error, "NoError"); break;
+    case 7: strcpy(_error, "OtherError"); break;
+    case 13: strcpy(_error, "UnderVoltage"); break;
+    case 14: strcpy(_error, "OverVoltage"); break;
+    }
+
+    for (uint8_t gun_index = 0; gun_index < pSysConfig->TotalConnectorCount; gun_index++) {
+        strcpy((char *)ShmOCPP16Data->StatusNotification[gun_index].ErrorCode, _error);
+    }
+}
+
+#if 0
+//===============================================
+// SQLite3 related routine
+//===============================================
+int DB_Open(sqlite3 *db)
+{
+    int result = PASS;
+    char *errMsg = NULL;
+    char *createRecordSql = "CREATE TABLE IF NOT EXISTS charging_record("
+                            "idx integer primary key AUTOINCREMENT, "
+                            "reservationId text, "
+                            "transactionId text, "
+                            "startMethod text, "
+                            "userId text, "
+                            "dateTimeStart text, "
+                            "dateTimeStop text,"
+                            "socStart text, "
+                            "socStop text, "
+                            "chargeEnergy text, "
+                            "stopReason text"
+                            ");";
+
+    /*char *createCfgSql = "CREATE TABLE IF NOT EXISTS `config` ( "
+                         "`idx` INTEGER PRIMARY KEY AUTOINCREMENT, "
+                         "`IsAvailable` TEXT NOT NULL, "
+                         "`connector` INTEGER NOT NULL, "
+                         "`val` TEXT NOT NULL, unique(IsAvailable,connector) on conflict replace);";
+    */
+    //DS60-120 add
+    char *createCfgSql = "CREATE TABLE IF NOT EXISTS `config` ( "
+                         "`idx` INTEGER PRIMARY KEY AUTOINCREMENT, "
+                         "`item` TEXT NOT NULL, "
+                         "`connector` INTEGER NOT NULL, "
+                         "`val` TEXT NOT NULL, unique(item,connector) on conflict replace);";
+
+    char *createrecordSql = "CREATE TABLE IF NOT EXISTS `event_record` ( "
+                            "`idx` INTEGER PRIMARY KEY AUTOINCREMENT, "
+                            "`occurDatetime` TEXT NOT NULL, "
+                            "`statusCode` TEXT NOT NULL, unique(occurDatetime,statusCode) on conflict replace);";
+
+    char *createrebootSql = "CREATE TABLE IF NOT EXISTS `reboot_record` ( "
+                            "`idx` INTEGER PRIMARY KEY AUTOINCREMENT, "
+                            "`rebootDatetime` TEXT NOT NULL, unique(rebootDatetime) on conflict replace);";
+
+    if (sqlite3_open(DB_FILE, &db)) {
+        result = FAIL;
+        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(db));
+        sqlite3_close(db);
+    } else {
+        log_info( "Local charging record database open successfully.\r\n");
+
+        if (sqlite3_exec(db, createRecordSql, 0, 0, &errMsg) != SQLITE_OK) {
+            result = FAIL;
+            log_info( "Create local charging record table error message: %s\n", errMsg);
+        } else {
+            log_info( "Opened local charging record table successfully\n");
+        }
+
+        if (sqlite3_exec(db, createCfgSql, 0, 0, &errMsg) != SQLITE_OK) {
+            result = FAIL;
+            log_info( "Create local config table error message: %s\n", errMsg);
+        } else {
+            log_info( "Opened local config table successfully\n");
+        }
+
+        //DS60-120
+        if (sqlite3_exec(db, createrecordSql, 0, 0, &errMsg) != SQLITE_OK) {
+            result = FAIL;
+            log_info( "Create local record table error message: %s\n", errMsg);
+        } else {
+            log_info( "Opened local record table successfully\n");
+        }
+
+        if (sqlite3_exec(db, createrebootSql, 0, 0, &errMsg) != SQLITE_OK) {
+            result = FAIL;
+            log_info( "Create reboot record table error message: %s\n", errMsg);
+        } else {
+            log_info( "Opened reboot record table successfully\n");
+        }
+        //-----
+
+        sqlite3_close(db);
+    }
+
+    return result;
+}
+
+int DB_Insert_Record(sqlite3 *db, int gun_index)
+{
+    int result = PASS;
+    char *errMsg = NULL;
+    char insertSql[1024];
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun_index);
+
+    sprintf(insertSql, "insert into charging_record(reservationId, transactionId, startMethod, userId, dateTimeStart, dateTimeStop, socStart, socStop, chargeEnergy, stopReason) "
+            "values('%d', '%d', '%d', '%s', '%s', '%s', '%d', '%d', '%f', '%s');",
+            pDcChargingInfo->ReservationId, //DS60-120 add
+            ShmOCPP16Data->StartTransaction[gun_index].ResponseTransactionId,
+            pDcChargingInfo->StartMethod,
+            pDcChargingInfo->StartUserId,
+            pDcChargingInfo->StartDateTime,
+            pDcChargingInfo->StopDateTime,
+            pDcChargingInfo->EvBatteryStartSoc,
+            pDcChargingInfo->EvBatterySoc,
+            pDcChargingInfo->PresentChargedEnergy,
+            //DS60-120 remove
+            //pSysInfo->AcChargingData[gun_index].ReservationId,
+            //ShmOCPP16Data->StartTransaction[gun_index].ResponseTransactionId,
+            //pSysInfo->AcChargingData[gun_index].StartMethod,
+            //pSysInfo->AcChargingData[gun_index].StartUserId,
+            //pSysInfo->AcChargingData[gun_index].StartDateTime,
+            //pSysInfo->AcChargingData[gun_index].StopDateTime,
+            //pSysInfo->AcChargingData[gun_index].EvBatterySoc,
+            //pSysInfo->AcChargingData[gun_index].EvBatterySoc,
+            //pSysInfo->AcChargingData[gun_index].PresentChargedEnergy,
+            ShmOCPP16Data->StopTransaction[gun_index].StopReason);
+
+    //if (sqlite3_open("/Storage/ChargeLog/localCgargingRecord.db", &db)) {
+    if (sqlite3_open(DB_FILE, &db)) { //DS60-120 add
+        result = FAIL;
+        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(db));
+        sqlite3_close(db);
+    } else {
+        log_info( "Local charging record database open successfully.\r\n");
+        if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
+            result = FAIL;
+            log_info( "Insert local charging record error message: %s\n", errMsg);
+        } else {
+            log_info( "Insert local charging record successfully\n");
+        }
+
+        //DS60-120 add
+        sprintf(insertSql, "delete from charging_record where idx < (select idx from charging_record order by idx desc limit 1)-2000;");
+        if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
+            result = FAIL;
+            log_info( "delete local charging error message: %s\n", errMsg);
+        } else {
+            log_info( "delete local charging record successfully\n");
+        }
+
+        sqlite3_close(db);
+    }
+
+    return result;
+}
+
+int DB_Update_Operactive(sqlite3 *db, uint8_t gun_index, uint8_t IsAvailable)
+{
+    uint8_t result = false;
+    char *errMsg = NULL;
+    char sqlStr[1024];
+    srand(time(NULL));
+
+    if (sqlite3_open(DB_FILE, &db)) {
+        result = FAIL;
+        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(db));
+        sqlite3_close(db);
+    } else {
+        log_info( "Local charging record database open successfully (%d).\r\n", IsAvailable);
+
+        //sprintf(sqlStr, "insert or replace into config (IsAvailable, connector, val) values('IsAvailable', %d, %d);", gun_index, IsAvailable);
+        sprintf(sqlStr, "insert or replace into config (item, connector, val) values('IsAvailable', %d, %d);", gun_index, IsAvailable); //DS60-120 add
+        log_info("sqlStr= %s\r\n", sqlStr);
+        if (sqlite3_exec(db, sqlStr, 0, 0, &errMsg) != SQLITE_OK) {
+            result = FAIL;
+            log_info( "update config error message: %s\n", errMsg);
+        } else {
+            log_info("update connector-%d config item isOperactive to %d\r\n", gun_index, IsAvailable);
+        }
+
+        sqlite3_close(db);
+    }
+
+    return result;
+}
+
+int DB_Get_Operactive(sqlite3 *db, uint8_t gun_index)
+{
+    uint8_t result = true;
+    char *errMsg = NULL;
+    char sqlStr[1024];
+    char **rs;
+    int  rows, cols;
+
+    //sprintf(sqlStr, "select * from config where IsAvailable='IsAvailable' and connector=%d;", gun_index);
+    sprintf(sqlStr, "select * from config where item='IsAvailable' and connector=%d;", gun_index); //DS60-120 add
+    //DEBUG_INFO("sqlStr= %s\r\n", sqlStr);
+
+    if (sqlite3_open(DB_FILE, &db)) {
+        result = FAIL;
+        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(db));
+        sqlite3_close(db);
+    } else {
+        log_info( "Local config query database open successfully.\r\n");
+        sqlite3_get_table(db, sqlStr, &rs, &rows, &cols, &errMsg);
+        if (rows > 0) {
+            for (int idxRow = 1; idxRow <= rows; idxRow++) {
+                if (strcmp(rs[(idxRow * cols) + 3], "0") == 0) {
+                    result = false;
+                }
+                log_info("Query connector-%d isOperactive: %s\r\n", gun_index, rs[(idxRow * cols) + 3]);
+            }
+        } else {
+            log_info("Query connector-%d fail, set default value to operactive.\r\n", gun_index);
+        }
+
+        sqlite3_free_table(rs);
+        sqlite3_close(db);
+    }
+
+    return result;
+}
+
+int DB_Reboot_Record(sqlite3 *db)
+{
+    int result = PASS;
+    char *errMsg = NULL;
+    char insertSql[256];
+
+    sprintf(insertSql, "insert into reboot_record(rebootDatetime) values(CURRENT_TIMESTAMP);");
+
+    if (sqlite3_open(DB_FILE, &db)) {
+        result = FAIL;
+        log_info( "Can't open database: %s\n", sqlite3_errmsg(db));
+        sqlite3_close(db);
+    } else {
+        log_info( "Local charging record database open successfully.\n");
+        if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
+            result = FAIL;
+            log_info( "Insert reboot record error message: %s\n", errMsg);
+        } else {
+            log_info( "Insert reboot record successfully\n");
+        }
+
+        sprintf(insertSql, "delete from reboot_record where idx < (select idx from charging_record order by idx desc limit 1)-2000;");
+        if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
+            result = FAIL;
+            log_info( "delete reboot record error message: %s\n", errMsg);
+        } else {
+            log_info( "delete reboot record successfully\n");
+        }
+
+        sqlite3_close(db);
+    }
+
+    return result;
+}
+#endif //0
+
+//===============================================
+// Config process
+//===============================================
+void AddPlugInTimes(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (pDcChargingInfo->Type == _Type_Chademo) {
+        pSysConfig->ChademoPlugInTimes += 1;
+    } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+        pSysConfig->Ccs2PlugInTimes += 1;
+    } else if (pDcChargingInfo->Type == _Type_GB) {
+        pSysConfig->GbPlugInTimes += 1;
+    }
+}
+
+void ChangeStartOrStopDateTime(uint8_t isStart, uint8_t gunIndex)
+{
+    char cmdBuf[32];
+    struct timeb csuTime;
+    struct tm *tmCSU;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    ftime(&csuTime);
+    tmCSU = localtime(&csuTime.time);
+
+    sprintf(cmdBuf, "%04d-%02d-%02d %02d:%02d:%02d", tmCSU->tm_year + 1900,
+            tmCSU->tm_mon + 1, tmCSU->tm_mday, tmCSU->tm_hour, tmCSU->tm_min,
+            tmCSU->tm_sec);
+    if (isStart) {
+        strcpy((char *)pDcChargingInfo->StartDateTime, cmdBuf);
+    } else {
+        strcpy((char *)pDcChargingInfo->StopDateTime, cmdBuf);
+    }
+}
+
+#if 0
+void zipLogFiles()
+{
+    const char *logPath = "/Storage/SystemLog";
+    // 獲取目錄
+    DIR *pDir = opendir(logPath);
+    if (pDir != NULL) {
+        struct timeb csuTime;
+        struct tm *tmCSU;
+
+        ftime(&csuTime);
+        tmCSU = localtime(&csuTime.time);
+//      log_info("Time : %04d-%02d-%02d %02d:%02d:%02d \n", tmCSU->tm_year + 1900,
+//          tmCSU->tm_mon + 1, tmCSU->tm_mday, tmCSU->tm_hour, tmCSU->tm_min,
+//          tmCSU->tm_sec);
+
+        // Read items inside the folder
+        struct dirent *pEntry = NULL;
+        while ((pEntry = readdir(pDir)) != NULL) {
+            if (strcmp(pEntry->d_name, ".") != 0 &&
+                    strcmp(pEntry->d_name, "..") != 0 &&
+                    strncmp(pEntry->d_name, "[", 1) == 0 &&
+                    strstr(pEntry->d_name, "tar") < 0) {
+                char yearC[5];
+                unsigned short year = 0;
+                char monthC[3];
+                unsigned short month = 0;
+
+                yearC[4] = '\0';
+                strncpy(yearC, pEntry->d_name + 1, 4);
+                monthC[2] = '\0';
+                strncpy(monthC, pEntry->d_name + 6, 2);
+
+                year = atoi(yearC);
+                month = atoi(monthC);
+
+                if (year != 0) {
+                    if (year < tmCSU->tm_year + 1900 ||
+                            (year >= tmCSU->tm_year + 1900 && month < tmCSU->tm_mon + 1)) {
+                        log_info("tar file name : %s \n", pEntry->d_name);
+                        char file[256];
+
+                        memset(file, 0x00, sizeof(file));
+                        strcat(file, "tar zcvf ");
+                        strcat(file, logPath);
+                        strncat(file, "/", 1);
+                        strcat(file, pEntry->d_name);
+                        strcat(file, ".tar");
+                        strncat(file, " ", 1);
+                        strcat(file, logPath);
+                        strncat(file, "/", 1);
+                        strcat(file, pEntry->d_name);
+                        log_info("zip = %s \n", file);
+                        system(file);
+                    }
+                }
+            }
+        }
+    }
+    // Close folder
+    closedir(pDir);
+}
+#endif //0
+
+void ChangeGunSelectByIndex(uint8_t sel)
+{
+    pSysInfo->CurGunSelected = sel;
+    pSysInfo->CurGunSelectedByAc = NO_DEFINE;
+}
+
+void CheckIsAlternatvieByModelName()
+{
+    // 黑白機 ?
+    /*if (strcmp((char *)pSysConfig->ModelName, "DWWU301J0UT1PH") == EQUAL ||
+            strcmp((char *)pSysConfig->ModelName, "DWYE301J0ET1PH") == EQUAL ||
+            strcmp((char *)pSysConfig->ModelName, "DSYE301J3EW2PH") == EQUAL ||
+            strcmp((char *)pSysConfig->ModelName, "DWYC301J0UW1PH") == EQUAL) {
+      */
+    if (pSysConfig->ModelName[1] == 'W') { //DS60-120
+        // 壁掛
+        pSysInfo->IsAlternatvieConf = YES;
+    } else {
+        pSysInfo->IsAlternatvieConf = NO;
+    }
+}
+
+void StopProcessingLoop()
+{
+    for (;;) {
+        CheckFactoryConfigFunction();
+        CheckFwUpdateFunction();
+        if (pSysWarning->Level == 2) {
+            ChkPrimaryStatus();
+            if (pSysWarning->Level == 0) {
+                log_info("Soft reboot for retry self-tets (Primary). \n");
+                KillAllTask();
+                sleep(3);
+                system("/usr/bin/run_evse_restart.sh");
+                return;
+            }
+        }
+        sleep(1);
+    }
+}
+
+#if 0
+int InitWatchDog(void)
+{
+    int fd;
+    system("/usr/bin/fuser -k /dev/watchdog");
+    sleep(1);
+    system("echo V > /dev/watchdog");
+    sleep(1);
+    fd = open("/dev/watchdog", O_RDWR);
+
+    if (fd <= 0) {
+        log_error("System watch dog initial fail.\r\n");
+    }
+    return fd;
+}
+
+void CreateWatchdog(void)
+{
+    if (pSysConfig->SwitchDebugFlag == NO) {
+        wtdFd = InitWatchDog();
+
+        if (wtdFd < 0) {
+            pAlarmCode->AlarmEvents.bits.CsuInitFailed = 1;
+        }
+    }
+}
+#endif //0
+
+bool IsConnectorWholeIdle()
+{
+    bool result = true;
+
+    for (uint8_t count = 0; count < pSysConfig->TotalConnectorCount; count++) {
+        pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(count);
+
+        if (pDcChargingInfo->SystemStatus != S_IDLE &&
+                pDcChargingInfo->SystemStatus != S_RESERVATION) {
+            result = false;
+            break;
+        }
+    }
+
+    for (uint8_t count = 0; count < pSysConfig->AcConnectorCount; count++) {
+        pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(count);
+
+        if (pAcChargingInfo->SystemStatus != S_IDLE &&
+                pAcChargingInfo->IsErrorOccur == NO) {
+            result = false;
+            break;
+        }
+    }
+
+    return result;
+}
+
+void ClearAlarmCodeWhenAcOff()
+{
+    if (!pSysInfo->AcContactorStatus) {
+        pAlarmCode->AlarmEvents.bits.PsuNoResource = NO;
+    }
+}
+
+//==========================================
+// Check task processing
+//==========================================
+void CheckTask()
+{
+    /*+++ 20200908, vern, disable it for DD360 +++*/
+#if 0
+    if (pSysConfig->ModelName[10] == 'T') {
+        if (system("pidof -s Module_4g > /dev/null") != 0) {
+            log_error("Module_4g not running, restart it.\r\n");
+            system("/root/Module_4g &");
+        }
+    } else if (pSysConfig->ModelName[10] == 'W') {
+        if (system("pidof -s Module_Wifi > /dev/null") != 0) {
+            log_error("Module_Wifi not running, restart it.\r\n");
+            system("/root/Module_Wifi &");
+        }
+    }
+
+    if (strcmp((char *)pSysConfig->OcppServerURL, "") != EQUAL &&
+            strcmp((char *)pSysConfig->ChargeBoxId, "") != EQUAL) {
+        if (system("pidof -s OcppBackend > /dev/null") != 0) {
+            log_error("OcppBackend not running, restart it.\r\n");
+            system("/root/OcppBackend &");
+        }
+    }
+#endif
+    /*--- 20200908, vern, disable it for DD360 ---*/
+    if (system("pidof -s Module_ProduceUtils > /dev/null") != 0) {
+        log_error("Module_ProduceUtils not running, restart it.\r\n");
+        system ("/root/Module_ProduceUtils &");
+    }
+}
+
+void InitialDHCP()
+{
+    char tmpbuf[256] = {0};
+
+    system("pgrep -f \"udhcpc -i eth0\" | xargs kill");
+    sprintf(tmpbuf, "/sbin/udhcpc -i eth0 -x hostname:CSU3_%s -s /root/dhcp_script/eth0.script > /dev/null &",
+            pSysConfig->SystemId);
+    system(tmpbuf);
+}
+
+//==========================================
+// Check Smart Charging Profile
+//==========================================
+int GetStartScheduleTime(uint8_t *time)
+{
+    int result = -1;
+    struct tm tmScheduleStart;
+    struct timeb tbScheduleStart;
+
+    if ((sscanf((char *)time, "%4d-%2d-%2dT%2d:%2d:%2d", &tmScheduleStart.tm_year, &tmScheduleStart.tm_mon, &tmScheduleStart.tm_mday, &tmScheduleStart.tm_hour, &tmScheduleStart.tm_min, &tmScheduleStart.tm_sec) == 6)) {
+        tmScheduleStart.tm_year -= 1900;
+        tmScheduleStart.tm_mon -= 1;
+        tbScheduleStart.time = mktime(&tmScheduleStart);
+        tbScheduleStart.millitm = 0;
+
+        result = DiffTimebWithNow(tbScheduleStart) / 1000;
+    }
+
+    return result;
+}
+
+void CheckSmartChargeProfile(uint8_t _index)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_index);
+
+    if (ShmOCPP16Data->CSUMsg.bits[_index].ChargingProfileConf == YES) {
+        // Get Charging Profile
+        ShmOCPP16Data->CSUMsg.bits[_index].ChargingProfileConf = NO;
+        if (strcmp((char *)ShmOCPP16Data->SmartChargingProfile[_index].ChargingProfileKind, "Absolute") == EQUAL &&
+                ShmOCPP16Data->SmartChargingProfile[_index].ChargingProfileId == YES //DS60-120 add
+           ) {
+            int _time = GetStartScheduleTime(ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.StartSchedule);
+            uint8_t _startCount = NO_DEFINE;
+            uint8_t _maxCount = ARRAY_SIZE(ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod);
+
+            for (uint8_t _count = 0; _count < _maxCount; _count++) {
+                // 預設最小輸出電流 (MIN_OUTPUT_CUR) A
+                if (_time >= ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_count].StartPeriod) {
+                    if ((_count == 0 && ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_count].Limit >= MIN_OUTPUT_CUR) ||
+                            ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_count].Limit > MIN_OUTPUT_CUR) {
+                        _startCount = _count;
+                    }
+                }
+            }
+
+            log_info("_startCount = %d \n", _startCount);
+            if (_startCount < _maxCount) {
+                //DS60-120 add
+                log_info("Profile Limit = %f \n", ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_startCount].Limit);
+                pDcChargingInfo->ChargingProfilePower = ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_startCount].Limit * AC_OUTPUT_VOL;
+                if (pDcChargingInfo->EvBatterytargetVoltage > 0 && pDcChargingInfo->PresentChargingVoltage > 0) {
+                    pDcChargingInfo->ChargingProfileCurrent = (pDcChargingInfo->ChargingProfilePower / pDcChargingInfo->PresentChargingVoltage) * 10;
+                } else {
+                    pDcChargingInfo->ChargingProfileCurrent = 0;
+                }
+
+                //DS60-120 remove
+                //log_info("*********Limit = %f \n", ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_startCount].Limit);
+                //pDcChargingInfo->ChargingProfileCurrent = ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_startCount].Limit * 10;
+                //pDcChargingInfo->ChargingProfilePower = ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_startCount].Limit * pDcChargingInfo->EvBatterytargetVoltage / 100;
+
+                //pDcChargingInfo->ChargingProfilePower = ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_startCount].Limit * AC_OUTPUT_VOL;
+//              if ((pDcChargingInfo->EvBatterytargetVoltage * 10) > 0)
+//              {
+//                  pDcChargingInfo->ChargingProfileCurrent = pDcChargingInfo->ChargingProfilePower / (pDcChargingInfo->EvBatterytargetVoltage * 10);
+//              }
+            } else {
+                pDcChargingInfo->ChargingProfilePower = -1;
+                pDcChargingInfo->ChargingProfileCurrent = -1;
+            }
+        } else {
+            pDcChargingInfo->ChargingProfilePower = -1;
+            pDcChargingInfo->ChargingProfileCurrent = -1;
+        }
+
+        log_info("ChargingProfilePower = %f \n", pDcChargingInfo->ChargingProfilePower);
+        log_info("ChargingProfileCurrent = %f \n", pDcChargingInfo->ChargingProfileCurrent);
+    }
+//
+//      printf("-------------Schedule------------\n");
+//      printf("index = %d \n", _index);
+//      printf("StartSchedule = %s \n", ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.StartSchedule);
+//      printf("ChargingRateUnit = %s \n", ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingRateUnit);
+//      printf("----------SchedulePeriod---------\n");
+//      for (int v = 0; v < 10; v++)
+//      {
+//          printf("StartPeriod = %d \n", ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[v].StartPeriod);
+//          printf("Limit = %f \n", ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[v].Limit);
+//      }
+//      printf("---------------------------------\n");
+}
+
+void ChargingProfileFlat(uint8_t _index)
+{
+    if (ShmOCPP16Data->CSUMsg.bits[_index].ChargingProfileConf == NO) {
+        if (ShmOCPP16Data->CSUMsg.bits[_index].ChargingProfileReq == NO) {
+            ShmOCPP16Data->CSUMsg.bits[_index].ChargingProfileReq = YES;
+        }
+    }
+}
+
+void CheckReturnToChargingConn()
+{
+    if ((pSysConfig->TotalConnectorCount + pSysConfig->AcConnectorCount) > 1 &&
+            pSysInfo->PageIndex != _LCM_AUTHORIZING &&
+            pSysInfo->PageIndex != _LCM_AUTHORIZ_FAIL &&
+            pSysInfo->PageIndex != _LCM_AUTHORIZ_COMP &&
+            pSysInfo->PageIndex != _LCM_WAIT_FOR_PLUG) {
+        bool isReturnTimeout = false;
+
+        for (uint8_t count = 0; count < pSysConfig->TotalConnectorCount; count++) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(count);
+
+            // 如果選的 DC 槍在充電~ 則 DC 槍不改變
+            if (count == pSysInfo->CurGunSelected) {
+                if ((pDcChargingInfo->SystemStatus >= S_REASSIGN_CHECK && pDcChargingInfo->SystemStatus <= S_COMPLETE) ||
+                        (pDcChargingInfo->SystemStatus >= S_CCS_PRECHARGE_ST0 && pDcChargingInfo->SystemStatus <= S_CCS_PRECHARGE_ST1)) {
+                    isReturnTimeout = false;
+                    break;
+                }
+            } else if (count != pSysInfo->CurGunSelected) {
+                if ((pDcChargingInfo->SystemStatus >= S_REASSIGN_CHECK && pDcChargingInfo->SystemStatus <= S_COMPLETE) ||
+                        (pDcChargingInfo->SystemStatus >= S_CCS_PRECHARGE_ST0 && pDcChargingInfo->SystemStatus <= S_CCS_PRECHARGE_ST1)) {
+                    isReturnTimeout = true;
+                    StartSystemTimeoutDet(Timeout_ReturnToChargingGunDet);
+                }
+            }
+        }
+
+        // AC 槍
+        if (!isReturnTimeout && pSysConfig->AcConnectorCount > 0) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(pSysInfo->CurGunSelected);
+            pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(0);
+
+            // 沒有選中 AC,且 AC 在充電中
+            if (pSysInfo->CurGunSelectedByAc == NO_DEFINE &&
+                    (pAcChargingInfo->SystemStatus >= S_PREPARNING &&
+                     pAcChargingInfo->SystemStatus <= S_COMPLETE)) {
+                // 當前 DC 充電槍在 idle 狀態
+                if (pDcChargingInfo->SystemStatus == S_IDLE ||
+                        pDcChargingInfo->SystemStatus == S_RESERVATION) {
+                    isReturnTimeout = true;
+                    StartSystemTimeoutDet(Timeout_ReturnToChargingGunDet);
+                }
+            } else if (pSysInfo->CurGunSelectedByAc == DEFAULT_AC_INDEX &&
+                       ((pDcChargingInfo->SystemStatus >= S_REASSIGN_CHECK &&
+                         pDcChargingInfo->SystemStatus <= S_COMPLETE) ||
+                        (pDcChargingInfo->SystemStatus >= S_CCS_PRECHARGE_ST0 &&
+                         pDcChargingInfo->SystemStatus <= S_CCS_PRECHARGE_ST1))) {
+                // 當前 DC 充電槍在 idle 狀態
+                if (pAcChargingInfo->SystemStatus == S_IDLE ||
+                        pAcChargingInfo->SystemStatus == S_RESERVATION) {
+                    isReturnTimeout = true;
+                    StartSystemTimeoutDet(Timeout_ReturnToChargingGunDet);
+                }
+            }
+        }
+
+        if (!isReturnTimeout) {
+            StopSystemTimeoutDet();
+        }
+    }
+}
+
+bool GetStartChargingByAlterMode(uint8_t _gun)
+{
+    bool result = true;
+
+    if (pSysConfig->TotalConnectorCount == 2 &&
+            pSysInfo->IsAlternatvieConf == YES) {
+        for (uint8_t _select = 0; _select < pSysConfig->TotalConnectorCount; _select++) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_select);
+
+            if (_select != _gun) {
+                if (pDcChargingInfo->SystemStatus != S_IDLE &&
+                        pDcChargingInfo->SystemStatus != S_RESERVATION) {
+                    result = false;
+                    break;
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+void TheEndCharging(uint8_t gun_index)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun_index);
+
+    ftime(&endChargingTime[gun_index]);
+
+    if (pDcChargingInfo->PresentChargedDuration != 0) {
+        pDcChargingInfo->PresentChargedDuration = DiffTimeb(startChargingTime[gun_index], endChargingTime[gun_index]);
+    }
+
+    pDcChargingInfo->isRemoteStart = NO;
+
+    StopGunInfoTimeoutDet(gun_index);
+    StartGunInfoTimeoutDet(gun_index, Timeout_EvseCompleteDet);
+    ChangeStartOrStopDateTime(NO, gun_index);
+    DB_Insert_Record(gun_index);
+}
+
+void UpdateErrorCodeToOcpp(uint8_t index)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+    //log_info("%d = ConnectorAlarmCode = %s\r\n", index, (char *)chargingInfo[index]->ConnectorAlarmCode);
+    //log_info("%d = EvConnAlarmCode = %s\r\n", index, (char *)chargingInfo[index]->EvConnAlarmCode);
+    if (strcmp((char *)pDcChargingInfo->ConnectorAlarmCode, "") != EQUAL) {
+        //if (strlen((char *)pDcChargingInfo->ConnectorAlarmCode) == EQUAL) {
+        strcpy((char *)ShmOCPP16Data->StatusNotification[index].ErrorCode, "InternalError");
+        strcpy((char *)ShmOCPP16Data->StatusNotification[index].VendorErrorCode, (char *)pDcChargingInfo->ConnectorAlarmCode);
+    } else if (strcmp((char *)pDcChargingInfo->EvConnAlarmCode, "") != EQUAL) {
+        //} else if (strlen((char *)pDcChargingInfo->EvConnAlarmCode) == EQUAL) {
+        strcpy((char *)ShmOCPP16Data->StatusNotification[index].ErrorCode, "OtherError");
+        strcpy((char *)ShmOCPP16Data->StatusNotification[index].VendorErrorCode, (char *)pDcChargingInfo->EvConnAlarmCode);
+    }
+
+    //log_info("2 %d = VendorErrorCode = %s\r\n", index, (char *)ShmOCPP16Data->StatusNotification[index].VendorErrorCode);
+}
+
+void AdjustChargerCurrent()
+{
+    pSysConfig->RatingCurrent = ShmPsuData->SystemAvailableCurrent / 10;
+
+    // 設定的電流~ 如超過可輸出的電流,則 bypass
+    if (pSysConfig->RatingCurrent < pSysConfig->MaxChargingCurrent ||
+            pSysConfig->RatingCurrent == 0) {
+        pSysConfig->MaxChargingCurrent = 0;
+    }
+
+    log_info ("PSU : MaxChargingPower = %d, MaxChargingCurrent = %d",
+              ShmPsuData->SystemAvailablePower / 10,
+              ShmPsuData->SystemAvailableCurrent / 10
+             );
+
+    log_info ("Config : ChargingPower = %d, ChargingCurrent = %d",
+              pSysConfig->MaxChargingPower,
+              pSysConfig->MaxChargingCurrent
+             );
+}
+
+void ResetDetAlarmStatus(uint8_t gun)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun);
+
+    if (pDcChargingInfo->Type == _Type_Chademo) {
+        if (pAlarmCode->AlarmEvents.bits.SystemChademoOutputOVP == YES) {
+            pAlarmCode->AlarmEvents.bits.SystemChademoOutputOVP = NO;
+        }
+    } else if (pDcChargingInfo->Type == _Type_GB) {
+        if (pAlarmCode->AlarmEvents.bits.SystemGbOutputOVP == YES) {
+            pAlarmCode->AlarmEvents.bits.SystemGbOutputOVP = NO;
+        }
+    } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+        if (pAlarmCode->AlarmEvents.bits.SystemCcsOutputOVP == YES) {
+            pAlarmCode->AlarmEvents.bits.SystemCcsOutputOVP = NO;
+        }
+    }
+}
+
+static void powerCabinetPsuAlarmStatus(void)
+{
+    uint8_t i = 0;
+
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+    return;
+#endif //!defined DD360 && !defined DD360Audi && !defined DD360ComBox
+
+    for (i = 0; i < pSysWarning->WarningCount; i++) {
+        if (memcmp(&pSysWarning->WarningCode[i][0], "042267", 6) == 0) {
+            EmcOccureByString("042267");
+        }
+    }
+}
+
+static void autoStartChargingForComBox(uint8_t gunIndex)
+{
+#if !defined DD360ComBox
+    return ;
+#endif //!defined DD360ComBox
+
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if ((pDcChargingInfo->ConnectorPlugIn == YES) &&
+            (pDcChargingInfo->SystemStatus == S_IDLE)
+       ) {
+        pSysInfo->CurGunSelected = gunIndex;
+        strcpy((char *)&pSysConfig->UserId, "AutoStartCharging");
+    }
+}
+
+static bool PrecheckIsPass(uint8_t gun_index)
+{
+    bool result = true;
+
+    // relay welding or driving 是反向
+    result = !ShmDcCommonData->GunRelayWeldingOccur[gun_index];
+
+    return result;
+}
+
+static void ReviewCriticalAlarm(void)
+{
+    if (ShmDcCommonData->GunRelayDrivingOccur[0] == YES ||
+            ShmDcCommonData->GunRelayDrivingOccur[1] == YES ||
+            ShmDcCommonData->GunRelayWeldingOccur[0] == YES ||
+            ShmDcCommonData->GunRelayWeldingOccur[1] == YES ||
+            pAlarmCode->AlarmEvents.bits.EmergencyStopTrip ||
+            pAlarmCode->AlarmEvents.bits.MainPowerBreakerTrip ||
+            pAlarmCode->AlarmEvents.bits.DoorOpen ||
+            pSysWarning->ExtraErrProcess != _EXTRA_ERR_PROCESS_NONE ||
+            pAlarmCode->AlarmEvents.bits.PsuFailureAlarm ||
+            pAlarmCode->AlarmEvents.bits.DisconnectedFromDo
+       ) {
+        pSysWarning->Level = 2;
+    } else {
+        pSysWarning->Level = 0;
+    }
+}
+
+static void CheckRelayWeldingOrDrivingFault(uint8_t gun_index)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun_index);
+
+    // relay welding fault then stop the charging process.
+    uint8_t faultCode = RELAY_STATUS_ERROR_NONE;
+
+    if (gun_index == 0) {
+        if (ShmDcCommonData->CheckRelayStatus[RELAY_SMR1_P_STATUS] == RELAY_STATUS_ERROR_WELDING ||
+                ShmDcCommonData->CheckRelayStatus[RELAY_SMR1_N_STATUS] == RELAY_STATUS_ERROR_WELDING) {
+            faultCode = RELAY_STATUS_ERROR_WELDING;
+        } else if (ShmDcCommonData->CheckRelayStatus[RELAY_SMR1_P_STATUS] == RELAY_STATUS_ERROR_DRIVING ||
+                   ShmDcCommonData->CheckRelayStatus[RELAY_SMR1_N_STATUS] == RELAY_STATUS_ERROR_DRIVING) {
+            faultCode = RELAY_STATUS_ERROR_DRIVING;
+        }
+    } else if (gun_index == 1) {
+        if (ShmDcCommonData->CheckRelayStatus[RELAY_SMR2_P_STATUS] == RELAY_STATUS_ERROR_WELDING ||
+                ShmDcCommonData->CheckRelayStatus[RELAY_SMR2_N_STATUS] == RELAY_STATUS_ERROR_WELDING) {
+            faultCode = RELAY_STATUS_ERROR_WELDING;
+        } else if (ShmDcCommonData->CheckRelayStatus[RELAY_SMR2_P_STATUS] == RELAY_STATUS_ERROR_DRIVING ||
+                   ShmDcCommonData->CheckRelayStatus[RELAY_SMR2_N_STATUS] == RELAY_STATUS_ERROR_DRIVING) {
+            faultCode = RELAY_STATUS_ERROR_DRIVING;
+        }
+    }
+
+    if (pSysConfig->TotalConnectorCount >= 2 &&
+            !pSysInfo->IsAlternatvieConf) {
+        // 橋接
+        if (ShmDcCommonData->CheckRelayStatus[RELAY_PARA_P_STATUS] == RELAY_STATUS_ERROR_WELDING ||
+                ShmDcCommonData->CheckRelayStatus[RELAY_PARA_N_STATUS] == RELAY_STATUS_ERROR_WELDING) {
+            faultCode = RELAY_STATUS_ERROR_WELDING;
+        } else if (ShmDcCommonData->CheckRelayStatus[RELAY_PARA_P_STATUS] == RELAY_STATUS_ERROR_DRIVING ||
+                   ShmDcCommonData->CheckRelayStatus[RELAY_PARA_N_STATUS] == RELAY_STATUS_ERROR_DRIVING) {
+            faultCode = RELAY_STATUS_ERROR_DRIVING;
+        }
+    }
+
+    if (faultCode == RELAY_STATUS_ERROR_WELDING) {
+        // welding
+        if (pDcChargingInfo->Type == _Type_Chademo) {
+            RecordAlarmCode(gun_index, "011011");
+        } else if (pDcChargingInfo->Type == _Type_GB) {
+            RecordAlarmCode(gun_index, "011015");
+        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+            RecordAlarmCode(gun_index, "011013");
+        }
+
+        ShmDcCommonData->GunRelayWeldingOccur[gun_index] = YES;
+        EmcOccureByString("");
+    } else if (faultCode == RELAY_STATUS_ERROR_DRIVING) {
+        // driving
+        if (pDcChargingInfo->Type == _Type_Chademo) {
+            RecordAlarmCode(gun_index, "011012");
+        } else if (pDcChargingInfo->Type == _Type_GB) {
+            RecordAlarmCode(gun_index, "011016");
+        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+            RecordAlarmCode(gun_index, "011014");
+        }
+
+        ShmDcCommonData->GunRelayDrivingOccur[gun_index] = YES;
+        EmcOccureByString("");
+    } else {
+        ShmDcCommonData->GunRelayWeldingOccur[gun_index] = NO;
+        ShmDcCommonData->GunRelayDrivingOccur[gun_index] = NO;
+
+        if (pDcChargingInfo->Type == _Type_Chademo) {
+            ResetChargerAlarmCode(gun_index, "011012");
+            ResetChargerAlarmCode(gun_index, "011011");
+        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+            ResetChargerAlarmCode(gun_index, "011014");
+            ResetChargerAlarmCode(gun_index, "011013");
+        } else if (pDcChargingInfo->Type == _Type_GB) {
+            ResetChargerAlarmCode(gun_index, "011016");
+            ResetChargerAlarmCode(gun_index, "011015");
+        }
+    }
+}
+
+int main(void)
+{
+    bool isModelNameMatch = true;
+    uint8_t evBoardStopState = 0;
+    uint8_t _ocppProfileChkFlag;
+
+    if (CreateAllCsuShareMemory() == FAIL) {
+        log_error("create share memory error\r\n");
+        return FAIL;
+    }
+    ClearAllShmMemParameter();
+
+    pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
+    pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
+    pSysWarning = (struct WARNING_CODE_INFO *)GetShmSysWarningInfo();
+
+    pAlarmCode = (struct AlarmCodeData *)GetShmAlarmCodeData();
+    pFaultCode = (struct FaultCodeData *)GetShmFaultCodeData();
+    pInfoCode = (struct InfoCodeData *)GetShmInfoCodeData();
+
+    ShmPsuData = (struct PsuData *)GetShmPsuData();
+
+    ShmCHAdeMOData = (struct CHAdeMOData *)GetShmCHAdeMOData();
+    ShmGBTData = (struct GBTData *)GetShmGBTData();
+    ShmCcsData = (struct CcsData *)GetShmCcsData();
+
+    ShmPrimaryMcuData = (struct PrimaryMcuData *)GetShmPrimaryMcuData();
+    ShmFanModuleData = (struct FanModuleData *)GetShmFanModuleData();
+    ShmRelayModuleData = (struct RelayModuleData *)GetShmRelayModuleData();
+    ShmLedModuleData = (struct LedModuleData *)GetShmLedModuleData();
+    ShmOCPP16Data = (struct OCPP16Data *)GetShmOCPP16Data();
+    ShmDcCommonData = (DcCommonInfo *)GetShmDcCommonData();
+    gAudiCustInfo = (SelectGunInfo *)GetShmSelectGunInfo();
+
+    log_info(" ****************  FileSystem Boot up ***************\n");
+    if (!InitialSystemDefaultConfig()) {
+        log_error("InitialSystemDefaultConfig NG \n");
+        //StopProcessingLoop();
+        sleep(5);
+        system("reboot -f");
+    }
+    CheckGunTypeFromHw();
+    CheckIsAlternatvieByModelName();
+    InitialShareMemoryInfo();
+
+    ChangeLcmByIndex(_LCM_INIT);
+    if (!CheckConnectorTypeStatus()) {
+        isModelNameMatch = false;
+    }
+
+    Initialization();
+    SpawnTask();
+    log_info("Spawned all Task");
+    if (!isModelNameMatch) {
+        pAlarmCode->AlarmEvents.bits.ModelNameNoneMatchStestFail = YES;
+        ChangeLcmByIndex(_LCM_FIX);
+        // Module Name 與硬體對應不正確
+        log_error("Module Name & HW info none match. \n");
+        sleep(3);
+        KillAllTask();
+        StopProcessingLoop();
+    }
+    CreateTimeoutFork();
+    log_info("Start self test... \n");
+    PrimaryLedIndicatorCtrlFork();
+    SelfTestRun();
+    StopSystemTimeoutDet();
+    log_info("Self test finished : SelfTestSeq = %d, Work_Step = %d ",
+             pSysInfo->SelfTestSeq,
+             ShmPsuData->Work_Step);
+
+    if (pSysInfo->SelfTestSeq == _STEST_FAIL ||
+            ShmPsuData->Work_Step == _NO_WORKING ||
+            pInfoCode->InfoEvents.bits.CcsSeccTimeoutQCA7000Comm == YES //DS60-120 add
+       ) {
+        if (pSysWarning->Level != 2) {
+            if (!DisplaySelfTestFailReason()) { //DS60-120 add
+                log_info("Soft reboot for retry self-tets. \n");
+
+                sleep(3);
+                system("killall OcppBackend &");
+                KillAllTask();
+                system("/usr/bin/run_evse_restart.sh");
+            }
+        }
+
+        for (uint8_t gun_index = 0; gun_index < pSysConfig->TotalConnectorCount; gun_index++) {
+            setChargerMode(gun_index, MODE_ALARM);
+        }
+        //ChangeLcmByIndex(_LCM_FIX);
+        sleep(3);
+        if (pSysWarning->Level == 2) { //DS60-120 add
+            KillTaskExceptPrimary();
+        } else {
+            KillTask();
+        }
+        StopProcessingLoop();
+    } else {
+        for (uint8_t gun_index = 0; gun_index < pSysConfig->TotalConnectorCount; gun_index++) {
+            setChargerMode(gun_index, MODE_IDLE);
+        }
+    }
+
+    // Local DB
+    if (DB_Open() != PASS) {
+        log_info("DB_Open fail. \n");
+        isDb_ready = false;
+    } else {
+        isDb_ready = true;
+        for (int _index = 0; _index < pSysConfig->TotalConnectorCount; _index++) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_index);
+
+            pDcChargingInfo->IsAvailable = DB_Get_Operactive(_index);
+        }
+        DB_Reboot_Record();
+    }
+    log_info("===== Create DB End ===== \n");
+
+#if defined DD360Audi
+    ChangeLcmByIndex(_LCM_SELECT_GUN);
+#else
+    ChangeLcmByIndex(_LCM_IDLE);
+#endif //defined DD360Audi
+
+    sleep(1);
+    //***** 須新增的偵測 *****//
+    // 1. Thernal - 控制風扇轉速
+    // 2. ouput fuse - 控制風扇轉速
+    CreateRfidFork();
+    // Create Watchdog
+    //CreateWatchdog();
+    // Main loop
+
+    log_info("===== Charger info ===== ");
+    log_info("SW Version = %s", fwVersion);
+    log_info("ModelName = %s", pSysConfig->ModelName);
+    CheckFwSlotStatusLog();
+    //AdjustChargerCurrent();
+    gettimeofday(&_cmdMainPriority_time, NULL);
+
+    GunIndexInfo *pGunIndexInfo = (GunIndexInfo *)GetGunIndexInfo();
+
+    for (;;) {
+        CheckOcppStatus();
+        ChkPrimaryStatus();
+        if ((IsConnectorWholeIdle() || pSysInfo->PageIndex == _LCM_FIX) &&
+                pSysInfo->SystemTimeoutFlag != Timeout_ReturnToChargingGunDet) {
+            CheckFactoryConfigFunction();
+
+            CheckFwUpdateFunction();
+        }
+
+        // OCPP 邏輯
+        OcppRemoteStartChk();
+        // 讀卡邏輯
+        ScannerCardProcess();
+        // 當 AC 沒有搭上時,清除一些錯誤碼
+        ClearAlarmCodeWhenAcOff();
+        // 確認是否要回到充電中的槍畫面邏輯判斷
+        CheckReturnToChargingConn();
+
+        //確認Power cabinet PSU Status
+        powerCabinetPsuAlarmStatus();
+
+        if (pGunIndexInfo->AcGunIndex > 0 && isDetectPlugin() && !GetIsCardScan()) {
+            pSysInfo->SystemPage = _LCM_WAIT_FOR_PLUG;
+        }
+
+        if ((GetTimeoutValue(_cmdMainPriority_time) / 1000) > 5000) {
+            CheckTask();
+
+            for (uint8_t _index = 0; _index < pSysConfig->TotalConnectorCount; _index++) {
+                pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_index);
+
+                if ((pDcChargingInfo->SystemStatus >= S_PREPARING_FOR_EVSE &&
+                        pDcChargingInfo->SystemStatus <= S_CHARGING) ||
+                        (pDcChargingInfo->SystemStatus >= S_CCS_PRECHARGE_ST0 &&
+                         pDcChargingInfo->SystemStatus <= S_CCS_PRECHARGE_ST1)) {
+                    if (pDcChargingInfo->SystemStatus == S_CHARGING &&
+                            _ocppProfileChkFlag == 12) {
+                        ChargingProfileFlat(_index);
+                        _ocppProfileChkFlag = 0;
+                    } else if (pDcChargingInfo->SystemStatus != S_CHARGING) {
+                        ChargingProfileFlat(_index);
+                        _ocppProfileChkFlag = 0;
+                    } else {
+                        _ocppProfileChkFlag++;
+                    }
+                }
+                checkGunOTPState(_index); //check gun OTP
+            }
+            gettimeofday(&_cmdMainPriority_time, NULL);
+        }
+
+        // 確認當前錯誤 Level = 2 ?
+        ReviewCriticalAlarm();
+        gEvBoardErr.GunErrMessage = 0;
+
+        for (uint8_t gun_index = 0; gun_index < pSysConfig->TotalConnectorCount; gun_index++) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun_index);
+
+            autoStartChargingForComBox(gun_index); //for DD360ComBox
+
+            CheckGpioInStatus();
+
+            CheckErrorOccurStatus(gun_index);
+
+            // 確認 Relay Welding or Driving Fault
+            CheckRelayWeldingOrDrivingFault(gun_index);
+
+            // 收集各槍的錯誤狀態
+            collectError(gun_index);
+
+            ChkOcppStatus(gun_index);
+
+            if ((pDcChargingInfo->SystemStatus >= S_PREPARING_FOR_EVSE &&
+                    pDcChargingInfo->SystemStatus <= S_CHARGING) ||
+                    (pDcChargingInfo->SystemStatus >= S_CCS_PRECHARGE_ST0 &&
+                     pDcChargingInfo->SystemStatus <= S_CCS_PRECHARGE_ST1)) {
+                CheckSmartChargeProfile(gun_index);
+            }
+
+            //log_info("index = %d, ErrorCode = %s \n", gun_index, ShmOCPP16Data->StatusNotification[gun_index].ErrorCode);
+            switch (pDcChargingInfo->SystemStatus) {
+            case S_IDLE:
+                ReleaseAlarmCode(gun_index);
+
+                if (isModeChange(gun_index)) {
+                    log_info("S_IDLE================================== %x \n", gun_index);
+                    pDcChargingInfo->PresentChargedDuration = 0;
+                    pDcChargingInfo->RemainChargingDuration = 0;
+                    pDcChargingInfo->PresentChargingVoltage = 0;//DS60-120 add
+                    pDcChargingInfo->PresentChargingCurrent = 0;//DS60-120 add
+                    strcpy((char *)pDcChargingInfo->StartDateTime, "");
+                    strcpy((char *)pDcChargingInfo->StopDateTime, "");
+                    strcpy((char *)pDcChargingInfo->StartUserId, "");
+                    strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "");
+
+                    //Jerry add
+                    memset(&gAudiCustInfo->PricesInfo[gun_index], 0, sizeof(PricesInfo));
+                    gAudiCustInfo->PricesInfo[gun_index].Balance = FAIL_BALANCE_PRICES;
+                    destroySelGun(gun_index);
+                    ResetDetAlarmStatus(gun_index); //recovery OVP status code
+                    if (gAudiCustInfo->AuthorStateFromCabinet[gun_index] == YES) {
+                        gAudiCustInfo->AuthorStateFromCabinet[gun_index] = NO;
+                    }
+                    //strcpy((char *)ShmOCPP16Data->StatusNotification[gun_index].VendorErrorCode, "");
+                }
+
+            case S_RESERVATION:
+                if (isModeChange(gun_index)) {
+                    log_info("S_RESERVATION....................%x \n", gun_index);
+                    ShmOCPP16Data->CsMsg.bits[gun_index].ReserveNowConf = YES;
+                }
+
+                if (pDcChargingInfo->IsAvailable == NO) {
+                    setChargerMode(gun_index, MODE_MAINTAIN);
+                }
+
+            case S_MAINTAIN:
+            case S_FAULT: {
+                if (pSysWarning->Level == 2) {
+                    pDcChargingInfo =  (struct ChargingInfoData *)GetDcChargingInfoData(pSysInfo->CurGunSelected);
+
+                    if (gun_index == pSysInfo->CurGunSelected) {
+                        pSysInfo->SystemPage = _LCM_FIX;
+                    } else if (pDcChargingInfo->SystemStatus != S_IDLE &&
+                               pDcChargingInfo->SystemStatus != S_RESERVATION &&
+                               pDcChargingInfo->SystemStatus != S_MAINTAIN &&
+                               pDcChargingInfo->SystemStatus != S_FAULT) {
+                        if (pDcChargingInfo->SystemStatus == S_CHARGING) {
+                            pSysInfo->SystemPage = _LCM_COMPLETE;
+                        } else {
+#if defined DD360Audi
+                            pSysInfo->SystemPage = _LCM_SELECT_GUN;
+#else
+                            pSysInfo->SystemPage = _LCM_NONE;
+#endif //defined DD360Audi
+                        }
+                    }
+
+                    ClearDetectPluginFlag();
+//#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                    UpdateErrorCodeToOcpp(gun_index);
+//#endif //!defined DD360 && !defined DD360Audi
+                    setChargerMode(gun_index, MODE_FAULT);
+                } else {
+#if 1
+                    if (pDcChargingInfo->SystemStatus == S_FAULT) {
+#if defined DD360Audi
+                        pSysInfo->SystemPage = _LCM_SELECT_GUN;
+#else
+                        pSysInfo->SystemPage = _LCM_NONE;
+#endif //defined DD360Audi
+                        setChargerMode(gun_index, MODE_IDLE);
+                    }
+
+                    //if (pSysInfo->SystemPage == _LCM_FIX) {
+                    //    pSysInfo->SystemPage = _LCM_SELECT_GUN;//_LCM_NONE; //Jerry add
+                    //    //for (uint8_t g_index = 0; g_index < pSysConfig->TotalConnectorCount; g_index++) {
+                    //    setChargerMode(gun_index, MODE_IDLE);
+                    //    //}
+                    //}
+#endif //0
+
+                    if (pSysInfo->MainChargingMode == _MAIN_CHARGING_MODE_AVER) {
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                        if (pSysInfo->AcContactorStatus == YES)
+#else
+                        if (1)
+#endif //!defined DD360 && !defined DD360Audi
+                        {
+                            // 均充 -> 最大充
+                            if (pSysInfo->BridgeRelayStatus == NO) {
+                                if (pSysInfo->ReAssignedFlag == _REASSIGNED_NONE) {
+                                    log_info("=============Smart Charging============= Step 11 \n");
+                                    pSysInfo->ReAssignedFlag = _REASSIGNED_PREPARE_A_TO_M;
+                                }
+                            } else if (pSysInfo->ReAssignedFlag != _REASSIGNED_COMP &&
+                                       pSysInfo->ReAssignedFlag != _REASSIGNED_WAITING) {
+                                log_info("=============Smart Charging============= Step 14 \n");
+                                pSysInfo->ReAssignedFlag = _REASSIGNED_WAITING;
+                            } else if (pSysInfo->ReAssignedFlag == _REASSIGNED_COMP) {
+                                pSysInfo->MainChargingMode = _MAIN_CHARGING_MODE_MAX;
+                                pSysInfo->ReAssignedFlag = _REASSIGNED_NONE;
+                            }
+                        } else {
+                            pSysInfo->MainChargingMode = _MAIN_CHARGING_MODE_MAX;
+                            pSysInfo->ReAssignedFlag = _REASSIGNED_NONE;
+                        }
+                    } else {
+                        pSysInfo->ReAssignedFlag = _REASSIGNED_NONE;
+                    }
+
+                    if (PrecheckIsPass(gun_index)) {
+
+                        if (pDcChargingInfo->SystemStatus == S_FAULT) {
+                            pSysInfo->SystemPage = _LCM_NONE;
+                            setChargerMode(gun_index, MODE_IDLE);
+                        }
+
+                        if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_NO_CHARGING) {
+                            if (pSysInfo->CurGunSelected == gun_index) {
+#if defined DD360Audi
+                                pSysInfo->ConnectorPage = _LCM_SELECT_GUN;
+#else
+                                pSysInfo->ConnectorPage = _LCM_IDLE;
+#endif //
+                            }
+                        } else {
+                            // Idle 正常程序起點
+                            // 判斷是否有啟用檢查插槍
+                            if (isDetectPlugin()) {
+                                // 卡號驗證成功後,等待充電槍插入充電車
+                                if (pDcChargingInfo->RemoteStartFlag == YES) {
+                                    if (pDcChargingInfo->ConnectorPlugIn == YES &&
+                                            pDcChargingInfo->IsAvailable) {
+                                        log_info("-----------------1----------------- %d \n", gun_index);
+                                        pDcChargingInfo->RemoteStartFlag = NO;
+                                        pDcChargingInfo->isRemoteStart = YES; //DS60-120
+                                        ChangeGunSelectByIndex(gun_index);
+                                        AddPlugInTimes(gun_index);
+                                        setChargerMode(gun_index, MODE_REASSIGN_CHECK);
+                                        strcpy((char *)pDcChargingInfo->StartUserId, "");
+                                        ClearDetectPluginFlag();
+                                        continue;
+                                    }
+                                } else if (pSysInfo->OrderCharging == NO_DEFINE) {
+                                    if (pDcChargingInfo->ConnectorPlugIn == YES &&
+                                            pDcChargingInfo->IsAvailable &&
+                                            pDcChargingInfo->SystemStatus == S_IDLE
+#if defined DD360Audi
+                                            && (waitRightGunPlugIt(gun_index) == PASS ||
+                                                waitLeftGunPlugIt(gun_index) == PASS)
+#endif //defined DD360Audi
+                                       ) {
+                                        log_info("-----------------2----------------- \n");
+                                        ChangeGunSelectByIndex(gun_index);
+                                        AddPlugInTimes(gun_index);
+                                        strcpy((char *)pDcChargingInfo->StartUserId, (char *)pSysConfig->UserId);
+                                        log_info("index = %d, CardNumber = %s \n", gun_index, pDcChargingInfo->StartUserId);
+                                        strcpy((char *)pSysConfig->UserId, "");
+                                        // 當前操作的槍號,進入 Preparing
+                                        setChargerMode(gun_index, MODE_REASSIGN_CHECK);
+                                        ClearDetectPluginFlag();
+                                        continue;
+                                    }
+                                }
+
+                                if (!GetIsCardScan()) {
+                                    // LCM => Waiting for plugging
+                                    pSysInfo->SystemPage = _LCM_WAIT_FOR_PLUG;
+                                }
+                            } else if (pDcChargingInfo->SystemStatus == S_RESERVATION) {
+                                if (!isReservationExpired(gun_index)) {
+                                    pDcChargingInfo->SystemStatus = S_IDLE;
+                                }
+                            } else if (pSysConfig->AuthorisationMode == AUTH_MODE_DISABLE &&
+                                       (pDcChargingInfo->ConnectorPlugIn == YES && pDcChargingInfo->IsAvailable)) {
+                                log_info("-----------------3----------------- \n");
+                                bool isCanStartChargingFlag = GetStartChargingByAlterMode(gun_index);
+
+                                if (isCanStartChargingFlag) {
+                                    ChangeGunSelectByIndex(gun_index);
+                                    AddPlugInTimes(gun_index);
+                                    setChargerMode(gun_index, MODE_REASSIGN_CHECK);
+                                    ClearDetectPluginFlag();
+                                    continue;
+                                }
+                            } else {
+                                if (pSysInfo->CurGunSelected == gun_index) {
+#if defined DD360Audi
+                                    pSysInfo->ConnectorPage = _LCM_SELECT_GUN;
+#else
+                                    pSysInfo->ConnectorPage = _LCM_IDLE;
+#endif // defined DD360Audi
+                                }
+                            }
+                        } // Idle 正常程序終點
+                    } else {
+                        setChargerMode(gun_index, MODE_FAULT);
+                        if (gun_index == pSysInfo->CurGunSelected) {
+                            pSysInfo->SystemPage = _LCM_FIX;
+                        }
+                    }// PrecheckIsPass()
+                }
+            }
+            break;
+            case S_REASSIGN_CHECK: {
+                if (isModeChange(gun_index)) {
+                    log_info("S_REASSIGN_CHECK================================== %x \n", gun_index);
+#if defined DD360Audi
+                    pSysInfo->SystemPage = _LCM_SELECT_GUN;
+#else
+                    pSysInfo->SystemPage = _LCM_NONE;
+#endif //defined DD360Audi
+                    if (pSysInfo->OrderCharging != NO_DEFINE) {
+                        pSysInfo->OrderCharging = NO_DEFINE;
+                    }
+                    StopSystemTimeoutDet();
+                }
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                bool isRessign = false;
+                if (pSysConfig->TotalConnectorCount > 1 && pSysInfo->IsAlternatvieConf == NO) {
+                    if (pSysInfo->MainChargingMode == _MAIN_CHARGING_MODE_MAX) {
+                        for (byte index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+                            // 有其他槍已經分配好 psu 模塊
+                            if (pSysInfo->CurGunSelected != index &&
+                                    chargingInfo[index]->SystemStatus >= S_PREPARNING &&
+                                    chargingInfo[index]->SystemStatus != S_MAINTAIN) {
+                                log_info("=============Smart Charging============= Step 1 \n");
+                                pSysInfo->ReAssignedFlag = _REASSIGNED_PREPARE_M_TO_A;
+                                isRessign = true;
+                                break;
+                            }
+                        }
+                    } else if (pSysInfo->MainChargingMode == _MAIN_CHARGING_MODE_AVER &&
+                               pSysInfo->ReAssignedFlag != _REASSIGNED_NONE) {
+                        // 如果在切換最大充的過程中,需等待最大充切換完成後,在走均充流程
+                        if (pSysInfo->BridgeRelayStatus == YES) {
+                            if (pSysInfo->ReAssignedFlag != _REASSIGNED_COMP &&
+                                    pSysInfo->ReAssignedFlag != _REASSIGNED_WAITING) {
+                                log_info("=============Smart Charging============= Step 14 \n");
+                                pSysInfo->ReAssignedFlag = _REASSIGNED_WAITING;
+                            } else if (pSysInfo->ReAssignedFlag == _REASSIGNED_COMP) {
+                                pSysInfo->MainChargingMode = _MAIN_CHARGING_MODE_MAX;
+                                pSysInfo->ReAssignedFlag = _REASSIGNED_NONE;
+                                continue;
+                            }
+                        }
+
+                        if (pSysInfo->CurGunSelected == gun_index) {
+                            pSysInfo->ConnectorPage = _LCM_PRE_CHARGE;
+                        }
+                        continue;
+                    }
+                }
+#endif // !defined DD360 && !defined DD360Audi
+
+                if (0) { // if (isRessign)
+#if defined DD360 ||defined DD360Audi || defined DD360ComBox
+                    setChargerMode(gun_index, MODE_PRECHARGE);
+#else
+                    setChargerMode(gun_index, MODE_REASSIGN);
+#endif //defined DD360 || defined DD360Audi
+                } else {
+                    setChargerMode(gun_index, MODE_PRECHARGE);
+                }
+
+                if (pSysInfo->CurGunSelected == gun_index) {
+                    pSysInfo->ConnectorPage = _LCM_PRE_CHARGE;
+                }
+            }
+            break;
+            case S_REASSIGN: {
+                if (isModeChange(gun_index)) {
+                    log_info("S_REASSIGN================================== %x \n", gun_index);
+                    gettimeofday(&_toAverage_time, NULL);
+                }
+
+                // 重新分配,此階段主要是讓已經在充電或者準備進入充電前的緩衝
+                // 此狀態下~ 控制權在於 PSU 及 EV小板 Process
+                if (pSysInfo->ReAssignedFlag == _REASSIGNED_NONE ||
+                        pSysInfo->MainChargingMode == _MAIN_CHARGING_MODE_AVER) {
+                    if (pSysInfo->CanAverageCharging) {
+                        pSysInfo->MainChargingMode = _MAIN_CHARGING_MODE_AVER;//DS60-120 add
+                        setChargerMode(gun_index, MODE_PRECHARGE);
+                    } else {
+                        setChargerMode(gun_index, MODE_IDLE);
+                    }
+                    pSysInfo->ReAssignedFlag = _REASSIGNED_NONE; //DS60-120 add
+                } else if (pSysInfo->ReAssignedFlag == _REASSIGNED_RELAY_M_TO_A &&
+                           pSysInfo->BridgeRelayStatus == NO) {
+                    log_info("=============Smart Charging : _REASSIGNED_COMP============= Step 6 \n");
+                    pSysInfo->MainChargingMode = _MAIN_CHARGING_MODE_AVER;
+                    //pSysInfo->ReAssignedFlag = _REASSIGNED_NONE; //DS60-120 remove
+                    pSysInfo->CanAverageCharging = true; //DS60-120 add
+                }
+
+                //log_info("CurGunSelected = %d, gun_index = %d \n", pSysInfo->CurGunSelected, gun_index);
+                if (pSysInfo->CurGunSelected == gun_index) {
+                    pSysInfo->ConnectorPage = _LCM_PRE_CHARGE;
+                    // pSysInfo->SystemPage = _LCM_NONE;
+                }
+            }
+            break;
+            case S_PREPARNING: {
+                if (isModeChange(gun_index)) {
+                    log_info("S_PREPARNING================================== %x \n", gun_index);
+                    StopGunInfoTimeoutDet(gun_index);
+                    StartGunInfoTimeoutDet(gun_index, Timeout_Preparing);
+                }
+
+                if (ShmPsuData->SystemPresentPsuQuantity > 0 &&
+                        ShmPsuData->SystemAvailablePower > 10 &&
+                        GetTimeoutValue(pDcChargingInfo->TimeoutTimer) >= 5000000) {
+                    //if ((pDcChargingInfo->MaximumChargingVoltage > 0) && //DS60-120 remove
+                    //        (pDcChargingInfo->AvailableChargingCurrent > 0) &&
+                    //        (pDcChargingInfo->AvailableChargingPower > 0)) {
+                    setChargerMode(gun_index, MODE_PREPARE_FOR_EV);
+                    //}
+                }
+
+                //DS60-120 add
+                if (pSysConfig->TotalConnectorCount >= 2) {
+                    bool oughtAver = true;
+                    for (uint8_t index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+                        pDcChargingInfo =  (struct ChargingInfoData *)GetDcChargingInfoData(index);
+                        // 共同進入充電邏輯
+                        if (pDcChargingInfo->SystemStatus != S_PREPARNING) {
+                            oughtAver = false;
+                            break;
+                        }
+                    }
+
+                    if (oughtAver) {
+                        log_info("********* Automatically change to aver mode ********** \n");
+                        pSysInfo->MainChargingMode = _MAIN_CHARGING_MODE_AVER;
+                        pSysInfo->ReAssignedFlag = _REASSIGNED_NONE;
+                    }
+                }
+
+                if ((evBoardStopState = isEvBoardStopChargeFlag(gun_index)) > 0) {
+                    // 板端要求停止 (錯誤)
+                    if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL) {
+                        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "EVDisconnected");
+                    }
+
+                    if (evBoardStopState == EV_BOARD_STOP_CHARGING) {
+                        ChargingAlarmProcess(gun_index);
+                    } else if (evBoardStopState == POWER_CABINET_STOP_CHARGING) {
+                        ChargingTerminalProcess(gun_index);
+                    }
+                } else if (isEvBoardNormalStopChargeFlag(gun_index) == YES) {
+                    // 板端要求停止 (正常)
+                    if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL) {
+                        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "EVDisconnected");
+                    }
+                    ChargingTerminalProcess(gun_index);
+                } else if (OcppRemoteStop(gun_index) == YES ||
+                           WifiScheduleStop(gun_index)) {
+                    // 後臺要求停止
+                    ChargingTerminalProcess(gun_index);
+                }
+
+                if (pSysInfo->CurGunSelected == gun_index) {
+                    pSysInfo->ConnectorPage = _LCM_PRE_CHARGE;
+                    // pSysInfo->SystemPage = _LCM_NONE;
+                }
+            }
+            break;
+            case S_PREPARING_FOR_EV: { // 等待車端的通訊 (EV 小板),待車端回報後,開始樁端的測試
+                if (isModeChange(gun_index)) {
+                    log_info("S_PREPARING_FOR_EV================================== %x \n", gun_index);
+                    //strcpy((char *)pSysConfig->UserId, "");
+                    StopGunInfoTimeoutDet(gun_index);
+                    StartGunInfoTimeoutDet(gun_index, Timeout_EvChargingDet);
+                }
+
+                if (pDcChargingInfo->Type == _Type_Chademo) {
+                    // 檢查車端的槍鎖是否為鎖上
+                    if (isEvGunLocked_chademo(gun_index) == YES) {
+                        setChargerMode(gun_index, MODE_PREPARE_FOR_EVSE);
+                    }
+                } else if (pDcChargingInfo->Type == _Type_GB) {
+                    // 檢查車端的 charging enable 是否為 1
+                    if (isEvGunLocked_gb(gun_index) == YES) {
+                        setChargerMode(gun_index, MODE_PREPARE_FOR_EVSE);
+                    }
+                } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                    // 檢查車端的 charging enable 是否為 1
+                    if (isEvGunLocked_ccs(gun_index) == YES) {
+                        setChargerMode(gun_index, MODE_PREPARE_FOR_EVSE);
+                    }
+                }
+
+                if ((evBoardStopState = isEvBoardStopChargeFlag(gun_index)) > 0) {
+                    // 板端要求停止 (錯誤)
+                    if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL) {
+                        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "EVDisconnected");
+                    }
+
+                    if (evBoardStopState == EV_BOARD_STOP_CHARGING) {
+                        ChargingAlarmProcess(gun_index);
+                    } else if (evBoardStopState == POWER_CABINET_STOP_CHARGING) {
+                        ChargingTerminalProcess(gun_index);
+                    }
+                } else if (isEvBoardNormalStopChargeFlag(gun_index) == YES) {
+                    // 板端要求停止 (正常)
+                    if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL) {
+                        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "EVDisconnected");
+                    }
+                    ChargingTerminalProcess(gun_index);
+                } else if (OcppRemoteStop(gun_index) == YES ||
+                           WifiScheduleStop(gun_index)) {
+                    // 後臺要求停止
+                    ChargingTerminalProcess(gun_index);
+                }
+
+                // LCM => Pre-charging
+                if (pSysInfo->CurGunSelected == gun_index) {
+                    pSysInfo->ConnectorPage = _LCM_PRE_CHARGE;
+                    // pSysInfo->SystemPage = _LCM_NONE;
+                }
+            }
+            break;
+            case S_PREPARING_FOR_EVSE: { // 等待 RB 通訊及測試,並將狀態回報, CSU 確認 Pass 後,開始進入充電
+                if (isModeChange(gun_index)) {
+                    log_info("S_PREPARING_FOR_EVSE================================== %x \n", gun_index);
+                    StopGunInfoTimeoutDet(gun_index);
+                    StartGunInfoTimeoutDet(gun_index, Timeout_EvseChargingDet);
+                }
+
+                if (pDcChargingInfo->Type == _Type_Chademo) {
+                    // 檢查樁端的 GFD 結果
+                    if (isPrechargeStatus_chademo(gun_index) > 5 && isPrechargeStatus_chademo(gun_index) < 8) {
+                        // 當前操作的槍號,進入 Charging
+                        setChargerMode(gun_index, MODE_CHARGING);
+                    }
+
+                    if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                        // GFD 錯誤停止
+                        RecordAlarmCode(gun_index, "012234");
+                    } else if (pDcChargingInfo->GroundFaultStatus == GFD_WARNING) {
+                        // GFD 警告
+                        RecordWarningCode(gun_index, "012296");
+                    }
+                } else if (pDcChargingInfo->Type == _Type_GB) {
+                    // 檢查樁端的 GFD 結果
+                    //if (isPrechargeStatus_gb(gun_index) > 5 && isPrechargeStatus_gb(gun_index) < 9) {
+                    if (isPrechargeStatus_gb(gun_index) > 9) {
+                        setChargerMode(gun_index, MODE_CHARGING);
+                    }
+
+                    if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                        // GFD 錯誤停止
+                        RecordAlarmCode(gun_index, "012236");
+                    } else if (pDcChargingInfo->GroundFaultStatus == GFD_WARNING) {
+                        // GFD 警告
+                        RecordWarningCode(gun_index, "012298");
+                    }
+                } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                    // 檢查樁端的 GFD 結果
+                    if ((pDcChargingInfo->GroundFaultStatus == GFD_PASS ||
+                            pDcChargingInfo->GroundFaultStatus == GFD_WARNING)) {
+                        setChargerMode(gun_index, MODE_CCS_PRECHARGE_STEP0);
+                    }
+
+                    if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                        // GFD 錯誤停止
+                        RecordAlarmCode(gun_index, "012235");
+                    } else if (pDcChargingInfo->GroundFaultStatus == GFD_WARNING) {
+                        // GFD 警告
+                        RecordWarningCode(gun_index, "012297");
+                    }
+                }
+
+                if ((evBoardStopState = isEvBoardStopChargeFlag(gun_index)) > 0) {
+                    // 板端要求停止 (錯誤)
+                    if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL) {
+                        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "EVDisconnected");
+                    }
+
+                    if (evBoardStopState == EV_BOARD_STOP_CHARGING) {
+                        ChargingAlarmProcess(gun_index);
+                    } else if (evBoardStopState == POWER_CABINET_STOP_CHARGING) {
+                        ChargingTerminalProcess(gun_index);
+                    }
+                } else if (isEvBoardNormalStopChargeFlag(gun_index) == YES) {
+                    // 板端要求停止 (正常)
+                    if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL) {
+                        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "EVDisconnected");
+                    }
+                    ChargingTerminalProcess(gun_index);
+                } else if (OcppRemoteStop(gun_index) == YES ||
+                           WifiScheduleStop(gun_index)) {
+                    // 後臺要求停止
+                    ChargingTerminalProcess(gun_index);
+                }
+
+                // LCM => Pre-charging
+                if (pSysInfo->CurGunSelected == gun_index) {
+                    pSysInfo->ConnectorPage = _LCM_PRE_CHARGE;
+                    // pSysInfo->SystemPage = _LCM_NONE;
+                }
+            }
+            break;
+            case S_CHARGING: { // 剛進入充電狀態,等待 EV 小板要求的輸出電流後開始輸出
+                if (isModeChange(gun_index)) {
+                    log_info("S_CHARGING================================== %x \n", gun_index);
+                    StopGunInfoTimeoutDet(gun_index);
+                    ftime(&startChargingTime[gun_index]);
+                    strcpy((char *)ShmOCPP16Data->StartTransaction[gun_index].ResponseIdTagInfo.Status, ""); //DS60-120 add
+                    ChangeStartOrStopDateTime(YES, gun_index);
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                    OcppStartTransation(gun_index);
+#endif //!defined DD360 && !defined DD360Audi
+                }
+
+                if (ShmOCPP16Data->CpMsg.bits[gun_index].StartTransactionConf) {
+                    ShmOCPP16Data->CpMsg.bits[gun_index].StartTransactionConf = NO;
+                }
+                ftime(&endChargingTime[gun_index]);
+                pDcChargingInfo->PresentChargedDuration = DiffTimeb(startChargingTime[gun_index], endChargingTime[gun_index]);
+
+                if (pDcChargingInfo->Type == _Type_Chademo) {
+                    if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                        // GFD 錯誤停止
+                        RecordAlarmCode(gun_index, "012234");
+                    }
+                    //else if (((pDcChargingInfo->EvBatterytargetVoltage * 10) > 0 && pDcChargingInfo->EvBatterytargetVoltage < SYSTEM_MIN_VOL) ||
+                    //           (pDcChargingInfo->PresentChargedDuration >= 10 && pDcChargingInfo->PresentChargingVoltage < SYSTEM_MIN_VOL)) {
+                    //    // UVP
+                    //    RecordAlarmCode(gun_index, "012289");
+                    //    ChargingTerminalProcess(gun_index);
+                    //}
+                    else if (pDcChargingInfo->GroundFaultStatus == GFD_WARNING) {
+                        // GFD 警告
+                        RecordWarningCode(gun_index, "012296");
+                    }
+                } else if (pDcChargingInfo->Type == _Type_GB) {
+                    if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                        // GFD 錯誤停止
+                        RecordAlarmCode(gun_index, "012236");
+                    }
+                    //else if (isPrechargeStatus_gb(gun_index) == 10 &&
+                    //           (((pDcChargingInfo->EvBatterytargetVoltage * 10) > 0 && pDcChargingInfo->EvBatterytargetVoltage < SYSTEM_MIN_VOL) ||
+                    //            (pDcChargingInfo->PresentChargedDuration >= 10 && pDcChargingInfo->PresentChargingVoltage < SYSTEM_MIN_VOL))) {
+                    //    // UVP
+                    //    RecordAlarmCode(gun_index, "012290");
+                    //    ChargingTerminalProcess(gun_index);
+                    //}
+                    else if (pDcChargingInfo->GroundFaultStatus == GFD_WARNING) {
+                        // GFD 警告
+                        RecordWarningCode(gun_index, "012298");
+                    }
+                } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                    if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                        // GFD 錯誤停止
+                        RecordAlarmCode(gun_index, "012235");
+                    }
+                    //else if (((pDcChargingInfo->EvBatterytargetVoltage * 10) > 0 && pDcChargingInfo->EvBatterytargetVoltage < SYSTEM_MIN_VOL) ||
+                    //           (pDcChargingInfo->PresentChargedDuration >= 10 && pDcChargingInfo->PresentChargingVoltage < SYSTEM_MIN_VOL)) {
+                    //    // UVP
+                    //    RecordAlarmCode(gun_index, "012288");
+                    //    ChargingTerminalProcess(gun_index);
+                    //}
+                    else if (pDcChargingInfo->GroundFaultStatus == GFD_WARNING) {
+                        // GFD 警告
+                        RecordWarningCode(gun_index, "012297");
+                    }
+                }
+
+                if ((evBoardStopState = isEvBoardStopChargeFlag(gun_index)) > 0) {
+                    // 板端要求停止 (錯誤)
+                    if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL) {
+                        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "EVDisconnected");
+                    }
+                    //printf("%d evBoardStopState = %d\r\n", gun_index, evBoardStopState);
+                    if (evBoardStopState == EV_BOARD_STOP_CHARGING) {
+                        ChargingAlarmProcess(gun_index);
+                    } else if (evBoardStopState == POWER_CABINET_STOP_CHARGING) {
+                        ChargingTerminalProcess(gun_index);
+                    }
+                } else if (isEvBoardNormalStopChargeFlag(gun_index) == YES) {
+                    // 板端要求停止 (正常)
+                    if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL) {
+                        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "EVDisconnected");
+                    }
+                    ChargingTerminalProcess(gun_index);
+                } else if (OcppRemoteStop(gun_index) == YES ||
+                           WifiScheduleStop(gun_index) ||
+                           CheckBackendChargingTimeout(gun_index) ||
+                           CheckBackendChargingEnergy(gun_index) ||
+                           strcmp((char *)ShmOCPP16Data->StartTransaction[gun_index].ResponseIdTagInfo.Status, "Invalid") == EQUAL) {
+
+                    // 後臺要求停止
+                    ChargingTerminalProcess(gun_index);
+                }
+
+                // LCM => Charging
+                if (pSysInfo->CurGunSelected == gun_index) {
+                    pSysInfo->ConnectorPage = _LCM_CHARGING;
+                    // pSysInfo->SystemPage = _LCM_NONE;
+                }
+            }
+            break;
+            case S_ALARM:
+            case S_TERMINATING: {
+                if (isModeChange(gun_index)) {
+                    if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL) {
+                        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "Local");
+                    }
+
+                    if (pDcChargingInfo->SystemStatus == S_ALARM) {
+                        log_info("================== S_ALARM (%x) ================ \n", gun_index);
+                        UpdateErrorCodeToOcpp(gun_index);
+
+                        if (strcmp((char *)pDcChargingInfo->StartDateTime, "") != EQUAL) {
+                            OcppStopTransation(gun_index);
+                        }
+
+                        TheEndCharging(gun_index);
+                    } else {
+                        log_info("================== S_TERMINATING (%x) ================ \n", gun_index);
+                    }
+
+                    //log_info ("terminating......................... %x \n", gun_index);
+                    StopGunInfoTimeoutDet(gun_index);
+                }
+
+                if (pDcChargingInfo->Type == _Type_Chademo) {
+                    // 非車端的停止 : 需等待小板送出停止指令,讓車端解除槍
+                    //if (isEvStopCharging_chademo(gun_index) == YES) {
+                    //    /*+++ 20200908, vern, disable it for DD360 +++*/
+                    //    /*if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL)
+                    //        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "Local");*/
+                    //    /*--- 20200908, vern, disable it for DD360 ---*/
+                    //}
+
+                    if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                        // GFD 錯誤停止
+                        RecordAlarmCode(gun_index, "012234");
+                    } else if (pDcChargingInfo->GroundFaultStatus == GFD_WARNING) {
+                        // GFD 警告
+                        RecordWarningCode(gun_index, "012296");
+                    }
+
+                    //if (isEvStopCharging_chademo(gun_index) == YES ||
+                    //        isPrechargeStatus_chademo(gun_index) <= 0) {
+                    //    setChargerMode(gun_index, MODE_COMPLETE);
+                    //}
+                } else if (pDcChargingInfo->Type == _Type_GB) {
+                    //log_info("************ GB lock Status = %d, status = %d \n",
+                    //         isEvStopCharging_gb(gun_index),
+                    //         isPrechargeStatus_gb(gun_index));
+
+                    // 非車端的停止 : 需等待小板送出停止指令,讓車端解除槍
+                    //if (isEvStopCharging_chademo(gun_index) == YES) {
+                    //    /*+++ 20200908, vern, disable it for DD360 +++*/
+                    //    /*if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL)
+                    //            strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "Local");*/
+                    //    /*--- 20200908, vern, disable it for DD360 ---*/
+                    //}
+
+                    if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                        // GFD 錯誤停止
+                        RecordAlarmCode(gun_index, "012236");
+                    } else if (pDcChargingInfo->GroundFaultStatus == GFD_WARNING) {
+                        // GFD 警告
+                        RecordWarningCode(gun_index, "012298");
+                    }
+
+                    //if (isEvStopCharging_gb(gun_index) == YES ||
+                    //        isPrechargeStatus_gb(gun_index) <= 0) {
+                    //    setChargerMode(gun_index, MODE_COMPLETE);
+                    //}
+                } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                    // 非車端的停止 : 需等待小板送出停止指令,讓車端解除槍
+                    //if (isEvStopCharging_chademo(gun_index) == YES) {
+                    //    /*+++ 20200908, vern, disable it for DD360 +++*/
+                    //    /*if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL)
+                    //            strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "Local");*/
+                    //    /*--- 20200908, vern, disable it for DD360 ---*/
+                    //}
+
+                    if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                        // GFD 錯誤停止
+                        RecordAlarmCode(gun_index, "012235");
+                    } else if (pDcChargingInfo->GroundFaultStatus == GFD_WARNING) {
+                        // GFD 警告
+                        RecordWarningCode(gun_index, "012297");
+                    }
+
+                    //if (isEvStopCharging_ccs(gun_index) == YES &&
+                    //        (isPrechargeStatus_ccs(gun_index) >= 53 || isPrechargeStatus_ccs(gun_index) == 0 ||
+                    //         isPrechargeStatus_ccs(gun_index) == 13 || isPrechargeStatus_ccs(gun_index) == 14)) {
+                    //    setChargerMode(gun_index, MODE_COMPLETE);
+                    //}
+                }
+
+                if (pDcChargingInfo->SystemStatus == S_ALARM) {
+                    if (pDcChargingInfo->ConnectorPlugIn == NO &&
+                            GetTimeoutValue(pDcChargingInfo->TimeoutTimer) >= 10000000) {
+                        setChargerMode(gun_index, MODE_IDLE);
+                    }
+                } else {
+                    if (pDcChargingInfo->Type == _Type_Chademo) {
+                        if (isEvStopCharging_chademo(gun_index) == YES ||
+                                isPrechargeStatus_chademo(gun_index) <= 0) {
+                            setChargerMode(gun_index, MODE_COMPLETE);
+                        }
+                    } else if (pDcChargingInfo->Type == _Type_GB) {
+                        if (isEvStopCharging_gb(gun_index) == YES ||
+                                isPrechargeStatus_gb(gun_index) <= 0) {
+                            setChargerMode(gun_index, MODE_COMPLETE);
+                        }
+                    } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                        if (isEvStopCharging_ccs(gun_index) == YES &&
+                                (isPrechargeStatus_ccs(gun_index) >= 53 || isPrechargeStatus_ccs(gun_index) == 0 ||
+                                 isPrechargeStatus_ccs(gun_index) == 13 || isPrechargeStatus_ccs(gun_index) == 14)) {
+                            setChargerMode(gun_index, MODE_COMPLETE);
+                        }
+                    }
+                }
+
+                // 車端的停止
+                //if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL) {
+                //    strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "EVDisconnected");
+                //}
+
+                if (pSysInfo->CurGunSelected == gun_index) {
+                    pSysInfo->ConnectorPage = _LCM_COMPLETE;
+                    // pSysInfo->SystemPage = _LCM_NONE;
+                }
+            }
+            break;
+            case S_COMPLETE: {
+                if (isModeChange(gun_index)) {
+                    log_info ("complete......................... %x \n", gun_index);
+                    if (strcmp((char *)pDcChargingInfo->StartDateTime, "") != EQUAL) {
+                        OcppStopTransation(gun_index);
+                    }
+
+                    TheEndCharging(gun_index);
+                    //ftime(&endChargingTime[gun_index]);
+                    //if (pDcChargingInfo->PresentChargedDuration != 0) {
+                    //    pDcChargingInfo->PresentChargedDuration = DiffTimeb(startChargingTime[gun_index], endChargingTime[gun_index]);
+                    //}
+
+                    //StopGunInfoTimeoutDet(gun_index);
+                    //StartGunInfoTimeoutDet(gun_index, Timeout_EvseCompleteDet);
+                    //ChangeStartOrStopDateTime(NO, gun_index);
+                }
+
+                //if (((pDcChargingInfo->ConnectorPlugIn == NO) ||
+                //        (restartFlag == 1)) &&
+                //        (GetTimeoutValue(pDcChargingInfo->TimeoutTimer) >= 10000000)) {
+                //    setChargerMode(gun_index, MODE_IDLE);
+                //    destroySelGun(gun_index); //Jerry add
+                //}
+
+                if (pDcChargingInfo->ConnectorPlugIn == NO &&
+                        GetTimeoutValue(pDcChargingInfo->TimeoutTimer) >= 10000000) {
+                    setChargerMode(gun_index, MODE_IDLE);
+#if defined DD360Audi
+                    destroySelGun(gun_index); //Jerry add
+#endif //defined DD360Audi
+                }
+
+                if (pSysInfo->CurGunSelected == gun_index) {
+                    pSysInfo->ConnectorPage = _LCM_COMPLETE;
+                    // pSysInfo->SystemPage = _LCM_NONE;
+                }
+            }
+            break;
+            case S_CCS_PRECHARGE_ST0: {
+                if (isModeChange(gun_index)) {
+                    log_info("CCS Precharge Processing 1....................%x \n", gun_index);
+                    StopGunInfoTimeoutDet(gun_index);
+                    StartGunInfoTimeoutDet(gun_index, Timeout_ForCcsPrechargeDet);
+                }
+
+                if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                    // GFD 錯誤停止
+                    RecordAlarmCode(gun_index, "012235");
+                }
+
+                if ((evBoardStopState = isEvBoardStopChargeFlag(gun_index)) > 0) {
+                    // 板端要求停止 (錯誤)
+                    if (evBoardStopState == EV_BOARD_STOP_CHARGING) {
+                        ChargingAlarmProcess(gun_index);
+                    } else if (evBoardStopState == POWER_CABINET_STOP_CHARGING) {
+                        ChargingTerminalProcess(gun_index);
+                    }
+                } else if (isEvBoardNormalStopChargeFlag(gun_index) == YES) {
+                    // 板端要求停止 (正常)
+                    ChargingTerminalProcess(gun_index);
+                } else if (OcppRemoteStop(gun_index) == YES ||
+                           WifiScheduleStop(gun_index)) {
+                    // 後臺要求停止
+                    ChargingTerminalProcess(gun_index);
+                }
+
+                // 等待 EV 小板 (CCS) 通知可以開始 Precharge
+                // 切換 D+ Relay to Precharge Relay
+                if (isPrechargeStatus_ccs(gun_index) == 39 || isPrechargeStatus_ccs(gun_index) == 40) {
+                    if (pDcChargingInfo->RelayKPK2Status == YES && pDcChargingInfo->PrechargeStatus != PRECHARGE_READY)
+                        //if (pDcChargingInfo->PrechargeStatus != PRECHARGE_PRERELAY_PASS)
+                    {
+                        //log_info("Send precharge ready 1..........%x, status = %d \n", gun_index, isPrechargeStatus_ccs(gun_index));
+                        if (isPrechargeStatus_ccs(gun_index) == 39) {
+                            log_info("Conn %x, Precharge ready, CCS status = PreChargeResponse (%d) \n", gun_index, isPrechargeStatus_ccs(gun_index));
+                        } else if (isPrechargeStatus_ccs(gun_index) == 40) {
+                            log_info("Conn %x, Precharge ready, CCS status = PowerDeliveryRequest start (%d) \n", gun_index, isPrechargeStatus_ccs(gun_index));
+                        }
+
+                        pDcChargingInfo->PrechargeStatus = PRECHARGE_READY;
+                    }
+                } else if (isPrechargeStatus_ccs(gun_index) == 45 || isPrechargeStatus_ccs(gun_index) == 46) {
+                    setChargerMode(gun_index, MODE_CCS_PRECHARGE_STEP1);
+                }
+
+                if (pSysInfo->CurGunSelected == gun_index) {
+                    pSysInfo->ConnectorPage = _LCM_PRE_CHARGE;
+                    // pSysInfo->SystemPage = _LCM_NONE;
+                }
+                break;
+            }
+            case S_CCS_PRECHARGE_ST1: {
+                if (isModeChange(gun_index)) {
+                    log_info("CCS Precharge Processing 2....................%x \n", gun_index);
+                }
+
+                if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                    // GFD 錯誤停止
+                    RecordAlarmCode(gun_index, "012235");
+                }
+
+                if ((evBoardStopState = isEvBoardStopChargeFlag(gun_index)) > 0) {
+                    // 板端要求停止 (錯誤)
+                    if (evBoardStopState == EV_BOARD_STOP_CHARGING) {
+                        ChargingAlarmProcess(gun_index);
+                    } else if (evBoardStopState == POWER_CABINET_STOP_CHARGING) {
+                        ChargingTerminalProcess(gun_index);
+                    }
+
+                } else if (isEvBoardNormalStopChargeFlag(gun_index) == YES) {
+                    // 板端要求停止 (正常)
+                    ChargingTerminalProcess(gun_index);
+                } else if (OcppRemoteStop(gun_index) == YES ||
+                           WifiScheduleStop(gun_index)) {
+                    // 後臺要求停止
+                    ChargingTerminalProcess(gun_index);
+                }
+
+                // 等待小板通知進入充電
+                // 切換 D+ Relay to Precharge Relay
+                if (pDcChargingInfo->RelayK1K2Status == YES) {
+                    pDcChargingInfo->PrechargeStatus = PRECHARGE_READY;
+                    setChargerMode(gun_index, MODE_CHARGING);
+                }
+
+                if (pSysInfo->CurGunSelected == gun_index) {
+                    pSysInfo->ConnectorPage = _LCM_PRE_CHARGE;
+                    // pSysInfo->SystemPage = _LCM_NONE;
+                }
+                break;
+            }
+            }
+        }
+
+#if defined DD360Audi
+        if (pSysInfo->SystemPage != _LCM_SELECT_GUN) {
+#else
+        if (pSysInfo->SystemPage != _LCM_NONE) {
+#endif //defined DD360Audi
+            ChangeLcmByIndex(pSysInfo->SystemPage);
+        } else {
+            bool dcPageRun = false;
+            if (pGunIndexInfo->AcGunIndex > 0 && pSysInfo->CurGunSelectedByAc != NO_DEFINE) {
+                pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(0);
+
+                if  (pAcChargingInfo->SystemStatus == S_IDLE) {
+                    ChangeLcmByIndex(_LCM_IDLE);
+                } else if (pAcChargingInfo->SystemStatus == S_PREPARNING) {
+                    ChangeLcmByIndex(_LCM_PRE_CHARGE);
+                } else if (pAcChargingInfo->SystemStatus == S_CHARGING) {
+                    ChangeLcmByIndex(_LCM_CHARGING);
+                } else if (pAcChargingInfo->SystemStatus == S_TERMINATING ||
+                           pAcChargingInfo->SystemStatus == S_COMPLETE) {
+                    ChangeLcmByIndex(_LCM_COMPLETE);
+                } else {
+                    dcPageRun = true;
+                }
+            } else {
+                dcPageRun = true;
+            }
+
+            if (dcPageRun) {
+                ChangeLcmByIndex(pSysInfo->ConnectorPage);
+            }
+        }
+
+        for (uint8_t gun_index = 0; gun_index < pSysConfig->TotalConnectorCount; gun_index++) {
+            pDcChargingInfo =  (struct ChargingInfoData *)GetDcChargingInfoData(gun_index);
+
+            checkEvBoardAlarmState(pDcChargingInfo->Type);
+        }
+
+        //write(wtdFd, "a", 1);
+        //WriteWatchDogState("a");
+
+        usleep(whileLoopTime);
+    }
+
+    return FAIL;
+}

+ 29 - 9
EVSE/Projects/DD360Audi/Apps/main.h → EVSE/Projects/DD360Audi/Apps/CSU/main.h

@@ -28,7 +28,7 @@
 #define DEFAULT_AC_INDEX                        2
 #define PSU_MIN_CUR                             100
 
-#define DB_FILE                                 "/Storage/ChargeLog/localCgargingRecord.db"
+//#define DB_FILE                                 "/Storage/ChargeLog/localCgargingRecord.db"
 
 #define uSEC_VAL                                1000000
 #define SELFTEST_TIMEOUT                        60//45
@@ -43,9 +43,9 @@
 #define GUN_COMP_WAIT_TIMEOUT                   10
 #define GUN_PRECHARGING_TIMEOUT                 60
 
-#define log_info(format, args...) StoreLogMsg_1("[%s:%d][%s][Info] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
-#define log_warn(format, args...) StoreLogMsg_1("[%s:%d][%s][Warn] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
-#define log_error(format, args...) StoreLogMsg_1("[%s:%d][%s][Error] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+//#define log_info(format, args...) StoreLogMsg_1("[%s:%d][%s][Info] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+//#define log_warn(format, args...) StoreLogMsg_1("[%s:%d][%s][Warn] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+//#define log_error(format, args...) StoreLogMsg_1("[%s:%d][%s][Error] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
 
 //------------------------------------------------------------------------------
 typedef struct StLedConfig {
@@ -61,18 +61,38 @@ typedef struct StLedConfig {
 } LedConfig;
 
 //------------------------------------------------------------------------------
-bool isDetectPlugin();
-void _DetectPlugInTimeout();
-void StopSystemTimeoutDet();
+bool isDetectPlugin(void);
+void _DetectPlugInTimeout(void);
+void StartSystemTimeoutDet(uint8_t flag);
+void StopSystemTimeoutDet(void);
 
 void StartGunInfoTimeoutDet(uint8_t gunIndex, uint8_t flag);
 void StopGunInfoTimeoutDet(uint8_t gunIndex);
 
-void ClearAuthorizedFlag();
+void AuthorizingStart(void);
+bool IsAuthorizingMode(void);
+bool isAuthorizedComplete(void);
+void ClearAuthorizedFlag(void);
 
 void ChargingAlarmProcess(uint8_t gunIndex);
 void StopChargingProcessByString(uint8_t level);
 
-void AcChargingTerminalProcess();
+void EmcOccureByString(char *code);
+void ReleaseEmsOccureByString(uint8_t index, char *code);
+
+void confirmSelGun(uint8_t selGun);
+void destroySelGun(uint8_t curGun);
+int getConfirmSelectedGun(uint8_t curSel);
+void setSelGunWaitToAuthor(uint8_t curSel);
+
+void ChargingTerminalProcess(uint8_t gunIndex);
+void AcChargingTerminalProcess(void);
+
+void ChangeGunSelectByIndex(uint8_t sel);
+
+void setChargerMode(uint8_t gun_index, uint8_t mode);
+
+void KillAllTask(void);
+void KillTask(void);
 
 #endif /* _MAIN_H_ */

File diff suppressed because it is too large
+ 282 - 256
EVSE/Projects/DD360Audi/Apps/CSU/mainNew.c


+ 2 - 0
EVSE/Projects/DD360Audi/Apps/Config.h

@@ -317,6 +317,8 @@ typedef struct StDcCommonInfo {
     uint8_t CheckRelayStatus[6]; //check Relay welding or driving fault
     uint8_t GunRelayWeldingOccur[2];
     uint8_t GunRelayDrivingOccur[2];
+    uint8_t SystemModeChange;
+    uint8_t Reserved[3];
 } DcCommonInfo;
 
 #endif /* CONFIG_H_ */

+ 54 - 53
EVSE/Projects/DD360Audi/Apps/DataBase/DataBase.c

@@ -9,7 +9,16 @@
 #include "../ShareMemory/shmMem.h"
 
 //------------------------------------------------------------------------------
-int DB_Open(sqlite3 *db)
+#define DB_FILE                                 "/Storage/ChargeLog/localCgargingRecord.db"
+
+//------------------------------------------------------------------------------
+static sqlite3 *localDb;
+
+//------------------------------------------------------------------------------
+//===============================================
+// SQLite3 related routine
+//===============================================
+int DB_Open(void)
 {
     int result = PASS;
     char *errMsg = NULL;
@@ -49,21 +58,21 @@ int DB_Open(sqlite3 *db)
                             "`idx` INTEGER PRIMARY KEY AUTOINCREMENT, "
                             "`rebootDatetime` TEXT NOT NULL, unique(rebootDatetime) on conflict replace);";
 
-    if (sqlite3_open(DB_FILE, &db)) {
+    if (sqlite3_open(DB_FILE, &localDb)) {
         result = FAIL;
-        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(db));
-        sqlite3_close(db);
+        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(localDb));
+        sqlite3_close(localDb);
     } else {
         log_info( "Local charging record database open successfully.\r\n");
 
-        if (sqlite3_exec(db, createRecordSql, 0, 0, &errMsg) != SQLITE_OK) {
+        if (sqlite3_exec(localDb, createRecordSql, 0, 0, &errMsg) != SQLITE_OK) {
             result = FAIL;
             log_info( "Create local charging record table error message: %s\n", errMsg);
         } else {
             log_info( "Opened local charging record table successfully\n");
         }
 
-        if (sqlite3_exec(db, createCfgSql, 0, 0, &errMsg) != SQLITE_OK) {
+        if (sqlite3_exec(localDb, createCfgSql, 0, 0, &errMsg) != SQLITE_OK) {
             result = FAIL;
             log_info( "Create local config table error message: %s\n", errMsg);
         } else {
@@ -71,14 +80,14 @@ int DB_Open(sqlite3 *db)
         }
 
         //DS60-120
-        if (sqlite3_exec(db, createrecordSql, 0, 0, &errMsg) != SQLITE_OK) {
+        if (sqlite3_exec(localDb, createrecordSql, 0, 0, &errMsg) != SQLITE_OK) {
             result = FAIL;
             log_info( "Create local record table error message: %s\n", errMsg);
         } else {
             log_info( "Opened local record table successfully\n");
         }
 
-        if (sqlite3_exec(db, createrebootSql, 0, 0, &errMsg) != SQLITE_OK) {
+        if (sqlite3_exec(localDb, createrebootSql, 0, 0, &errMsg) != SQLITE_OK) {
             result = FAIL;
             log_info( "Create reboot record table error message: %s\n", errMsg);
         } else {
@@ -86,49 +95,41 @@ int DB_Open(sqlite3 *db)
         }
         //-----
 
-        sqlite3_close(db);
+        sqlite3_close(localDb);
     }
 
     return result;
 }
 
-int DB_Insert_Record(sqlite3 *db, int gun_index)
+int DB_Insert_Record(int gun_index)
 {
     int result = PASS;
     char *errMsg = NULL;
     char insertSql[1024];
+    struct ChargingInfoData *pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun_index);
+    struct OCPP16Data *ShmOCPP16Data = (struct OCPP16Data *)GetShmOCPP16Data();
 
     sprintf(insertSql, "insert into charging_record(reservationId, transactionId, startMethod, userId, dateTimeStart, dateTimeStop, socStart, socStop, chargeEnergy, stopReason) "
             "values('%d', '%d', '%d', '%s', '%s', '%s', '%d', '%d', '%f', '%s');",
-            chargingInfo[gun_index]->ReservationId, //DS60-120 add
+            pDcChargingInfo->ReservationId, //DS60-120 add
             ShmOCPP16Data->StartTransaction[gun_index].ResponseTransactionId,
-            chargingInfo[gun_index]->StartMethod,
-            chargingInfo[gun_index]->StartUserId,
-            chargingInfo[gun_index]->StartDateTime,
-            chargingInfo[gun_index]->StopDateTime,
-            chargingInfo[gun_index]->EvBatteryStartSoc,
-            chargingInfo[gun_index]->EvBatterySoc,
-            chargingInfo[gun_index]->PresentChargedEnergy,
-            //DS60-120 remove
-            //ShmSysConfigAndInfo->SysInfo.AcChargingData[gun_index].ReservationId,
-            //ShmOCPP16Data->StartTransaction[gun_index].ResponseTransactionId,
-            //ShmSysConfigAndInfo->SysInfo.AcChargingData[gun_index].StartMethod,
-            //ShmSysConfigAndInfo->SysInfo.AcChargingData[gun_index].StartUserId,
-            //ShmSysConfigAndInfo->SysInfo.AcChargingData[gun_index].StartDateTime,
-            //ShmSysConfigAndInfo->SysInfo.AcChargingData[gun_index].StopDateTime,
-            //ShmSysConfigAndInfo->SysInfo.AcChargingData[gun_index].EvBatterySoc,
-            //ShmSysConfigAndInfo->SysInfo.AcChargingData[gun_index].EvBatterySoc,
-            //ShmSysConfigAndInfo->SysInfo.AcChargingData[gun_index].PresentChargedEnergy,
+            pDcChargingInfo->StartMethod,
+            pDcChargingInfo->StartUserId,
+            pDcChargingInfo->StartDateTime,
+            pDcChargingInfo->StopDateTime,
+            pDcChargingInfo->EvBatteryStartSoc,
+            pDcChargingInfo->EvBatterySoc,
+            pDcChargingInfo->PresentChargedEnergy,
             ShmOCPP16Data->StopTransaction[gun_index].StopReason);
 
     //if (sqlite3_open("/Storage/ChargeLog/localCgargingRecord.db", &db)) {
-    if (sqlite3_open(DB_FILE, &db)) { //DS60-120 add
+    if (sqlite3_open(DB_FILE, &localDb)) { //DS60-120 add
         result = FAIL;
-        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(db));
-        sqlite3_close(db);
+        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(localDb));
+        sqlite3_close(localDb);
     } else {
         log_info( "Local charging record database open successfully.\r\n");
-        if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
+        if (sqlite3_exec(localDb, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
             result = FAIL;
             log_info( "Insert local charging record error message: %s\n", errMsg);
         } else {
@@ -137,50 +138,50 @@ int DB_Insert_Record(sqlite3 *db, int gun_index)
 
         //DS60-120 add
         sprintf(insertSql, "delete from charging_record where idx < (select idx from charging_record order by idx desc limit 1)-2000;");
-        if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
+        if (sqlite3_exec(localDb, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
             result = FAIL;
             log_info( "delete local charging error message: %s\n", errMsg);
         } else {
             log_info( "delete local charging record successfully\n");
         }
 
-        sqlite3_close(db);
+        sqlite3_close(localDb);
     }
 
     return result;
 }
 
-int DB_Update_Operactive(sqlite3 *db, uint8_t gun_index, uint8_t IsAvailable)
+int DB_Update_Operactive(uint8_t gun_index, uint8_t IsAvailable)
 {
     uint8_t result = false;
     char *errMsg = NULL;
     char sqlStr[1024];
     srand(time(NULL));
 
-    if (sqlite3_open(DB_FILE, &db)) {
+    if (sqlite3_open(DB_FILE, &localDb)) {
         result = FAIL;
-        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(db));
-        sqlite3_close(db);
+        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(localDb));
+        sqlite3_close(localDb);
     } else {
         log_info( "Local charging record database open successfully (%d).\r\n", IsAvailable);
 
         //sprintf(sqlStr, "insert or replace into config (IsAvailable, connector, val) values('IsAvailable', %d, %d);", gun_index, IsAvailable);
         sprintf(sqlStr, "insert or replace into config (item, connector, val) values('IsAvailable', %d, %d);", gun_index, IsAvailable); //DS60-120 add
         log_info("sqlStr= %s\r\n", sqlStr);
-        if (sqlite3_exec(db, sqlStr, 0, 0, &errMsg) != SQLITE_OK) {
+        if (sqlite3_exec(localDb, sqlStr, 0, 0, &errMsg) != SQLITE_OK) {
             result = FAIL;
             log_info( "update config error message: %s\n", errMsg);
         } else {
             log_info("update connector-%d config item isOperactive to %d\r\n", gun_index, IsAvailable);
         }
 
-        sqlite3_close(db);
+        sqlite3_close(localDb);
     }
 
     return result;
 }
 
-int DB_Get_Operactive(sqlite3 *db, uint8_t gun_index)
+int DB_Get_Operactive(uint8_t gun_index)
 {
     uint8_t result = true;
     char *errMsg = NULL;
@@ -192,13 +193,13 @@ int DB_Get_Operactive(sqlite3 *db, uint8_t gun_index)
     sprintf(sqlStr, "select * from config where item='IsAvailable' and connector=%d;", gun_index); //DS60-120 add
     //DEBUG_INFO("sqlStr= %s\r\n", sqlStr);
 
-    if (sqlite3_open(DB_FILE, &db)) {
+    if (sqlite3_open(DB_FILE, &localDb)) {
         result = FAIL;
-        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(db));
-        sqlite3_close(db);
+        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(localDb));
+        sqlite3_close(localDb);
     } else {
         log_info( "Local config query database open successfully.\r\n");
-        sqlite3_get_table(db, sqlStr, &rs, &rows, &cols, &errMsg);
+        sqlite3_get_table(localDb, sqlStr, &rs, &rows, &cols, &errMsg);
         if (rows > 0) {
             for (int idxRow = 1; idxRow <= rows; idxRow++) {
                 if (strcmp(rs[(idxRow * cols) + 3], "0") == 0) {
@@ -211,13 +212,13 @@ int DB_Get_Operactive(sqlite3 *db, uint8_t gun_index)
         }
 
         sqlite3_free_table(rs);
-        sqlite3_close(db);
+        sqlite3_close(localDb);
     }
 
     return result;
 }
 
-int DB_Reboot_Record(sqlite3 *db)
+int DB_Reboot_Record(void)
 {
     int result = PASS;
     char *errMsg = NULL;
@@ -225,13 +226,13 @@ int DB_Reboot_Record(sqlite3 *db)
 
     sprintf(insertSql, "insert into reboot_record(rebootDatetime) values(CURRENT_TIMESTAMP);");
 
-    if (sqlite3_open(DB_FILE, &db)) {
+    if (sqlite3_open(DB_FILE, &localDb)) {
         result = FAIL;
-        log_info( "Can't open database: %s\n", sqlite3_errmsg(db));
-        sqlite3_close(db);
+        log_info( "Can't open database: %s\n", sqlite3_errmsg(localDb));
+        sqlite3_close(localDb);
     } else {
         log_info( "Local charging record database open successfully.\n");
-        if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
+        if (sqlite3_exec(localDb, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
             result = FAIL;
             log_info( "Insert reboot record error message: %s\n", errMsg);
         } else {
@@ -239,14 +240,14 @@ int DB_Reboot_Record(sqlite3 *db)
         }
 
         sprintf(insertSql, "delete from reboot_record where idx < (select idx from charging_record order by idx desc limit 1)-2000;");
-        if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
+        if (sqlite3_exec(localDb, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
             result = FAIL;
             log_info( "delete reboot record error message: %s\n", errMsg);
         } else {
             log_info( "delete reboot record successfully\n");
         }
 
-        sqlite3_close(db);
+        sqlite3_close(localDb);
     }
 
     return result;

+ 15 - 10
EVSE/Projects/DD360Audi/Apps/Makefile

@@ -16,6 +16,7 @@ INC_FLAGS += -I $(TOP)/Define
 INC_FLAGS += -I $(TOP)/Log
 INC_FLAGS += -I $(TOP)/ShareMemory
 INC_FLAGS += -I $(TOP)/CSU
+INC_FLAGS += -I $(TOP)/DataBase
 INC_FLAGS += -I $(TOP)/ModuleInternalComm
 INC_FLAGS += -I $(TOP)/ModuleEvComm
 INC_FLAGS += -I $(TOP)/ModulePrimary
@@ -27,6 +28,7 @@ DefineLib = $(TOP)/Define
 LogLib = $(TOP)/Log
 ShmMemLib = $(TOP)/ShareMemory
 CSULib = $(TOP)/CSU
+DataBaseLib = $(TOP)/DataBase
 InternalCommLib = $(TOP)/ModuleInternalComm
 EvCommLib = $(TOP)/ModuleEvComm
 PrimaryLib = $(TOP)/ModulePrimary
@@ -62,10 +64,13 @@ COMMON_OBJ_FILES = common.o \
 					$(DefineLib)/define.o \
 					$(ShmMemLib)/shmMem.o \
 					$(LogLib)/log.o \
-					$(SelectGunLib)/SelectGun.o
-#main
-MAIN_OBJ_FILES = $(COMMON_OBJ_FILES) $(SQLite3_H) $(ModuleUpgrade_H) $(RFID_H) $(Lib_Module_RatedCurrent) \
-					main.o $(CSULib)/Primary.o
+					$(SelectGunLib)/SelectGun.o \
+
+
+MAIN_OBJ_FILES = $(COMMON_OBJ_FILES) $(DataBaseLib)/DataBase.o \
+					$(CSULib)/main.o  $(CSULib)/Primary.o $(CSULib)/WatchDog.o $(CSULib)/ZipFile.o \
+					$(CSULib)/RFID.o $(CSULib)/SelfTest.o $(CSULib)/UpgradeFW.o \
+					$(CSULib)/Ethernet.o
 MAIN_SRC_FILES = $(patsubst %.o, %.c, $(MAIN_OBJ_FILES))
 %.o: %.c
 	$(CC) $(CFLAGS) -c $<
@@ -95,8 +100,8 @@ apps: MainTask DoCommTask EvCommTask \
 				FactoryConfigApp OtherTools CleanExec
 
 MainTask:
-	#$(CC) $(DEFINE) $(MAIN_SRC_FILES) $(CFLAGS) $(TFLAGS) $(INC_FLAGS) ${Lib_Module_RFID} \
-	#	 ${Lib_Module_Upgrade} ${Lib_SQLite3} $(Lib_Module_RatedCurrent) -o main
+	#$(CC) $(DEFINE) $(MAIN_SRC_FILES) $(CFLAGS) $(TFLAGS) $(INC_FLAGS) $(SQLite3_H) $(ModuleUpgrade_H) $(RateCurrent_H) \
+	#	$(RFID_H) $(Lib_Module_RFID) $(Lib_Module_Upgrade) $(Lib_SQLite3) $(Lib_Module_RateCurrent) -o main
 	$(CC) $(DEFINE) $(SQLite3_H) $(ModuleUpgrade_H) $(RFID_H) $(RatedCurrent_H) $(CFLAGS) -c -o main.o main.c
 	$(CC) $(DEFINE) $(SQLite3_H) $(ModuleUpgrade_H) $(RFID_H) $(RatedCurrent_H) $(CFLAGS) -c -o timeout.o timeout.c
 	$(CC) $(DEFINE) $(CFLAGS) -c -o common.o common.c
@@ -108,10 +113,10 @@ DoCommTask:
 	$(CC) -o Module_DoComm DoComm.o define.o
 
 EvCommTask:
-	$(CC) $(DEFINE) $(EVCOMM_SRC_FILES) $(CFLAGS) $(TFLAGS) $(INC_FLAGS) $(Lib_Module_RatedCurrent) -o Module_EvComm
-	#$(CC) $(DEFINE) $(CFLAGS) $(RatedCurrent_H) -c -o Ev_Comm.o $(EvCommLib)/Ev_Comm.c
-	#$(CC) $(DEFINE) $(CFLAGS) $(RatedCurrent_H) -c -o Module_EvComm.o $(EvCommLib)/Module_EvComm.c
-	#$(CC) -o Module_EvComm Ev_Comm.o Module_EvComm.o $(Lib_Module_RatedCurrent)
+	#$(CC) $(DEFINE) $(EVCOMM_SRC_FILES) $(CFLAGS) $(TFLAGS) $(INC_FLAGS) $(Lib_Module_RatedCurrent) -o Module_EvComm
+	$(CC) $(DEFINE) $(CFLAGS) $(RatedCurrent_H) -c -o Ev_Comm.o $(EvCommLib)/Ev_Comm.c
+	$(CC) $(DEFINE) $(CFLAGS) $(RatedCurrent_H) -c -o Module_EvComm.o $(EvCommLib)/Module_EvComm.c
+	$(CC) -o Module_EvComm Ev_Comm.o Module_EvComm.o $(Lib_Module_RatedCurrent)
 
 EventLoggingTask:
 	$(CC) $(DEFINE) $(CFLAGS) -c -o define.o $(DefineLib)/define.c

+ 2 - 2
EVSE/Projects/DD360Audi/Apps/ModuleEvComm/Module_EvComm.c

@@ -2228,7 +2228,7 @@ static float ReadAdcVolt(uint8_t AdcChannel)
     //AIN3=pilot voltage
     int fd = -1;
     uint8_t str[64] = {0};
-    uint8_t AdcValue[4] = {0};
+    uint8_t AdcValue[8] = {'\0'};
 
     if (AdcChannel > 7) {
         return -1;
@@ -2240,7 +2240,7 @@ static float ReadAdcVolt(uint8_t AdcChannel)
 
     close(fd);
 
-    return (1.8 * atoi((int)AdcValue)) / 4095;
+    return (1.8 * atoi((char *)&AdcValue[0])) / 4095;
 }
 
 static void getChillerTemperature(ChillerTemp *chillerTemp)

+ 31 - 29
EVSE/Projects/DD360Audi/Apps/ModuleEvComm/Module_EvRxComm.c

@@ -96,22 +96,22 @@ static float ReadAdcVolt(uint8_t AdcChannel)
     //AIN2=CCS_Proximity/2
     //AIN3=pilot voltage
     int fd = -1;
-    uint8_t str[64];
-    uint8_t AdcValue[4];
+    uint8_t str[64] = {0};
+    uint8_t AdcValue[8] = {'\0'};
+    //uint32_t AdcValue = 0;
 
     if (AdcChannel > 7) {
         return -1;
     }
 
-    memset(str, 0, sizeof(str));
-    memset(AdcValue, 0, sizeof(AdcValue));
     sprintf((char *)str, "/sys/bus/iio/devices/iio\:device0/in_voltage%d_raw", AdcChannel);
     fd = open((char *)str, O_RDONLY);
     read(fd, AdcValue, 4);
 
     close(fd);
 
-    return (1.8 * atoi((int)AdcValue)) / 4095;
+    return (1.8 * atoi((char *)&AdcValue[0])) / 4095;
+    //return (1.8 * atoi((char *)&AdcValue)) / 4095;
 }
 
 static void getChillerTemperature(ChillerTemp *chillerTemp)
@@ -124,14 +124,14 @@ static void getChillerTemperature(ChillerTemp *chillerTemp)
         adcVoltage = 0.0;
         adcVoltage =  ReadAdcVolt(i);
         if ((adcVoltage <= 0.9) && (adcVoltage >= 0.8)) { //0 ~ -40
-            chillerTemp->Temp[i] = ((adcVoltage - 0.908) * 500) + 60;
+            pChillerTemp->Temp[i] = ((adcVoltage - 0.908) * 500) + 60;
             //log_info("1 adcVoltage = %f", (adcVoltage - 0.9) * 500);
         } else if ((adcVoltage <= 1.07) && (adcVoltage > 0.9)) {
-            chillerTemp->Temp[i] = ((adcVoltage - 0.91) * 705.88) + 60;
+            pChillerTemp->Temp[i] = ((adcVoltage - 0.91) * 705.88) + 60;
             //log_info("2 adcVoltage = %f", (adcVoltage - 0.9) * 500);
-        } /*else {
-            chillerTemp->Temp[i] = 195;
-        }*/
+        } else {
+            pChillerTemp->Temp[i] = 195;
+        }
 
         //CcsConnectorTemp1 = ReadAdcVolt(i);
         //if ((CcsConnectorTemp1 <= 0.9) && (CcsConnectorTemp1 >= 0.8)) { //0 ~ -40
@@ -182,7 +182,6 @@ static void AddrAssignment(uint8_t *data)
     //}
 }
 
-
 void CANReceiver(int fd)
 {
     pid_t canRecPid;
@@ -211,7 +210,7 @@ void CANReceiver(int fd)
         ShmCHAdeMOData = (struct CHAdeMOData *)GetShmCHAdeMOData();
         ShmGBTData = (struct GBTData *)GetShmGBTData();
         ShmCcsData = (struct CcsData *)GetShmCcsData();
-        ShmDcCommonData = (DcCommonInfo *)GetShmDcCommonInfo();
+        ShmDcCommonData = (DcCommonInfo *)GetShmDcCommonData();
 
         while (isContinue) {
             memset(&frame, 0, sizeof(struct can_frame));
@@ -493,23 +492,26 @@ void CANReceiver(int fd)
                     //         pDcChargingInfo->ConnectorTemp);
                 }
 #endif //0
-                //log_info("EvboardStatus = %x \n",
-                //         ShmCHAdeMOData->evse[gunTypeIndex].EvboardStatus);
-                //log_info("ConnectorPlug locked = %x \n",
-                //         frame.data[0]);
-
-                //if (frame.data[1] >= GUN_OTP_VALUE ||
-                //        frame.data[2] >= GUN_OTP_VALUE ||
-                //        chiilerTemp.Temp[0] >= GUN_OTP_VALUE ||
-                //        chiilerTemp.Temp[1] >= GUN_OTP_VALUE) {
-                //    log_info("Conn %d Temp 0= %d, Temp 1 = %d, chillerTemp1 = %d, chillerTemp2 = %d\r\n",
-                //             targetGun,
-                //             frame.data[1],
-                //             frame.data[2],
-                //             chiilerTemp.Temp[0],
-                //             chiilerTemp.Temp[1]);
-                //}
-                //log_info("PilotVoltage = %x \n", (-120 + frame.data[3]) / 10);
+                if (ShmDcCommonData->SystemModeChange == YES) {
+                    ShmDcCommonData->SystemModeChange = NO;
+                    //log_info("EvboardStatus = %x \n",
+                    //         ShmCHAdeMOData->evse[gunTypeIndex].EvboardStatus);
+                    //log_info("ConnectorPlug locked = %x \n",
+                    //         frame.data[0]);
+
+                    //if (frame.data[1] >= GUN_OTP_VALUE ||
+                    //        frame.data[2] >= GUN_OTP_VALUE ||
+                    //        chiilerTemp.Temp[0] >= GUN_OTP_VALUE ||
+                    //        chiilerTemp.Temp[1] >= GUN_OTP_VALUE) {
+                    log_info("Conn %d Temp 0= %d, Temp 1 = %d, chillerTemp1 = %d, chillerTemp2 = %d\r\n",
+                             targetGun,
+                             frame.data[1],
+                             frame.data[2],
+                             chiilerTemp.Temp[0],
+                             chiilerTemp.Temp[1]);
+                    //}
+                    //log_info("PilotVoltage = %x \n", (-120 + frame.data[3]) / 10);
+                }
                 break;
 
             case ACK_EVSE_ISOLATION_STATUS:

+ 2 - 2
EVSE/Projects/DD360Audi/Apps/ModuleEvComm/Module_EvTxComm.c

@@ -484,7 +484,7 @@ static void checkConnectorOVPState(uint8_t gunIndex)
     struct ChargingInfoData *pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
 
     // 避免槍溫偵測誤判
-    static uint8_t gunTempAllowCount[2] = {0, 0};
+    static uint8_t gunTempAllowCount[2] = {0};
     bool isOTP = false;
 
     switch (pDcChargingInfo->Type) {
@@ -593,7 +593,7 @@ int main(int argc, char *argv[])
     pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
     pAlarmCode = (struct AlarmCodeData *)GetShmAlarmCodeData();
     pFaultCode = (struct FaultCodeData *)GetShmFaultCodeData();
-    ShmDcCommonData = (DcCommonInfo *)GetShmDcCommonInfo();
+    ShmDcCommonData = (DcCommonInfo *)GetShmDcCommonData();
     ShmCHAdeMOData = (struct CHAdeMOData *)GetShmCHAdeMOData();
     ShmGBTData = (struct GBTData *)GetShmGBTData();
     ShmCcsData = (struct CcsData *)GetShmCcsData();

+ 2 - 1
EVSE/Projects/DD360Audi/Apps/ModuleInternalComm/RelayBoard.c

@@ -1131,7 +1131,7 @@ void RelayBoardTask(int uartFD)
         pAlarmCode = (struct AlarmCodeData *)GetShmAlarmCodeData();
         ShmRelayModuleData = (struct RelayModuleData *)GetShmRelayModuleData();
         ShmPsuData = (struct PsuData *)GetShmPsuData();
-        ShmDcCommonData = (DcCommonInfo *)GetShmDcCommonInfo();
+        ShmDcCommonData = (DcCommonInfo *)GetShmDcCommonData();
         ShmPrimaryMcuData = (struct PrimaryMcuData *)GetShmPrimaryMcuData();
 
         Uart5Fd = uartFD;
@@ -1284,6 +1284,7 @@ void RelayBoardTask(int uartFD)
                     //regRelay.relay_event.bits.Gun1_Parallel_N = outputRelay.relay_event.bits.Gun1_Parallel_N;
 
                     //MatchRelayStatus();
+
                     //log_info("Match Relay, AC = %x, g1_p = %x, g1_n = %x, g2_p = %x, g2_n = %x, pre = %x, bri_p = %x, bri_n = %x \n",
                     //         regRelay.relay_event.bits.AC_Contactor,
                     //         regRelay.relay_event.bits.Gun1_P,

+ 22 - 12
EVSE/Projects/DD360Audi/Apps/ShareMemory/shmMem.c

@@ -40,7 +40,7 @@ static struct LedModuleData *ShmLedModuleData = NULL;
 static struct OCPP16Data *ShmOCPP16Data = NULL;
 
 static SelectGunInfo *ShmSelectGunInfo = NULL;
-static DcCommonInfo *ShmDcCommonInfo = NULL;
+static DcCommonInfo *ShmDcCommonData = NULL;
 
 static struct ChargingInfoData *DcChargingData[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY] = {NULL};
 static struct ChargingInfoData *AcChargingData[AC_QUANTITY] = {NULL};
@@ -51,7 +51,7 @@ static GunIndexInfo gGunIndexInfo = {0};
 //struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
 //struct WARNING_CODE_INFO *pSysWarning = (struct WARNING_CODE_INFO *)GetShmSysWarningInfo();
 
-//struct AlarmCodeData *pAlarmCode =(struct AlarmCodeData *)GetShmAlarmCodeData();
+//struct AlarmCodeData *pAlarmCode = (struct AlarmCodeData *)GetShmAlarmCodeData();
 //struct InfoCodeData *pInfoCode = (struct InfoCodeData *)GetShmInfoCodeData();
 //struct FaultCodeData *pFaultCode = (struct FaultCodeData *)GetShmFaultCodeData();
 
@@ -68,7 +68,10 @@ static GunIndexInfo gGunIndexInfo = {0};
 //struct OCPP16Data *ShmOCPP16Data = (struct OCPP16Data *)GetShmOCPP16Data();
 
 //SelectGunInfo *ShmSelectGunInfo = (SelectGunInfo *)GetShmSelectGunInfo();
-//DcCommonInfo *ShmDcCommonInfo = (DcCommonInfo *)GetShmDcCommonInfo();
+//DcCommonInfo *ShmDcCommonData = (DcCommonInfo *)GetShmDcCommonData();
+
+//struct ChargingInfoData *pDcChargingInfo = NULL;
+//struct ChargingInfoData *pAcChargingInfo = NULL;
 
 //------------------------------------------------------------------------------
 void *GetGunIndexInfo(void)
@@ -306,17 +309,17 @@ void *GetShmSelectGunInfo(void)
     return ShmSelectGunInfo;
 }
 
-void *GetShmDcCommonInfo(void)
+void *GetShmDcCommonData(void)
 {
-    if (ShmDcCommonInfo == NULL) {
+    if (ShmDcCommonData == NULL) {
         return NULL;
     }
 
-    return ShmDcCommonInfo;
+    return ShmDcCommonData;
 }
 
 //------------------------------------------------------------------------------
-/*static void initialGunIndexToUnUse(void)
+static void initialGunIndexToUnUse(void)
 {
     uint8_t index = 0;
     struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
@@ -337,7 +340,6 @@ void *GetShmDcCommonInfo(void)
         pSysInfo->AcChargingData[index].Index = NO_DEFINE;
     }
 }
-*/
 
 #if 0
 static void getFirmwareVersion(void)
@@ -424,7 +426,7 @@ static void getFirmwareVersion(void)
 }
 #endif //0
 
-void InitialShareMemoryParameter(void)
+void InitialShareMemoryInfo(void)
 {
     FILE *fp = NULL;
     char cmd[512] = {0};
@@ -532,7 +534,15 @@ void InitialShareMemoryParameter(void)
     pAlarmCode->AlarmEvents.bits.ModelNameNoneMatchStestFail = NO;
     pAlarmCode->AlarmEvents.bits.PsuNoResource = NO;
     pAlarmCode->AlarmEvents.bits.FailToCreateShareMemory = NO;
-    //initialGunIndexToUnUse();//DS60-120 add
+
+    initialGunIndexToUnUse();//DS60-120 add
+
+    //ShmDcCommonData->CcsVersion = _CCS_VERSION_CHECK_TAG_V015S0;
+    //ShmDcCommonData->psuKeepCommunication = NO;
+    //ShmDcCommonData->acContactSwitch = NO;
+    ShmDcCommonData->ConnectErrList[0].GunErrMessage = 0;
+    ShmDcCommonData->ConnectErrList[1].GunErrMessage = 0;
+    //ShmDcCommonData->LcmFwVersion = 0;
 }
 
 int InitSelectGunShmMem(void)
@@ -558,7 +568,7 @@ int InitCommonShmMem(void)
 
     if ((MeterSMId = shmget(ShmCommonKey, sizeof(DcCommonInfo), IPC_CREAT | 0777)) < 0) {
         return FAIL;
-    } else if ((ShmDcCommonInfo = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+    } else if ((ShmDcCommonData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
         return FAIL;
     }
 
@@ -750,7 +760,7 @@ void ClearAllShmMemParameter(void)
     //memset(ShmOCPP16Data,0,sizeof(struct OCPP16Data));
 
     //memset(ShmCsuMeterInfo, 0, sizeof(struct MeterInformation));
-    memset(ShmDcCommonInfo, 0, sizeof(DcCommonInfo));
+    memset(ShmDcCommonData, 0, sizeof(DcCommonInfo));
 
 #if defined DD360 || defined DD360Audi || defined DD360ComBox
     memset(ShmSelectGunInfo, 0, sizeof(SelectGunInfo));

+ 1 - 4
EVSE/Projects/DD360Audi/Apps/ShareMemory/shmMem.h

@@ -28,7 +28,7 @@ bool MappingGunChargingInfo(char *whichTask);
 
 int CreateAllCsuShareMemory(void);
 void ClearAllShmMemParameter(void);
-void InitialShareMemoryParameter(void);
+void InitialShareMemoryInfo(void);
 
 void SetDcChargingInfoData(uint8_t index, struct ChargingInfoData *chargingInfoIndex);
 void *GetDcChargingInfoData(uint8_t index);
@@ -66,8 +66,5 @@ void MappingChargingInfoData(void);
 
 void *GetShmSelectGunInfo(void);
 
-void *GetShmDcCommonInfo(void);
-
-
 int InitSelectGunShmMem(void);
 #endif /* _CSU_SHARE_MEMORY_H_ */

+ 60 - 3
EVSE/Projects/DD360Audi/Apps/main.c

@@ -27,12 +27,12 @@
 #include <ctype.h>
 #include <ifaddrs.h>
 #include <math.h>
-#include "./Define/define.h"
+#include "../../define.h"
 #include <stdbool.h>
 #include <dirent.h>
 
 #include "Config.h"
-#include "main.h"
+//#include "main.h"
 #include "common.h"
 #include "timeout.h"
 
@@ -40,6 +40,62 @@
 #include "./SelectGun/SelectGun.h"
 #endif //defined DD360Audi
 
+//------------------------------------------------------------------------------
+#define MODELNAME_FAIL                          0
+#define BUFFER_SIZE                             128
+#define BTN_RELEASE                             0
+#define BTN_PRESS                               1
+#define MAX_BUF                                 64
+#define MtdBlockSize                            0x600000
+#define SYSFS_GPIO_DIR                          "/sys/class/gpio"
+#define UPGRADE_FAN                             0x02
+#if defined DD360 ||defined DD360Audi || defined DD360ComBox
+#define UPGRADE_RB                              0x09 //0x09 for DD360 dispenser
+#else
+#define UPGRADE_RB                              0x03 //other module use
+#endif //defined DD360 || defined DD360Audi
+#define UPGRADE_PRI                             0x04
+#define UPGRADE_AC                              0x05
+#define UPGRADE_LED                             0x06
+#define SYSTEM_MIN_VOL                          80 //150
+#define MIN_OUTPUT_CUR                          0
+#define AC_OUTPUT_VOL                           220
+
+#define DEFAULT_AC_INDEX                        2
+#define PSU_MIN_CUR                             100
+
+#define DB_FILE                                 "/Storage/ChargeLog/localCgargingRecord.db"
+
+#define uSEC_VAL                                1000000
+#define SELFTEST_TIMEOUT                        60//45
+#define AUTHORIZE_TIMEOUT                       15//30
+#define AUTHORIZE_COMP_TIMEOUT                  3
+#define AUTHORIZE_FAIL_TIMEOUT                  3
+#define AUTHORIZE_STOP_TIMEOUT                  30
+#define RETURN_TO_CHARGING_PAGE                 30
+#define GUN_PREPARE_TIMEOUT                     30
+#define GUN_EV_WAIT_TIMEOUT                     120
+#define GUN_EVSE_WAIT_TIMEOUT                   60
+#define GUN_COMP_WAIT_TIMEOUT                   10
+#define GUN_PRECHARGING_TIMEOUT                 60
+
+#define log_info(format, args...) StoreLogMsg_1("[%s:%d][%s][Info] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+#define log_warn(format, args...) StoreLogMsg_1("[%s:%d][%s][Warn] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+#define log_error(format, args...) StoreLogMsg_1("[%s:%d][%s][Error] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+
+//------------------------------------------------------------------------------
+typedef struct StLedConfig {
+    //OutputDrvValue[0]
+    uint8_t LeftButtonLed: 1;                   //bit 0,    H: ON,      L:OFF
+    uint8_t RightButtonLed: 1;                  //bit 1,    H: ON,      L:OFF
+    uint8_t GreenLED: 1;                        //bit 2,    H: ON,      L:OFF
+    uint8_t YellowLED: 1;                       //bit 3,    H: ON,      L:OFF
+    uint8_t RedLED: 1;                          //bit 4,    H: ON,      L:OFF
+    uint8_t SystemLed4: 1;                      //bit 5,    H: ON,      L:OFF
+    uint8_t AcContactor: 1;                     //bit 6,    H: ON,      L:OFF
+    uint8_t Reserved: 1;                        //bit 7 reserved
+} LedConfig;
+
 //------------------------------------------------------------------------------
 char *valid_Internet[2] = {"8.8.8.8", "180.76.76.76"};
 uint8_t mask_table[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
@@ -306,7 +362,8 @@ static void checkGunOTPState(uint8_t _index)
     case _Type_CCS_2:
         // CCS 不管甚麼輸出都會有槍溫偵測!!~
         if (chargingInfo[_index]->ConnectorTemp != UNDEFINED_TEMP) {
-            ResetChargerAlarmCode(_index, "011019");
+            ResetChargerAlarmCode(_index, "011019"); //清除溫度檢測異常status code
+
             if (chargingInfo[_index]->ConnectorTemp >= GUN_OTP_VALUE) {
                 RecordAlarmCode(_index, "012230");
             } else if (chargingInfo[_index]->ConnectorTemp != 0 &&

二進制
EVSE/Projects/DD360Audi/Images/ramdisk.gz


二進制
EVSE/Projects/DD360Audi/output/Module_DoComm


二進制
EVSE/Projects/DD360Audi/output/Module_EvComm


二進制
EVSE/Projects/DD360Audi/output/Module_EventLogging


二進制
EVSE/Projects/DD360Audi/output/Module_InternalComm


二進制
EVSE/Projects/DD360Audi/output/Module_LcmControl


二進制
EVSE/Projects/DD360Audi/output/Module_PrimaryComm


二進制
EVSE/Projects/DD360Audi/output/main


+ 0 - 17
EVSE/Projects/DD360ComBox/Apps/CSU/AcPlug.c

@@ -1,17 +0,0 @@
-#include <stdio.h>      /*標準輸入輸出定義*/
-#include <stdlib.h>     /*標準函數庫定義*/
-#include <string.h>
-#include <stdint.h>
-
-#include "../Config.h"
-#include "../Log/log.h"
-#include "../Define/define.h"
-#include "../ShareMemory/shmMem.h"
-
-//------------------------------------------------------------------------------
-void AcChargingTerminalProcess(void)
-{
-    struct ChargingInfoData *pAcChargingInfoData = (struct ChargingInfoData *)GetAcChargingInfoData(0);
-
-    pAcChargingInfoData->SystemStatus = MODE_TERMINATING;
-}

+ 278 - 0
EVSE/Projects/DD360ComBox/Apps/CSU/Ethernet.c

@@ -0,0 +1,278 @@
+#include <stdio.h>      /*標準輸入輸出定義*/
+#include <stdlib.h>     /*標準函數庫定義*/
+#include <string.h>
+#include <stdint.h>
+
+#include "../Config.h"
+#include "../Log/log.h"
+#include "../Define/define.h"
+#include "../ShareMemory/shmMem.h"
+
+#include "../common.h"
+
+//------------------------------------------------------------------------------
+void GetMacAddress(void)
+{
+    uint8_t index = 0;
+    struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
+
+    for (index = 0; index < 2; index++) {
+        int fd;
+        struct ifreq ifr;
+        char tarEth[5];
+        char Mac[18];
+
+        sprintf(tarEth, "eth%d", index);
+        fd = socket(AF_INET, SOCK_DGRAM, 0);
+
+        ifr.ifr_addr.sa_family = AF_INET;
+        strncpy(ifr.ifr_name, tarEth, IFNAMSIZ - 1);
+
+        ioctl(fd, SIOCGIFHWADDR, &ifr);
+        close(fd);
+
+        sprintf(Mac, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
+                ifr.ifr_hwaddr.sa_data[0],
+                ifr.ifr_hwaddr.sa_data[1],
+                ifr.ifr_hwaddr.sa_data[2],
+                ifr.ifr_hwaddr.sa_data[3],
+                ifr.ifr_hwaddr.sa_data[4],
+                ifr.ifr_hwaddr.sa_data[5]
+               );
+
+        if (index == 0) {
+            strcpy((char *) pSysConfig->Eth0Interface.EthMacAddress, Mac);
+        } else {
+            strcpy((char *) pSysConfig->Eth1Interface.EthMacAddress, Mac);
+        }
+    }
+}
+
+static int isRouteFail(void)
+{
+    int result = YES;
+    FILE *fp;
+    char buf[512];
+
+    fp = popen("route -n", "r");
+    if (fp != NULL) {
+        while (fgets(buf, sizeof(buf), fp) != NULL) {
+            if (strstr(buf, "eth0") != NULL) {
+                result = NO;
+            }
+        }
+    }
+    pclose(fp);
+
+    return result;
+}
+
+static int isReachableInternet(void)
+{
+    int result = FAIL;
+    FILE *fp;
+    char cmd[256];
+    char buf[512];
+    char tmp[512];
+    struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
+    struct AlarmCodeData *pAlarmCode = (struct AlarmCodeData *)GetShmAlarmCodeData();
+
+    strcpy(cmd, "ifconfig eth0");
+    fp = popen(cmd, "r");
+
+    if (fp != NULL) {
+        while (fgets(buf, sizeof(buf), fp) != NULL) {
+            if (strstr(buf, "inet addr:") > 0) {
+                sscanf(buf, "%*s%s", tmp);
+                substr(tmp, tmp, strspn(tmp, "addr:"), strlen(buf) - strspn(tmp, "addr:"));
+
+                if (strcmp(tmp, (char *)pSysConfig->Eth0Interface.EthIpAddress) != EQUAL) {
+                    strcpy((char *) pSysConfig->Eth0Interface.EthIpAddress, tmp);
+                }
+            }
+        }
+    }
+    pclose(fp);
+
+#if defined DD360 ||defined DD360Audi || defined DD360ComBox
+    if (pAlarmCode->AlarmEvents.bits.DisconnectedFromDo == NORMAL) {
+        result = FAIL;
+    } else {
+        result = PASS;
+    }
+#else
+    memset(buf, 0x00, sizeof(buf));
+    for (int idx = 0; idx < ARRAY_SIZE(valid_Internet); idx++) {
+        sprintf(cmd, "ping -c 1 -w 3 -I eth0 %s", valid_Internet[idx]);
+        fp = popen(cmd, "r");
+        if (fp != NULL) {
+            while (fgets(buf, sizeof(buf), fp) != NULL) {
+                if (strstr(buf, "transmitted") > 0) {
+                    //sscanf(buf, "%*s%*s%*s%*s%*s%*s%s", tmp);
+
+                    if (strstr(buf, "100%") != NULL) {
+                    } else {
+                        result = PASS;
+                    }
+                    //DEBUG_INFO("%s",buf);
+                    //DEBUG_INFO("%s\n",tmp);
+                }
+            }
+        }
+        pclose(fp);
+    }
+
+#endif //defined DD360 || defined DD360Audi
+
+    return result;
+}
+
+void InitEthernet(void)
+{
+    char tmpbuf[256];
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+    bool ethResult = false;
+    uint8_t cnt_pingDNS_Fail = 0;
+#endif //!defined DD360 && !defined DD360Audi
+
+    struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
+
+    system("ifconfig eth0 down");// eth0 down
+    system("ifconfig eth1 down");// eth1 down
+    sleep(2);
+
+    // /sbin/ifconfig eth0 192.168.1.10 netmask 255.255.255.0 down
+    system("echo 1 > /sys/class/gpio/gpio110/value");//reset PHY
+    sleep(2);
+    //Init Eth0 for internet
+    memset(tmpbuf, 0, 256);
+    sprintf(tmpbuf, "/sbin/ifconfig eth0 %s netmask %s up",
+            pSysConfig->Eth0Interface.EthIpAddress,
+            pSysConfig->Eth0Interface.EthSubmaskAddress);
+    //sprintf(tmpbuf,"/sbin/ifconfig eth0 192.168.100.10 netmask 255.255.255.0 up");
+    system(tmpbuf);
+
+    memset(tmpbuf, 0, 256);
+    sprintf(tmpbuf, "route add default gw %s eth0 ",
+            pSysConfig->Eth0Interface.EthGatewayAddress);
+    //sprintf(tmpbuf,"route add default gw 192.168.100.1 eth0 ");
+    system(tmpbuf);
+    //system("ifconfig lo up");
+    //  /sbin/ifconfig eth0 192.168.1.10 netmask 255.255.255.0 up
+    //Init Eth1 for administrator tool
+    memset(tmpbuf, 0, 256);
+    sprintf(tmpbuf, "/sbin/ifconfig eth1 %s netmask %s up",
+            pSysConfig->Eth1Interface.EthIpAddress,
+            pSysConfig->Eth1Interface.EthSubmaskAddress);
+    system(tmpbuf);
+
+    //Run DHCP client if enabled
+    system("killall udhcpc");
+    system("rm -rf /etc/resolv.conf");
+    system("echo nameserver 8.8.8.8 > /etc/resolv.conf");       //Google DNS server
+    system("echo nameserver 180.76.76.76 > /etc/resolv.conf");  //Baidu DNS server
+    //system("/sbin/ifconfig eth0 down;/sbin/ifconfig eth0 up");
+
+    if (pSysConfig->Eth0Interface.EthDhcpClient == 0) {
+        sprintf(tmpbuf, "/sbin/udhcpc -i eth0 -x hostname:CSU3_%s -s /root/dhcp_script/eth0.script > /dev/null &",
+                pSysConfig->SystemId);
+        system(tmpbuf);
+    }
+
+    //Upgrade system id to /etc/hostname
+    sprintf(tmpbuf, "echo %s > /etc/hostname", pSysConfig->SystemId);
+    system(tmpbuf);
+
+    pid_t pid = fork();
+    if (pid == 0) {
+        log_info("InitEthernet = %d\r\n", pid);
+        for (;;) {
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+            if (isRouteFail()) {
+                //log_info("eth0 not in route, restart eht0. \n");
+                system("/sbin/ifconfig eth0 down;/sbin/ifconfig eth0 up");
+
+                if (pSysConfig->Eth0Interface.EthDhcpClient == 0) {
+                    InitialDHCP();
+                }
+            }
+
+            if (isReachableInternet() == PASS) {
+                pSysInfo->ethInternetConn = YES;
+                cnt_pingDNS_Fail = 0;
+            } else {
+                if (++cnt_pingDNS_Fail > 3) {
+                    pSysInfo->ethInternetConn = NO;
+                }
+            }
+
+            ethResult = pSysInfo->ethInternetConn;
+
+            if (ethResult == YES) {
+                system("/sbin/ifmetric eth0 0");
+
+                if ((pSysConfig->ModelName[10] == 'W') ||
+                        (pSysConfig->ModelName[10] == 'D')) {
+                    system("/sbin/ifmetric mlan0 1");
+                }
+
+                if ((pSysConfig->ModelName[10] == 'T') ||
+                        (pSysConfig->ModelName[10] == 'D')) {
+                    system("/sbin/ifmetric ppp0 2");
+                }
+            }
+
+            if (!ethResult &&
+                    pSysConfig->AthInterface.WifiMode != _SYS_WIFI_MODE_DISABLE &&
+                    (pSysConfig->ModelName[10] == 'W' ||
+                     pSysConfig->ModelName[10] == 'D')) {
+                //ethResult = pSysConfig->AthInterface.WifiNetworkConn;
+                ethResult = pInfoCode->InfoEvents.bits.InternetDisconnectViaWiFi == YES ? NO : YES;
+
+                if (ethResult) {
+                    if ((pSysConfig->ModelName[10] == 'W') ||
+                            (pSysConfig->ModelName[10] == 'D')) {
+                        system("/sbin/ifmetric eth0 1");
+                        system("/sbin/ifmetric mlan0 0");
+                    }
+
+
+                    if ((pSysConfig->ModelName[10] == 'T') ||
+                            (pSysConfig->ModelName[10] == 'D')) {
+                        system("/sbin/ifmetric ppp0 2");
+                    }
+                }
+            }
+
+            if (!ethResult &&
+                    pSysConfig->TelecomInterface.TelcomEnabled == YES &&
+                    (pSysConfig->ModelName[10] == 'T' ||
+                     pSysConfig->ModelName[10] == 'D')) {
+                //ethResult = pSysConfig->TelecomInterface.TelcomNetworkConn;
+                ethResult = pInfoCode->InfoEvents.bits.InternetDisconnectVia4Gi == YES ? NO : YES;
+
+                if (ethResult) {
+                    if ((pSysConfig->ModelName[10] == 'W') ||
+                            (pSysConfig->ModelName[10] == 'D')) {
+                        system("/sbin/ifmetric mlan0 2");
+                    }
+
+                    if ((pSysConfig->ModelName[10] == 'T') ||
+                            (pSysConfig->ModelName[10] == 'D')) {
+                        system("/sbin/ifmetric eth0 1");
+                        system("/sbin/ifmetric ppp0 0");
+                    }
+                }
+            }
+
+            pSysInfo->InternetConn = ethResult;
+#else
+            isReachableInternet();
+#endif //!defined DD360 && !defined DD360
+
+            sleep(5);
+        }
+    }
+
+    log_info("Initial Ethernet OK\r\n");
+}

+ 0 - 0
EVSE/Projects/DD360ComBox/Apps/CSU/Gpio.c


+ 56 - 129
EVSE/Projects/DD360ComBox/Apps/CSU/Primary.c

@@ -42,22 +42,22 @@ void PrimaryLedIndicatorCtrlFork(void)
     if (pid == 0) {
         uint8_t gunIndex = 0;
         int isContinue = 1;
-        LedConfig *pLedConfig = NULL;
+
         struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
         struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
-        struct WARNING_CODE_INFO *pSysWarningInfo = (struct WARNING_CODE_INFO *)GetShmSysWarningInfo();
+        struct WARNING_CODE_INFO *pSysWarning = (struct WARNING_CODE_INFO *)GetShmSysWarningInfo();
         struct PrimaryMcuData *ShmPrimaryMcuData = (struct PrimaryMcuData *)GetShmPrimaryMcuData();
-        struct ChargingInfoData *pDcChargingInfoData = NULL;
+        struct ChargingInfoData *pDcChargingInfo = NULL;
 
-        pLedConfig = (LedConfig *)&ShmPrimaryMcuData->OutputDrv.OutputDrvValue[0];
+        LedConfig *pLedConfig = (LedConfig *)&ShmPrimaryMcuData->OutputDrv.OutputDrvValue[0];
 
         while (isContinue) {
             for (gunIndex = 0; gunIndex < pSysConfig->TotalConnectorCount; gunIndex++) {
-                pDcChargingInfoData = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+                pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
 
-                //printf("led indicator status = %d\r\n", pDcChargingInfoData->SystemStatus);
-                //printf("level = %d\r\n", pSysWarningInfo->Level);
-                switch (pDcChargingInfoData->SystemStatus) {
+                //printf("led indicator status = %d\r\n", chargingInfo[gunIndex]->SystemStatus);
+                //printf("level = %d\r\n", pSysWarning->Level);
+                switch (pDcChargingInfo->SystemStatus) {
                 case S_BOOTING:
                     if (pSysInfo->SelfTestSeq == _STEST_COMPLETE) {
                         //Module_DoComm tcp disconnect
@@ -127,7 +127,7 @@ void PrimaryLedIndicatorCtrlFork(void)
 
                 case S_TERMINATING:
                 case S_COMPLETE:
-                    if (pSysWarningInfo->Level == 2) {
+                    if (pSysWarning->Level == 2) {
                         pLedConfig->YellowLED = NO;
                         pLedConfig->GreenLED = NO;
                         if (checkCabinetEthConnectState(pLedConfig) == YES) {
@@ -146,7 +146,7 @@ void PrimaryLedIndicatorCtrlFork(void)
                 case S_FAULT:
                     pLedConfig->YellowLED = NO;
                     pLedConfig->GreenLED = NO;
-                    if (pSysWarningInfo->Level == 2) {
+                    if (pSysWarning->Level == 2) {
                         if (checkCabinetEthConnectState(pLedConfig) == YES) {
                             break;
                         }
@@ -160,125 +160,47 @@ void PrimaryLedIndicatorCtrlFork(void)
                 case S_UPDATE:
                 case S_NONE:
                     break;
-                }//switch
+                }
 
-            } //for
-            usleep(500000);
-        } //while
-    } //fork
+                usleep(500000);
+            }//switch
+        }//for
+    }//while
 }
 
 //------------------------------------------------------------------------------
-// 急停狀況的停止充電處理函式
-void EmcOccureByString(char *code)
-{
-    uint8_t level = 2;
-    uint8_t gunIndex = 0;
-    struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
-    struct ChargingInfoData *pDcChargingInfoData = NULL;
-
-
-    // 嚴重的急停有以下幾種 : EMC 按鈕、Mainbreak、Dooropen
-    // 其錯誤等級為 2
-
-//#if defined DD360 ||defined DD360Audi || defined DD360ComBox
-//    //DS60-120 remove
-//    if (strncmp(code, "012251", 6) == EQUAL ||
-//            strncmp(code, "012252", 6) == EQUAL ||
-//            strncmp(code, "012238", 6) == EQUAL ||
-//            strncmp(code, "042251", 6) == EQUAL ||
-//            strncmp(code, "042252", 6) == EQUAL ||
-//            strncmp(code, "012304", 6) == EQUAL ||
-//            strncmp(code, "042200", 6) == EQUAL ||
-//            strncmp(code, "042201", 6) == EQUAL ||
-//            strncmp(code, "042202", 6) == EQUAL ||
-//            strncmp(code, "042267", 6) == EQUAL)
-//#endif //defined DD360 || defined DD360Audi
-    {
-        for (gunIndex = 0; gunIndex < pSysConfig->TotalConnectorCount; gunIndex++) {
-            pDcChargingInfoData = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
-
-            //strncpy((char *)ShmOCPP16Data->StatusNotification[gunIndex].VendorErrorCode, code, 6);
-
-            if ((pDcChargingInfoData->SystemStatus > S_IDLE &&
-                    pDcChargingInfoData->SystemStatus < S_TERMINATING) ||
-                    (pDcChargingInfoData->SystemStatus >= S_CCS_PRECHARGE_ST0 &&
-                     pDcChargingInfoData->SystemStatus <= S_CCS_PRECHARGE_ST1)) {
-                //ChargingTerminalProcess(gunIndex);
-                ChargingAlarmProcess(gunIndex);
-            }
-        }
-//#if defined DD360 ||defined DD360Audi || defined DD360ComBox
-        StopChargingProcessByString(level);
-        //InformOcppErrOccur(4);
-//#endif //defined DD360 || defined DD360Audi
-    }
-}
-
-void ReleaseEmsOccureByString(uint8_t index, char *code)
-{
-    bool isTrigger = false;
-    uint8_t level = 2;
-    struct AlarmCodeData *pAlarmCode = (struct AlarmCodeData *)GetShmAlarmCodeData();
-
-    if (strncmp(code, "042251", 6) == 0 ) {
-        isTrigger = true;
-    } else if (strncmp(code, "012251", 6) == 0 &&
-               pAlarmCode->AlarmEvents.bits.EmergencyStopTrip == YES) {
-        isTrigger = true;
-        pAlarmCode->AlarmEvents.bits.EmergencyStopTrip = NO;
-    } else if (strncmp(code, "012252", 6) == 0 &&
-               pAlarmCode->AlarmEvents.bits.DoorOpen == YES) {
-        isTrigger = true;
-        pAlarmCode->AlarmEvents.bits.DoorOpen = NO;
-    } else if (strncmp(code, "012237", 6) == 0 &&
-               pAlarmCode->AlarmEvents.bits.SpdTrip == YES) {
-        isTrigger = true;
-        pAlarmCode->AlarmEvents.bits.SpdTrip = NO;
-    } else if (strncmp(code, "012238", 6) == 0 &&
-               pAlarmCode->AlarmEvents.bits.MainPowerBreakerTrip == YES) {
-        isTrigger = true;
-        pAlarmCode->AlarmEvents.bits.MainPowerBreakerTrip = NO;
-    }
-
-    if (isTrigger) {
-        ReleaseChargingProcessByString(level);
-        InformOcppErrOccur(6);
-    }
-}
-
 void ChkPrimaryStatus(void)
 {
-    uint8_t Rtn;
     static bool leftBtnPush = false;
     static bool rightBtnPush = false;
+    uint8_t Rtn;
     struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
     struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
-    struct WARNING_CODE_INFO *pSysWarningInfo = (struct WARNING_CODE_INFO *)GetShmSysWarningInfo();
+    struct WARNING_CODE_INFO *pSysWarning = (struct WARNING_CODE_INFO *)GetShmSysWarningInfo();
     struct PrimaryMcuData *ShmPrimaryMcuData = (struct PrimaryMcuData *)GetShmPrimaryMcuData();
     struct AlarmCodeData *pAlarmCode = (struct AlarmCodeData *)GetShmAlarmCodeData();
-    struct ChargingInfoData *pDcChargingInfoData = NULL;
-    struct ChargingInfoData *pAcChargingInfoData = (struct ChargingInfoData *)GetAcChargingInfoData(0);
+    struct ChargingInfoData *pDcChargingInfo = NULL;
+    struct ChargingInfoData *pAcChargingInfo = NULL;
 
-    if (pSysWarningInfo->WarningCount > 0) {
+    if (pSysWarning->WarningCount > 0) {
         Rtn = 0;
-        for (uint8_t i = 0; i < pSysWarningInfo->WarningCount; i++) {
-            if (memcmp(&pSysWarningInfo->WarningCode[i][0], "042251", 6) == 0) {
+        for (uint8_t i = 0; i < pSysWarning->WarningCount; i++) {
+            if (memcmp(&pSysWarning->WarningCode[i][0], "042251", 6) == 0) {
                 EmcOccureByString("042251");
                 Rtn = 1;
-            } else if (memcmp(&pSysWarningInfo->WarningCode[i][0], "042252", 6) == 0) {
+            } else if (memcmp(&pSysWarning->WarningCode[i][0], "042252", 6) == 0) {
                 EmcOccureByString("042252");
                 Rtn = 1;
-            } else if (memcmp(&pSysWarningInfo->WarningCode[i][0], "042200", 6) == 0) {
+            } else if (memcmp(&pSysWarning->WarningCode[i][0], "042200", 6) == 0) {
                 EmcOccureByString("042200");
                 Rtn = 1;
-            } else if (memcmp(&pSysWarningInfo->WarningCode[i][0], "042201", 6) == 0) {
+            } else if (memcmp(&pSysWarning->WarningCode[i][0], "042201", 6) == 0) {
                 EmcOccureByString("042201");
                 Rtn = 1;
-            } else if (memcmp(&pSysWarningInfo->WarningCode[i][0], "042202", 6) == 0) {
+            } else if (memcmp(&pSysWarning->WarningCode[i][0], "042202", 6) == 0) {
                 EmcOccureByString("042202");
                 Rtn = 1;
-            } else if (memcmp(&pSysWarningInfo->WarningCode[i][0], "012304", 6) == 0) {
+            } else if (memcmp(&pSysWarning->WarningCode[i][0], "012304", 6) == 0) {
                 EmcOccureByString("012304");
                 Rtn = 1;
             }
@@ -335,17 +257,25 @@ void ChkPrimaryStatus(void)
     //    pSysConfig->ShowInformation = NO;
     //}
 
-    pDcChargingInfoData = (struct ChargingInfoData *)GetDcChargingInfoData(pSysInfo->CurGunSelected);
-
     if (ShmPrimaryMcuData->InputDet.bits.Button1 == BTN_PRESS &&
-            !leftBtnPush &&
-            WaitAuthorPageState()
+            !leftBtnPush
+#if defined DD360Audi
+            &&
+            pSysInfo->SystemPage != _LCM_AUTHORIZING &&
+            pSysInfo->SystemPage != _LCM_AUTHORIZ_COMP &&
+            pSysInfo->SystemPage != _LCM_AUTHORIZ_FAIL
+#endif //defined DD360Audi
        ) {
+        pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(pSysInfo->CurGunSelected);
+
         if (!leftBtnPush) {
             leftBtnPush = true;
-            log_info("left btn down...............................%x\n", pDcChargingInfoData->SystemStatus);
+            log_info("left btn down...............................%x\n",
+                     pDcChargingInfo->SystemStatus);
             if (pSysInfo->CurGunSelectedByAc != NO_DEFINE) {
-                switch (pAcChargingInfoData->SystemStatus) {
+                pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(0);
+
+                switch (pAcChargingInfo->SystemStatus) {
                 case S_IDLE:
                     if (isDetectPlugin()) {
                         _DetectPlugInTimeout();
@@ -376,17 +306,14 @@ void ChkPrimaryStatus(void)
                 }
             }
 
-            switch (pDcChargingInfoData->SystemStatus) {
+            switch (pDcChargingInfo->SystemStatus) {
             case S_IDLE:
                 if (isDetectPlugin()) {
                     _DetectPlugInTimeout();
                     StopSystemTimeoutDet();
-#if defined DD360Audi
                     destroySelGun(pSysInfo->CurGunSelected);
-#endif //defined DD360Audi
-                }
+                }             else {
 #if defined DD360Audi
-                else {
                     if (getConfirmSelectedGun(pSysInfo->CurGunSelected) == PASS) {
                         //printf("destroy gun = %d\r\n", pSysInfo->CurGunSelected);
                         destroySelGun(pSysInfo->CurGunSelected);
@@ -395,8 +322,9 @@ void ChkPrimaryStatus(void)
                         log_info("confirm select gun ............................... %d \n",
                                  pSysInfo->CurGunSelected);
                     }
-                }
+
 #endif //defined DD360Audi
+                }
                 break;
 
             case S_REASSIGN_CHECK:
@@ -425,7 +353,7 @@ void ChkPrimaryStatus(void)
             case S_COMPLETE:
                 // 回 IDLE
                 //log_info("right btn down.................S_COMPLETE \n");
-                //pDcChargingInfoData->SystemStatus = S_IDLE;
+                //pDcChargingInfo->SystemStatus = S_IDLE;
                 break;
             }
         }
@@ -440,18 +368,17 @@ void ChkPrimaryStatus(void)
             !rightBtnPush
 #if defined DD360Audi
             &&
-            getCurLcmPage() != _LCM_IDLE &&
-            getCurLcmPage() != _LCM_AUTHORIZING &&
-            getCurLcmPage() != _LCM_AUTHORIZ_COMP &&
-            getCurLcmPage() != _LCM_AUTHORIZ_FAIL &&
-            getCurLcmPage() != _LCM_WAIT_FOR_PLUG
+            pSysInfo->SystemPage != _LCM_IDLE &&
+            pSysInfo->SystemPage != _LCM_AUTHORIZING &&
+            pSysInfo->SystemPage != _LCM_AUTHORIZ_COMP &&
+            pSysInfo->SystemPage != _LCM_AUTHORIZ_FAIL &&
+            pSysInfo->SystemPage != _LCM_WAIT_FOR_PLUG
 #endif //defined DD360Audi
        ) {
         if (!rightBtnPush) {
             rightBtnPush = true;
             //log_info("right btn down............................... %d \n", pSysInfo->CurGunSelected);
-            if (pSysInfo->CurGunSelected + 1 <
-                    pSysConfig->TotalConnectorCount &&
+            if (pSysInfo->CurGunSelected + 1 < pSysConfig->TotalConnectorCount &&
                     pSysInfo->IsAlternatvieConf == NO) {
                 pSysInfo->CurGunSelected++;
                 ChangeGunSelectByIndex(pSysInfo->CurGunSelected);
@@ -460,11 +387,11 @@ void ChkPrimaryStatus(void)
                 pSysInfo->CurGunSelectedByAc = DEFAULT_AC_INDEX;
             } else if (pSysInfo->IsAlternatvieConf == YES) {
                 for (uint8_t _index = 0; _index < pSysConfig->TotalConnectorCount; _index++) {
-                    pDcChargingInfoData = (struct ChargingInfoData *)GetDcChargingInfoData(_index);
+                    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_index);
 
-                    if (pDcChargingInfoData->SystemStatus != S_BOOTING &&
-                            pDcChargingInfoData->SystemStatus != S_IDLE &&
-                            pDcChargingInfoData->SystemStatus != S_RESERVATION) {
+                    if (pDcChargingInfo->SystemStatus != S_BOOTING &&
+                            pDcChargingInfo->SystemStatus != S_IDLE &&
+                            pDcChargingInfo->SystemStatus != S_RESERVATION) {
                         pSysInfo->CurGunSelected = _index;
                         ChangeGunSelectByIndex(pSysInfo->CurGunSelected);
                         return;

+ 247 - 152
EVSE/Projects/DD360ComBox/Apps/CSU/RFID.c

@@ -7,19 +7,55 @@
 #include "../Log/log.h"
 #include "../Define/define.h"
 #include "../ShareMemory/shmMem.h"
+#include "../SelectGun/SelectGun.h"
+
+#include "../main.h"
+#include "../timeout.h"
+
+//------------------------------------------------------------------------------
+static char *rfidPortName = "/dev/ttyS2";
+
+static bool isCardScan = false;
 
 //------------------------------------------------------------------------------
+static bool canStartCharging(void)
+{
+    char buf2[16] = "";
+    memset(buf2, 0, ARRAY_SIZE(buf2));
+    struct OCPP16Data *ShmOCPP16Data = (struct OCPP16Data *)GetShmOCPP16Data();
+
+    for (uint8_t index = 0; index < strlen((char *)ShmOCPP16Data->Authorize.ResponseIdTagInfo.Status); index++) {
+        sprintf(buf2 + (index - 1) * 2, "%02X", ShmOCPP16Data->Authorize.ResponseIdTagInfo.Status[index]);
+    }
+    sprintf(buf2, "%s", ShmOCPP16Data->Authorize.ResponseIdTagInfo.Status);
+
+    // 因為無法得知實際的長度,所以只能用搜尋的方式
+    if (strcmp(buf2, "Accepted") == EQUAL) {
+        return true;
+    } else {
+
+    }
+
+    return false;
+}
+
 static void UserScanFunction(void)
 {
     bool idleReq = false;
-    uint8_t stopReq = 255;
+    uint8_t stopReq = NO_DEFINE;
+    static uint8_t _authorizeIndex = NO_DEFINE;
+    struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
+    struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
+    struct ChargingInfoData *pAcChargingInfo =  (struct ChargingInfoData *)GetAcChargingInfoData(0);
+    struct ChargingInfoData *pDcChargingInfo = NULL;
+    GunIndexInfo *pGunIndexInfo = (GunIndexInfo *)GetGunIndexInfo();
 
     // 當前非驗證的狀態
     if (!IsAuthorizingMode()) {
 #if defined DD360Audi
         //當前沒有選槍
-        if (getConfirmSelectedGun(ShmSysConfigAndInfo->SysInfo.CurGunSelected) == FAIL) { //Jerry add
-            strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+        if (getConfirmSelectedGun(pSysInfo->CurGunSelected) == FAIL) { //Jerry add
+            strcpy((char *)pSysConfig->UserId, "");
             return;
         }
 #endif //defined DD360Audi
@@ -27,139 +63,145 @@ static void UserScanFunction(void)
         // 先判斷現在是否可以提供刷卡
         // 1. 如果當前沒有槍是閒置狀態,則無提供刷卡功能
         // 2. 停止充電
-        if (ShmSysConfigAndInfo->SysInfo.PageIndex == _LCM_FIX) {
-            strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+        if (pSysInfo->PageIndex == _LCM_FIX) {
+            strcpy((char *)pSysConfig->UserId, "");
             return;
         }
 
-        for (uint8_t i = 0; i < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; i++) {
-            if (chargingInfo[i]->SystemStatus == S_CHARGING) {
+        for (uint8_t i = 0; i < pSysConfig->TotalConnectorCount; i++) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(i);
+
+            if (pDcChargingInfo->SystemStatus == S_CHARGING) {
                 stopReq = i;
             }
-            if ((chargingInfo[i]->SystemStatus == S_IDLE &&
-                    chargingInfo[i]->IsAvailable) == YES ||
-                    (_acgunIndex > 0 && ac_chargingInfo[0]->SystemStatus ==
-                     S_IDLE && ac_chargingInfo[0]->IsAvailable)
+            if ((pDcChargingInfo->SystemStatus == S_IDLE &&
+                    pDcChargingInfo->IsAvailable) == YES ||
+                    (pGunIndexInfo->AcGunIndex > 0 && pAcChargingInfo->SystemStatus ==
+                     S_IDLE && pAcChargingInfo->IsAvailable)
                ) {
                 idleReq = true;
             }
         }
 
-        if (_acgunIndex > 0 && ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc == DEFAULT_AC_INDEX &&
-                ac_chargingInfo[0]->SystemStatus == S_CHARGING) {
+        if (pGunIndexInfo->AcGunIndex > 0 && pSysInfo->CurGunSelectedByAc == DEFAULT_AC_INDEX &&
+                pAcChargingInfo->SystemStatus == S_CHARGING) {
             stopReq = DEFAULT_AC_INDEX;
         }
 
-        if (strlen((char *)ShmSysConfigAndInfo->SysConfig.UserId) > 0) {
-            if (_acgunIndex > 0 && stopReq == DEFAULT_AC_INDEX &&
-                    ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc == DEFAULT_AC_INDEX) {
+        if (strlen((char *)pSysConfig->UserId) > 0) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(pSysInfo->CurGunSelected);
+
+            if (pGunIndexInfo->AcGunIndex > 0 && stopReq == DEFAULT_AC_INDEX &&
+                    pSysInfo->CurGunSelectedByAc == DEFAULT_AC_INDEX) {
                 char value[32];
 
                 log_info("ac stop charging \n");
-                log_info("index = %d, card number = %s, UserId = %s \n", ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc,
-                         ac_chargingInfo[0]->StartUserId, ShmSysConfigAndInfo->SysConfig.UserId);
-                memcpy(value, (uint8_t *)ac_chargingInfo[0]->StartUserId,
-                       ARRAY_SIZE(ac_chargingInfo[0]->StartUserId));
-                if (strcmp((char *)ShmSysConfigAndInfo->SysConfig.UserId, value) == EQUAL) {
+                log_info("index = %d, card number = %s, UserId = %s \n", pSysInfo->CurGunSelectedByAc,
+                         pAcChargingInfo->StartUserId, pSysConfig->UserId);
+                memcpy(value, (uint8_t *)pAcChargingInfo->StartUserId,
+                       ARRAY_SIZE(pAcChargingInfo->StartUserId));
+                if (strcmp((char *)pSysConfig->UserId, value) == EQUAL) {
                     AcChargingTerminalProcess();
                 }
-                strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
-            } else if (stopReq < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount &&
-                       chargingInfo[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus == S_CHARGING &&
-                       (_acgunIndex <= 0 || (_acgunIndex > 0 && ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc == NO_DEFINE))) {
+                strcpy((char *)pSysConfig->UserId, "");
+            } else if (stopReq < pSysConfig->TotalConnectorCount &&
+                       pDcChargingInfo->SystemStatus == S_CHARGING &&
+                       (pGunIndexInfo->AcGunIndex <= 0 || (pGunIndexInfo->AcGunIndex > 0 && pSysInfo->CurGunSelectedByAc == NO_DEFINE))) {
                 char value[32];
 
                 log_info("stop charging \n");
                 log_info("index = %d, card number = %s, UserId = %s \n",
-                         ShmSysConfigAndInfo->SysInfo.CurGunSelected,
-                         chargingInfo[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->StartUserId,
-                         ShmSysConfigAndInfo->SysConfig.UserId);
-                memcpy(value, (uint8_t *)chargingInfo[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->StartUserId,
-                       ARRAY_SIZE(chargingInfo[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->StartUserId));
+                         pSysInfo->CurGunSelected,
+                         pDcChargingInfo->StartUserId,
+                         pSysConfig->UserId);
+                memcpy(value, (uint8_t *)pDcChargingInfo->StartUserId,
+                       ARRAY_SIZE(pDcChargingInfo->StartUserId));
 
                 // 同一張卡直接停掉
-                if (strcmp((char *)ShmSysConfigAndInfo->SysConfig.UserId, value) == EQUAL) {
-                    ChargingTerminalProcess(ShmSysConfigAndInfo->SysInfo.CurGunSelected);
-                    strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                if (strcmp((char *)pSysConfig->UserId, value) == EQUAL) {
+                    ChargingTerminalProcess(pSysInfo->CurGunSelected);
+                    strcpy((char *)pSysConfig->UserId, "");
                 } else {
                     // 進驗證
-                    if (_acgunIndex > 0 && ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc == DEFAULT_AC_INDEX) {
-                        _authorizeIndex = ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc;
+                    if (pGunIndexInfo->AcGunIndex > 0 && pSysInfo->CurGunSelectedByAc == DEFAULT_AC_INDEX) {
+                        _authorizeIndex = pSysInfo->CurGunSelectedByAc;
                     } else {
-                        _authorizeIndex = ShmSysConfigAndInfo->SysInfo.CurGunSelected;
+                        _authorizeIndex = pSysInfo->CurGunSelected;
                     }
 #if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
                     StartSystemTimeoutDet(Timeout_AuthorizingForStop);
                     AuthorizingStart();
 #else
-                    strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                    strcpy((char *)pSysConfig->UserId, "");
 #endif //!defined DD360 && !defined DD360Audi
                 }
             } else if (idleReq) {
-                if (ShmSysConfigAndInfo->SysConfig.TotalConnectorCount > 1 &&
+                if (pSysConfig->TotalConnectorCount > 1 &&
                         stopReq != 255 &&
-                        ShmSysConfigAndInfo->SysInfo.IsAlternatvieConf == YES) {
+                        pSysInfo->IsAlternatvieConf == YES) {
                     idleReq = false;
-                    strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
-                } else if ((_acgunIndex > 0 && ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc == DEFAULT_AC_INDEX) ||
-                           chargingInfo[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus == S_IDLE) {
+                    strcpy((char *)pSysConfig->UserId, "");
+                } else if ((pGunIndexInfo->AcGunIndex > 0 && pSysInfo->CurGunSelectedByAc == DEFAULT_AC_INDEX) ||
+                           pDcChargingInfo->SystemStatus == S_IDLE) {
                     log_info("// LCM => Authorizing \n");
 #if defined DD360Audi
-                    setSelGunWaitToAuthor(ShmSysConfigAndInfo->SysInfo.CurGunSelected); //Jerry add
+                    setSelGunWaitToAuthor(pSysInfo->CurGunSelected); //Jerry add
 #endif //defined DD360Audi
                     // LCM => Authorizing
-                    ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_AUTHORIZING;
+                    pSysInfo->SystemPage = _LCM_AUTHORIZING;
                     // 進入確認卡號狀態
                     AuthorizingStart();
                 } else {
-                    strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                    strcpy((char *)pSysConfig->UserId, "");
                 }
             } else {
-                strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                strcpy((char *)pSysConfig->UserId, "");
             }
         }
     } else {
         // 透過後臺停止充電的判斷
         if (isAuthorizedComplete()
 #if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
-                || (ShmSysConfigAndInfo->SysInfo.OcppConnStatus == NO &&
-                    ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING)
+                || (pSysInfo->OcppConnStatus == NO &&
+                    pSysConfig->OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING)
 #endif //!defined DD360 && !defined DD360Audi
            ) {
             // 判斷後台回覆狀態
             if (canStartCharging()
 #if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
-                    || (ShmSysConfigAndInfo->SysInfo.OcppConnStatus == NO &&
-                        ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING)
+                    || (pSysInfo->OcppConnStatus == NO &&
+                        pSysConfig->OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING)
 #endif //!defined DD360 && !defined DD360Audi
                ) {
                 if (_authorizeIndex != NO_DEFINE) {
+                    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_authorizeIndex);
+
                     // 先找 AC
                     if (_authorizeIndex == DEFAULT_AC_INDEX) {
-                        if (ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST &&
-                                strcmp((char *)chargingInfo[_authorizeIndex]->StartUserId, "") != EQUAL) {
+                        if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST &&
+                                strcmp((char *)pDcChargingInfo->StartUserId, "") != EQUAL) {
                             AcChargingTerminalProcess();
                         }
                     } else {
-                        if (ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST &&
-                                strcmp((char *)chargingInfo[_authorizeIndex]->StartUserId, "") != EQUAL) {
+                        if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST &&
+                                strcmp((char *)pDcChargingInfo->StartUserId, "") != EQUAL) {
                             ChargingTerminalProcess(_authorizeIndex);
                         }
                     }
-                    strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                    strcpy((char *)pSysConfig->UserId, "");
                     _authorizeIndex = NO_DEFINE;
                 }
             } else {
-                strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                strcpy((char *)pSysConfig->UserId, "");
             }
             ClearAuthorizedFlag();
-        } else if (ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST) {
+        } else if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST) {
             // 白名單驗證
             for (int i = 0; i < 10; i++) {
-                if (strcmp((char *)ShmSysConfigAndInfo->SysConfig.LocalWhiteCard[i], "") != EQUAL) {
-                    if (strcmp((char *)ShmSysConfigAndInfo->SysConfig.LocalWhiteCard[i], (char *)ShmSysConfigAndInfo->SysConfig.UserId) == EQUAL) {
+                if (strcmp((char *)pSysConfig->LocalWhiteCard[i], "") != EQUAL) {
+                    if (strcmp((char *)pSysConfig->LocalWhiteCard[i], (char *)pSysConfig->UserId) == EQUAL) {
                         ChargingTerminalProcess(_authorizeIndex);
-                        strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                        strcpy((char *)pSysConfig->UserId, "");
                         ClearAuthorizedFlag();
                         break;
                     }
@@ -169,152 +211,205 @@ static void UserScanFunction(void)
     }
 }
 
-void ScannerCardProcess()
+bool GetIsCardScan(void)
+{
+    return isCardScan;
+}
+
+void SetIsCardScan(bool value)
+{
+    isCardScan = value;
+}
+
+void ScannerCardProcess(void)
 {
-    if (!isDetectPlugin() && !isCardScan && ShmSysConfigAndInfo->SysWarningInfo.Level != 2 &&
-            ShmSysConfigAndInfo->SysConfig.AuthorisationMode == AUTH_MODE_ENABLE) {
+    struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
+    struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
+    struct WARNING_CODE_INFO *pSysWarning = (struct WARNING_CODE_INFO *)GetShmSysWarningInfo();
+    SelectGunInfo *ShmSelectGunInfo = (SelectGunInfo *)GetShmSelectGunInfo();
+
+    if (!isDetectPlugin() && !isCardScan && pSysWarning->Level != 2 &&
+            pSysConfig->AuthorisationMode == AUTH_MODE_ENABLE) {
         isCardScan = true;
         // 處理刷卡及驗證卡號的動作
         UserScanFunction();
     }
 
-    if (ShmSysConfigAndInfo->SysInfo.PageIndex == _LCM_AUTHORIZING) {
+    if (pSysInfo->PageIndex == _LCM_AUTHORIZING) {
         StartSystemTimeoutDet(Timeout_Authorizing);
 
         // 確認驗證卡號完成沒
         if (isAuthorizedComplete()
 #if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
-                || ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING
+                || pSysConfig->OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING
 #else
-                && gAudiCustInfo->PricesInfo[ShmSysConfigAndInfo->SysInfo.CurGunSelected].Balance != FAIL_BALANCE_PRICES
+                && ShmSelectGunInfo->PricesInfo[pSysInfo->CurGunSelected].Balance != FAIL_BALANCE_PRICES
 #endif //!defined DD360 && !defined DD360Audi
            ) {
             StopSystemTimeoutDet();
             // 判斷後台回覆狀態
             if (canStartCharging()
 #if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
-                    || ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING
+                    || pSysConfig->OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING
 #endif //!defined DD360 && !defined DD360Audi
                ) {
                 // LCM => Authorize complete
-                ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_AUTHORIZ_COMP;
+                pSysInfo->SystemPage = _LCM_AUTHORIZ_COMP;
             } else {
                 // LCM => Authorize fail
-                ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_AUTHORIZ_FAIL;
-                strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                pSysInfo->SystemPage = _LCM_AUTHORIZ_FAIL;
+                strcpy((char *)pSysConfig->UserId, "");
             }
             ClearAuthorizedFlag();
-        } else if (ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST) {
+        } else if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST) {
             // 白名單驗證
             for (int i = 0; i < 10; i++) {
-                if (strcmp((char *)ShmSysConfigAndInfo->SysConfig.LocalWhiteCard[i], "") != EQUAL) {
-                    if (strcmp((char *)ShmSysConfigAndInfo->SysConfig.LocalWhiteCard[i], (char *)ShmSysConfigAndInfo->SysConfig.UserId) == EQUAL) {
-                        ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_AUTHORIZ_COMP;
+                if (strcmp((char *)pSysConfig->LocalWhiteCard[i], "") != EQUAL) {
+                    if (strcmp((char *)pSysConfig->LocalWhiteCard[i], (char *)pSysConfig->UserId) == EQUAL) {
+                        pSysInfo->SystemPage = _LCM_AUTHORIZ_COMP;
                         ClearAuthorizedFlag();
                         break;
                     }
                 }
             }
         }
-    } else if (ShmSysConfigAndInfo->SysInfo.PageIndex == _LCM_AUTHORIZ_FAIL) {
+    } else if (pSysInfo->PageIndex == _LCM_AUTHORIZ_FAIL) {
         StartSystemTimeoutDet(Timeout_VerifyFail);
         isCardScan = false;
-    } else if (ShmSysConfigAndInfo->SysInfo.PageIndex == _LCM_AUTHORIZ_COMP) {
+    } else if (pSysInfo->PageIndex == _LCM_AUTHORIZ_COMP) {
         StartSystemTimeoutDet(Timeout_VerifyComp);
-    } else if (ShmSysConfigAndInfo->SysInfo.PageIndex == _LCM_WAIT_FOR_PLUG) {
+    } else if (pSysInfo->PageIndex == _LCM_WAIT_FOR_PLUG) {
         StartSystemTimeoutDet(Timeout_WaitPlug);
     } else {
         isCardScan = false;
     }
 }
 
-void CreateRfidFork()
+
+static int InitialRfidPort(void)
+{
+    int fd = open(rfidPortName, O_RDWR);
+    struct termios tios;
+    struct AlarmCodeData *pAlarmCode = (struct AlarmCodeData *)GetShmAlarmCodeData();
+
+    if (fd != FAIL) {
+        ioctl (fd, TCGETS, &tios);
+        tios.c_cflag = B19200 | CS8 | CLOCAL | CREAD;
+        tios.c_lflag = 0;
+        tios.c_iflag = 0;
+        tios.c_oflag = 0;
+        tios.c_cc[VMIN] = 0;
+        tios.c_cc[VTIME] = (uint8_t) 1;
+        tios.c_lflag = 0;
+        tcflush(fd, TCIFLUSH);
+        ioctl(fd, TCSETS, &tios);
+    }
+
+    if (fd < 0) {
+        pAlarmCode->AlarmEvents.bits.RfidModuleCommFail = 1;
+    }
+
+    return fd;
+}
+
+void CreateRfidFork(void)
 {
     pid_t rfidRecPid;
 
     rfidRecPid = fork();
     log_info("CreateRfidFork = %d\r\n", rfidRecPid);
     if (rfidRecPid == 0) {
+        int fd = -1;
+        RFID rfid = {0};
+        fd = InitialRfidPort();
+        struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
+
         while (true) {
             // 刷卡判斷
-            RFID rfid;
-            if (ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_NO_CHARGING ||
-                    !ShmSysConfigAndInfo->SysConfig.isRFID)
-            {}
-            else if (getRequestCardSN(rfidFd, 0, &rfid)) {
-                //log_info("Get Card..-%s- \n", ShmSysConfigAndInfo->SysConfig.UserId);
-                if (strlen((char *)ShmSysConfigAndInfo->SysConfig.UserId) == 0) {
-                    if (ShmSysConfigAndInfo->SysConfig.RfidCardNumEndian == RFID_ENDIAN_LITTLE) {
-                        switch (rfid.snType) {
-                        case RFID_SN_TYPE_6BYTE:
-                            sprintf((char *) ShmSysConfigAndInfo->SysConfig.UserId,
-                                    "%02X%02X%02X%02X%02X%02X",
-                                    rfid.currentCard[0], rfid.currentCard[1],
-                                    rfid.currentCard[2], rfid.currentCard[3],
-                                    rfid.currentCard[4], rfid.currentCard[5]);
-                            break;
-                        case RFID_SN_TYPE_7BYTE:
-                            sprintf((char *) ShmSysConfigAndInfo->SysConfig.UserId,
-                                    "%02X%02X%02X%02X%02X%02X%02X",
-                                    rfid.currentCard[0], rfid.currentCard[1],
-                                    rfid.currentCard[2], rfid.currentCard[3],
-                                    rfid.currentCard[4], rfid.currentCard[5],
-                                    rfid.currentCard[6]);
-                            break;
-                        case RFID_SN_TYPE_10BYTE:
-                            sprintf((char *) ShmSysConfigAndInfo->SysConfig.UserId,
-                                    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
-                                    rfid.currentCard[0], rfid.currentCard[1],
-                                    rfid.currentCard[2], rfid.currentCard[3],
-                                    rfid.currentCard[4], rfid.currentCard[5],
-                                    rfid.currentCard[6], rfid.currentCard[7],
-                                    rfid.currentCard[8], rfid.currentCard[9]);
-                            break;
-                        case RFID_SN_TYPE_4BYTE:
-                            sprintf((char *) ShmSysConfigAndInfo->SysConfig.UserId,
-                                    "%02X%02X%02X%02X",
-                                    rfid.currentCard[0], rfid.currentCard[1],
-                                    rfid.currentCard[2], rfid.currentCard[3]);
-                            break;
-                        }
-                    } else if (ShmSysConfigAndInfo->SysConfig.RfidCardNumEndian == RFID_ENDIAN_BIG) {
-                        switch (rfid.snType) {
-                        case RFID_SN_TYPE_6BYTE:
-                            sprintf((char *) ShmSysConfigAndInfo->SysConfig.UserId,
-                                    "%02X%02X%02X%02X%02X%02X",
-                                    rfid.currentCard[5], rfid.currentCard[4],
-                                    rfid.currentCard[3], rfid.currentCard[2],
-                                    rfid.currentCard[1], rfid.currentCard[0]);
-                            break;
-                        case RFID_SN_TYPE_7BYTE:
-                            sprintf((char *) ShmSysConfigAndInfo->SysConfig.UserId,
-                                    "%02X%02X%02X%02X%02X%02X%02X",
-                                    rfid.currentCard[6], rfid.currentCard[5],
-                                    rfid.currentCard[4], rfid.currentCard[3],
-                                    rfid.currentCard[2], rfid.currentCard[1],
-                                    rfid.currentCard[0]);
-                            break;
-                        case RFID_SN_TYPE_10BYTE:
-                            sprintf((char *) ShmSysConfigAndInfo->SysConfig.UserId,
-                                    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
-                                    rfid.currentCard[9], rfid.currentCard[8],
-                                    rfid.currentCard[7], rfid.currentCard[6],
-                                    rfid.currentCard[5], rfid.currentCard[4],
-                                    rfid.currentCard[3], rfid.currentCard[2],
-                                    rfid.currentCard[1], rfid.currentCard[0]);
-                            break;
-                        case RFID_SN_TYPE_4BYTE:
-                            sprintf((char *) ShmSysConfigAndInfo->SysConfig.UserId,
-                                    "%02X%02X%02X%02X",
-                                    rfid.currentCard[3], rfid.currentCard[2],
-                                    rfid.currentCard[1], rfid.currentCard[0]);
-                            break;
-                        }
+            if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_NO_CHARGING ||
+                    !pSysConfig->isRFID) {
+                usleep(500000);
+                continue;
+            }
+
+            if (getRequestCardSN(fd, 0, &rfid) == false) {
+                usleep(500000);
+                continue;
+            }
+
+            //log_info("Get Card..-%s- \n", pSysConfig->UserId);
+            if (strlen((char *)pSysConfig->UserId) == 0) {
+                if (pSysConfig->RfidCardNumEndian == RFID_ENDIAN_LITTLE) {
+                    switch (rfid.snType) {
+                    case RFID_SN_TYPE_6BYTE:
+                        sprintf((char *) pSysConfig->UserId,
+                                "%02X%02X%02X%02X%02X%02X",
+                                rfid.currentCard[0], rfid.currentCard[1],
+                                rfid.currentCard[2], rfid.currentCard[3],
+                                rfid.currentCard[4], rfid.currentCard[5]);
+                        break;
+                    case RFID_SN_TYPE_7BYTE:
+                        sprintf((char *) pSysConfig->UserId,
+                                "%02X%02X%02X%02X%02X%02X%02X",
+                                rfid.currentCard[0], rfid.currentCard[1],
+                                rfid.currentCard[2], rfid.currentCard[3],
+                                rfid.currentCard[4], rfid.currentCard[5],
+                                rfid.currentCard[6]);
+                        break;
+                    case RFID_SN_TYPE_10BYTE:
+                        sprintf((char *) pSysConfig->UserId,
+                                "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
+                                rfid.currentCard[0], rfid.currentCard[1],
+                                rfid.currentCard[2], rfid.currentCard[3],
+                                rfid.currentCard[4], rfid.currentCard[5],
+                                rfid.currentCard[6], rfid.currentCard[7],
+                                rfid.currentCard[8], rfid.currentCard[9]);
+                        break;
+                    case RFID_SN_TYPE_4BYTE:
+                        sprintf((char *) pSysConfig->UserId,
+                                "%02X%02X%02X%02X",
+                                rfid.currentCard[0], rfid.currentCard[1],
+                                rfid.currentCard[2], rfid.currentCard[3]);
+                        break;
+                    }
+                } else if (pSysConfig->RfidCardNumEndian == RFID_ENDIAN_BIG) {
+                    switch (rfid.snType) {
+                    case RFID_SN_TYPE_6BYTE:
+                        sprintf((char *) pSysConfig->UserId,
+                                "%02X%02X%02X%02X%02X%02X",
+                                rfid.currentCard[5], rfid.currentCard[4],
+                                rfid.currentCard[3], rfid.currentCard[2],
+                                rfid.currentCard[1], rfid.currentCard[0]);
+                        break;
+                    case RFID_SN_TYPE_7BYTE:
+                        sprintf((char *) pSysConfig->UserId,
+                                "%02X%02X%02X%02X%02X%02X%02X",
+                                rfid.currentCard[6], rfid.currentCard[5],
+                                rfid.currentCard[4], rfid.currentCard[3],
+                                rfid.currentCard[2], rfid.currentCard[1],
+                                rfid.currentCard[0]);
+                        break;
+                    case RFID_SN_TYPE_10BYTE:
+                        sprintf((char *) pSysConfig->UserId,
+                                "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
+                                rfid.currentCard[9], rfid.currentCard[8],
+                                rfid.currentCard[7], rfid.currentCard[6],
+                                rfid.currentCard[5], rfid.currentCard[4],
+                                rfid.currentCard[3], rfid.currentCard[2],
+                                rfid.currentCard[1], rfid.currentCard[0]);
+                        break;
+                    case RFID_SN_TYPE_4BYTE:
+                        sprintf((char *) pSysConfig->UserId,
+                                "%02X%02X%02X%02X",
+                                rfid.currentCard[3], rfid.currentCard[2],
+                                rfid.currentCard[1], rfid.currentCard[0]);
+                        break;
                     }
-                    log_info("card number = %s\n", ShmSysConfigAndInfo->SysConfig.UserId);
                 }
+                log_info("card number = %s\n", pSysConfig->UserId);
             }
             usleep(500000);
         }
     }
 }
+

+ 215 - 0
EVSE/Projects/DD360ComBox/Apps/CSU/SelfTest.c

@@ -0,0 +1,215 @@
+#include <stdio.h>      /*標準輸入輸出定義*/
+#include <stdlib.h>     /*標準函數庫定義*/
+#include <string.h>
+#include <stdint.h>
+
+#include "../Config.h"
+#include "../Log/log.h"
+#include "../Define/define.h"
+#include "../ShareMemory/shmMem.h"
+
+#include "../main.h"
+#include "../timeout.h"
+
+//------------------------------------------------------------------------------
+extern void ChkPrimaryStatus(void);
+
+//------------------------------------------------------------------------------
+void SelfTestRun(void)
+{
+    bool evInitFlag = false;
+    struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
+    struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
+    struct WARNING_CODE_INFO *pSysWarning = (struct WARNING_CODE_INFO *)GetShmSysWarningInfo();
+
+    struct PsuData *ShmPsuData = (struct PsuData *)GetShmPsuData();
+    struct CHAdeMOData *ShmCHAdeMOData = (struct CHAdeMOData *)GetShmCHAdeMOData();
+    struct GBTData *ShmGBTData = (struct GBTData *)GetShmGBTData();
+    struct CcsData *ShmCcsData = (struct CcsData *)GetShmCcsData();
+
+    struct PrimaryMcuData *ShmPrimaryMcuData = (struct PrimaryMcuData *)GetShmPrimaryMcuData();
+    struct FanModuleData *ShmFanModuleData = (struct FanModuleData *)GetShmFanModuleData();
+    struct RelayModuleData *ShmRelayModuleData = (struct RelayModuleData *)GetShmRelayModuleData();
+    struct ChargingInfoData *pDcChargingInfo = NULL;
+    struct ChargingInfoData *pAcChargingInfo = NULL;
+
+    StartSystemTimeoutDet(Timeout_SelftestChk);
+    pSysInfo->SelfTestSeq = _STEST_VERSION;
+
+    while (pSysInfo->SelfTestSeq != _STEST_COMPLETE //||
+            //GetTimeoutValue(pSysInfo->SystemTimeoutTimer) / uSEC_VAL <= 20 //DS60-120 add
+          ) {
+        if (pSysInfo->SelfTestSeq == _STEST_COMPLETE) {
+            return;
+        }
+
+        ChkPrimaryStatus();
+        if (pSysWarning->Level == 2 //||
+                //pAlarmCode->AlarmEvents.bits.PsuDipSwitchStestFail == YES //DS60-120 add
+           ) {
+            pSysInfo->SelfTestSeq = _STEST_FAIL;
+            return;
+        }
+
+        if (pSysConfig->TotalConnectorCount > 0) {
+            if (ShmPsuData->Work_Step == _NO_WORKING ||
+                    pSysInfo->SelfTestSeq == _STEST_FAIL) {
+                pSysInfo->SelfTestSeq = _STEST_FAIL;
+                return;
+            }
+
+            switch (pSysInfo->SelfTestSeq) {
+            case _STEST_VERSION: {
+                if ((strlen((char *)pSysInfo->RelayModuleFwRev) != 0 ||
+                        pSysInfo->RelayModuleFwRev[0] != '\0')
+                        && (ShmRelayModuleData->SelfTest_Comp != YES)
+                   ) {
+                    log_info("Relay Board FW Rev = %s", pSysInfo->RelayModuleFwRev);
+                    ShmRelayModuleData->SelfTest_Comp = YES;
+                }
+#if !defined NO_FAN_BOARD && !defined DD360ComBox
+                if ((strlen((char *)pSysInfo->FanModuleFwRev) != 0 ||
+                        pSysInfo->FanModuleFwRev[0] != '\0')
+                        && (ShmFanModuleData->SelfTest_Comp != YES)
+                   ) {
+                    log_info("Fan Board FW Rev = %s", pSysInfo->FanModuleFwRev);
+                    ShmFanModuleData->SelfTest_Comp = YES;
+                }
+#else
+                ShmFanModuleData->SelfTest_Comp = YES;
+#endif //NO_FAN_BOARD
+
+                if ((strlen((char *)ShmPrimaryMcuData->version) != 0 ||
+                        ShmPrimaryMcuData->version[0] != '\0')
+                        && (ShmPrimaryMcuData->SelfTest_Comp != YES)
+                   ) {
+                    log_info("Primary FW Rev = %s", pSysInfo->CsuPrimFwRev);
+                    ShmPrimaryMcuData->SelfTest_Comp = YES;
+                }
+
+                // EV 小板
+                if (!evInitFlag) {
+                    evInitFlag = YES;
+                    for (uint8_t index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+                        pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+                        //log_info("index = %d, charging index = %d, type = %d\r\n",
+                        //         index,
+                        //         chargingInfo[index]->type_index,
+                        //         chargingInfo[index]->Type);
+                        if (pDcChargingInfo->Type == _Type_Chademo) {
+                            if ((strlen((char *)ShmCHAdeMOData->evse[pDcChargingInfo->type_index].version) != 0 ||
+                                    ShmCHAdeMOData->evse[pDcChargingInfo->type_index].version[0] != '\0')
+                                    //&& (ShmCHAdeMOData->evse[pDcChargingInfo->type_index].SelfTest_Comp != YES)
+                               ) {
+                                log_info("CHAdeMO[%d] FW Rev = %s", pDcChargingInfo->type_index, ShmCHAdeMOData->evse[pDcChargingInfo->type_index].version);
+                                ShmCHAdeMOData->evse[pDcChargingInfo->type_index].SelfTest_Comp = YES;
+                            } else {
+                                //log_info("chademo fw lose...... %s \n", ShmCHAdeMOData->evse[pDcChargingInfo->type_index].version);
+                                evInitFlag = NO;
+                            }
+                        } else if (pDcChargingInfo->Type == _Type_GB) {
+                            if ((strlen((char *)ShmGBTData->evse[pDcChargingInfo->type_index].version) != 0 ||
+                                    ShmGBTData->evse[pDcChargingInfo->type_index].version[0] != '\0')
+                                    //&& (ShmGBTData->evse[pDcChargingInfo->type_index].SelfTest_Comp != YES)
+                               ) {
+                                log_info("GBT[%d] FW Rev = %s", pDcChargingInfo->type_index, ShmGBTData->evse[pDcChargingInfo->type_index].version);
+                                ShmGBTData->evse[pDcChargingInfo->type_index].SelfTest_Comp = YES;
+                            } else {
+                                //log_info("GBT fw lose...... %s \n", ShmCHAdeMOData->evse[pDcChargingInfo->type_index].version);
+                                evInitFlag = NO;
+                            }
+                        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                            if (ShmCcsData->CommProtocol == _CCS_COMM_V2GMessage_DIN70121) {
+                                if ((strlen((char *)ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].version) != 0 ||
+                                        ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].version[0] != '\0')
+                                        /*&&(ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].SelfTest_Comp != YES)*/
+                                   ) {
+                                    log_info("CCS[%d] FW Rev = %s",
+                                             pDcChargingInfo->type_index,
+                                             ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].version);
+                                    ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].SelfTest_Comp = YES;
+                                } else {
+                                    //log_info("CCS[%d] ccs fw lose...... %s \n",
+                                    //         chargingInfo[index]->type_index,
+                                    //         ShmCcsData->V2GMessage_DIN70121[chargingInfo[index]->type_index].version);
+                                    evInitFlag = NO;
+                                }
+                            }
+                        }
+                    }
+
+                    for (uint8_t index = 0; index < pSysConfig->AcConnectorCount; index++) {
+                        pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(index);
+
+                        if (pAcChargingInfo->Type == _Type_AC) {
+                            if ((strlen((char *)pAcChargingInfo->version) != 0 || pAcChargingInfo->version[0] != '\0')
+                                    && (pAcChargingInfo->SelfTest_Comp != YES)
+                               ) {
+                                log_info("AC connector[%d] FW Rev = %s", index, pAcChargingInfo->version);
+                                pAcChargingInfo->SelfTest_Comp = YES;
+                            } else {
+                                evInitFlag = NO;
+                            }
+                        }
+                    }
+                }
+
+                if ( ShmFanModuleData->SelfTest_Comp &&
+                        ShmRelayModuleData->SelfTest_Comp &&
+                        ShmPrimaryMcuData->SelfTest_Comp &&
+                        evInitFlag
+                   ) {
+                    pSysInfo->SelfTestSeq = _STEST_AC_CONTACTOR;
+                }
+            }
+            break;
+            case _STEST_AC_CONTACTOR: {
+                //ShmPsuData->Work_Step = _TEST_COMPLETE;
+                // 因為 30KW 以下沒有 Relay feedback 功能,所以暫時先直接跳過
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                if (pSysInfo->AcContactorStatus == YES) {
+                    pSysInfo->SelfTestSeq = _STEST_PSU_DETECT;
+                    log_info("AC contactor self test OK");
+                }
+#else
+                pSysInfo->SelfTestSeq = _STEST_PSU_DETECT;
+                log_info("Waiting for DO communication");
+#endif //!defined DD360 && !defined DD360Audi
+            }
+            break;
+            case _STEST_PSU_DETECT: {
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                if (ShmPsuData->Work_Step >= GET_SYS_CAP) {
+                    pSysInfo->SelfTestSeq = _STEST_PSU_CAP;
+                }
+#else
+                pSysInfo->SelfTestSeq = _STEST_PSU_CAP;
+#endif //defined DD360 && !defined DD360Audi
+            }
+            break;
+            case _STEST_PSU_CAP: {
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                // 此測試是要確認當前總輸出能力
+                // 如果沒有 PSU 模組請 bypass
+                if (ShmPsuData->Work_Step == BOOTING_COMPLETE) {
+                    sleep(1);
+                    pSysInfo->SelfTestSeq = _STEST_COMPLETE;
+                    pSysInfo->BootingStatus = BOOT_COMPLETE;
+                }
+#else
+                //check the power limit from DO
+                pSysInfo->SelfTestSeq = _STEST_COMPLETE;
+                pSysInfo->BootingStatus = BOOT_COMPLETE;
+                log_info("Successful Self Test");
+#endif //defined DD360 && !defined DD360Audi
+            }
+            break;
+            }
+        } else {
+            break;
+        }
+
+        usleep(100000);
+    }
+}

+ 0 - 303
EVSE/Projects/DD360ComBox/Apps/CSU/TimeTask.c

@@ -1,303 +0,0 @@
-
-void _CcsPrechargeTimeout(uint8_t gunIndex)
-{
-    log_info("*********** _CcsPrechargeTimeout ***********\n");
-    setChargerMode(gunIndex, MODE_IDLE);
-}
-
-void _DetectEvseChargingEnableTimeout(uint8_t gunIndex)
-{
-    log_info("*********** _DetectEvseChargingEnableTimeout (GFD timeout) ***********\n");
-    //if (chargingInfo[gunIndex]->GroundFaultStatus != GFD_PASS)
-    {
-        setChargerMode(gunIndex, MODE_IDLE);
-        _AutoReturnTimeout();
-    }
-}
-
-void _DetectEvChargingEnableTimeout(uint8_t gunIndex)
-{
-    if (chargingInfo[gunIndex]->Type == _Type_Chademo) {
-        if (!isEvGunLocked_chademo(gunIndex)) {
-            log_info("*********** _DetectEvChargingEnableTimeout (chademo) ***********\n");
-        }
-    } else if (chargingInfo[gunIndex]->Type == _Type_GB) {
-        if (!isEvGunLocked_ccs(gunIndex)) {
-            log_info("*********** _DetectEvChargingEnableTimeout (gb) ***********\n");
-        }
-    } else if (chargingInfo[gunIndex]->Type == _Type_CCS_2) {
-        if (!isEvGunLocked_ccs(gunIndex)) {
-            log_info("*********** _DetectEvChargingEnableTimeout (ccs) ***********\n");
-        }
-    }
-    ChargingTerminalProcess(gunIndex);
-    _AutoReturnTimeout();
-}
-
-void _PrepareTimeout(uint8_t gunIndex)
-{
-    log_info("*********** _PrepareTimeout ***********\n");
-    setChargerMode(gunIndex, MODE_IDLE);
-    ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuNoResource = YES;
-    _AutoReturnTimeout();
-}
-
-void ClearAuthorizedFlag()
-{
-    ShmOCPP16Data->SpMsg.bits.AuthorizeConf = NO;
-    ShmSysConfigAndInfo->SysInfo.AuthorizeFlag = NO;
-}
-
-void DisplayChargingInfo()
-{
-    log_info("*********** DisplayChargingInfo *********** \n");
-    for (uint8_t i = 0; i < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; i++) {
-        if (chargingInfo[i]->SystemStatus != S_IDLE &&
-                chargingInfo[i]->SystemStatus != S_RESERVATION) {
-            ChangeGunSelectByIndex(i);
-            return;
-        }
-    }
-
-    if (ShmSysConfigAndInfo->SysConfig.AcConnectorCount > 0 &&
-            ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc == NO_DEFINE &&
-            ac_chargingInfo[0]->SystemStatus >= S_PREPARNING && ac_chargingInfo[0]->SystemStatus <= S_COMPLETE) {
-        ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc = DEFAULT_AC_INDEX;
-    }
-
-    usleep(50000);
-#if defined DD360Audi
-    ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_SELECT_GUN;
-#else
-    ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_NONE;
-#endif //defined DD360Audi
-}
-
-void _DetectPlugInTimeout()
-{
-    log_info("*********** _DetectPlugInTimeout *********** \n");
-    strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
-    ClearDetectPluginFlag();
-    //usleep(50000);
-    sleep(1); //Jerry add
-#if defined DD360Audi
-    ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_SELECT_GUN;
-#else
-    ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_NONE;
-#endif //defined DD360Audi
-}
-
-void _AutoReturnTimeout()
-{
-    log_info("*********** _AutoReturnTimeout %d*********** \n", ShmSysConfigAndInfo->SysInfo.PageIndex);
-    if (ShmSysConfigAndInfo->SysInfo.PageIndex == _LCM_WAIT_FOR_PLUG) {
-        ClearDetectPluginFlag();
-    } else if (ShmSysConfigAndInfo->SysInfo.PageIndex == _LCM_AUTHORIZ_COMP) {
-        DetectPluginStart();
-    }
-    usleep(50000);
-#if defined DD360Audi
-    ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_SELECT_GUN;
-#else
-    ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_NONE;
-#endif //defined DD360Audi
-}
-
-void StopSystemTimeoutDet()
-{
-    gettimeofday(&ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer, NULL);
-    ShmSysConfigAndInfo->SysInfo.SystemTimeoutFlag = Timeout_None;
-}
-
-void _SelfTestTimeout()
-{
-    if (ShmSysConfigAndInfo->SysInfo.BootingStatus != BOOT_COMPLETE) {
-        for (uint8_t gun_index = 0; gun_index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; gun_index++) {
-            setChargerMode(gun_index, MODE_ALARM);
-        }
-    }
-    ShmPsuData->Work_Step = _NO_WORKING;
-    ShmSysConfigAndInfo->SysInfo.SelfTestSeq = _STEST_FAIL;
-    log_info("Self test timeout. \n");
-}
-
-void CheckConnectionTimeout(void)
-{
-#if defined DD360 || defined DD360Audi || defined DD360ComBox
-    if (gAudiCustInfo->RemoteSetup.ConnectionTimeout != 0) { //Jerry add
-        _connectionTimeout = gAudiCustInfo->RemoteSetup.ConnectionTimeout;
-    } else {
-        _connectionTimeout = CONN_PLUG_TIME_OUT;
-    }
-
-    return;
-#endif //defined DD360 || defined DD360Audi || defined DD360ComBox
-
-    if (system("pidof -s OcppBackend > /dev/null") != 0) {
-        _connectionTimeout = CONN_PLUG_TIME_OUT;
-    } else {
-        if (strcmp((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[ConnectionTimeOut].ItemData, "") != 0) {
-            _connectionTimeout = atoi((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[ConnectionTimeOut].ItemData);
-            if (_connectionTimeout <= 0) {
-                _connectionTimeout = CONN_PLUG_TIME_OUT;
-            }
-        } else {
-            _connectionTimeout = CONN_PLUG_TIME_OUT;
-        }
-    }
-}
-
-void CreateTimeoutFork(void)
-{
-    pid_t timeoutPid;
-
-    timeoutPid = fork();
-    log_info("CreateTimeoutFork = %d\r\n", timeoutPid);
-    if (timeoutPid == 0) {
-        gettimeofday(&_cmdSubPriority_time, NULL);
-        CheckConnectionTimeout();
-
-        while (1) {
-            if ((GetTimeoutValue(_cmdSubPriority_time) / 1000) > 5000) {
-                CheckConnectionTimeout();
-                gettimeofday(&_cmdSubPriority_time, NULL);
-            }
-
-            //printf("Timeout ***********SystemTimeoutFlag = %d, ********\n", ShmSysConfigAndInfo->SysInfo.SystemTimeoutFlag);
-            // 系統
-            switch (ShmSysConfigAndInfo->SysInfo.SystemTimeoutFlag) {
-            case Timeout_SelftestChk:
-                if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) / uSEC_VAL >= SELFTEST_TIMEOUT) {
-                    _SelfTestTimeout();
-                    StopSystemTimeoutDet();
-                    destroySelGun(DESTROY_ALL_SEL); //jerry add
-                }
-                break;
-
-            case Timeout_Authorizing:
-                if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) / uSEC_VAL >= AUTHORIZE_TIMEOUT) {
-                    _AuthorizedTimeout();
-                    StopSystemTimeoutDet();
-                    destroySelGun(ShmSysConfigAndInfo->SysInfo.CurGunSelected);
-                    if (gAudiCustInfo->AuthorStateFromCabinet[ShmSysConfigAndInfo->SysInfo.CurGunSelected] == YES) { //DoComm no ask cabinet balance
-                        gAudiCustInfo->AuthorStateFromCabinet[ShmSysConfigAndInfo->SysInfo.CurGunSelected] = NO;
-                        ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DisconnectedFromDo = ABNORMAL;
-                        log_error("Author timeout restart DoComm\r\n");
-                        system("killall Module_DoComm");
-                        sleep(1);
-                        system("/root/Module_DoComm &");
-                    }
-                }
-                break;
-
-            case Timeout_VerifyFail:
-                if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) / uSEC_VAL >= AUTHORIZE_FAIL_TIMEOUT) {
-                    _AutoReturnTimeout();
-                    StopSystemTimeoutDet();
-                    destroySelGun(ShmSysConfigAndInfo->SysInfo.CurGunSelected);
-                    if (gAudiCustInfo->AuthorStateFromCabinet[ShmSysConfigAndInfo->SysInfo.CurGunSelected] == YES) { //DoComm no ask cabinet balance
-                        gAudiCustInfo->AuthorStateFromCabinet[ShmSysConfigAndInfo->SysInfo.CurGunSelected] = NO;
-                        ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DisconnectedFromDo = ABNORMAL;
-                        log_error("Author timeout restart DoComm\r\n");
-                        system("killall Module_DoComm");
-                        sleep(1);
-                        system("/root/Module_DoComm &");
-                    }
-                }
-                break;
-
-            case Timeout_VerifyComp:
-                if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) / uSEC_VAL >= AUTHORIZE_COMP_TIMEOUT) {
-                    _AutoReturnTimeout();
-                    StopSystemTimeoutDet();
-                }
-                break;
-
-            case Timeout_WaitPlug:
-                if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) / uSEC_VAL >= _connectionTimeout) {
-                    _DetectPlugInTimeout();
-                    StopSystemTimeoutDet();
-                    destroySelGun(ShmSysConfigAndInfo->SysInfo.CurGunSelected);
-                }
-                break;
-
-            case Timeout_ReturnToChargingGunDet:
-                if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) / uSEC_VAL >= RETURN_TO_CHARGING_PAGE) {
-#if defined DD360Audi
-                    if (getCurLcmPage() != _LCM_PRE_CHARGE &&
-                            getCurLcmPage() != _LCM_CHARGING &&
-                            getCurLcmPage() != _LCM_COMPLETE) {
-                        destroySelGun(ShmSysConfigAndInfo->SysInfo.CurGunSelected); //jerry add
-
-                    }
-#endif //defined DD360Audi
-                    DisplayChargingInfo();
-                    StopSystemTimeoutDet();
-                }
-                break;
-
-            case Timeout_AuthorizingForStop:
-                if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) / uSEC_VAL >= AUTHORIZE_STOP_TIMEOUT) {
-                    strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
-                    ClearAuthorizedFlag();
-                    StopSystemTimeoutDet();
-                }
-                break;
-
-            } //switch
-
-            // 各槍
-            for (uint8_t gun_index = 0; gun_index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; gun_index++) {
-                //printf("Timeout ***********TimeoutFlag = %d, ********\n", chargingInfo[gun_index]->TimeoutFlag);
-                switch (chargingInfo[gun_index]->TimeoutFlag) {
-                case Timeout_Preparing:
-                    if (GetTimeoutValue(chargingInfo[gun_index]->TimeoutTimer) / uSEC_VAL >= GUN_PREPARE_TIMEOUT) {
-                        _PrepareTimeout(gun_index);
-                        StopGunInfoTimeoutDet(gun_index);
-                        destroySelGun(gun_index); //jerry add
-                    }
-                    break;
-
-                case Timeout_EvChargingDet:
-                    if (GetTimeoutValue(chargingInfo[gun_index]->TimeoutTimer) / uSEC_VAL >= GUN_EV_WAIT_TIMEOUT) {
-                        _DetectEvChargingEnableTimeout(gun_index);
-                        StopGunInfoTimeoutDet(gun_index);
-                        destroySelGun(gun_index); //jerry add
-                    }
-                    break;
-
-                case Timeout_EvseChargingDet:
-                    if (GetTimeoutValue(chargingInfo[gun_index]->TimeoutTimer) / uSEC_VAL >= GUN_EVSE_WAIT_TIMEOUT) {
-                        _DetectEvseChargingEnableTimeout(gun_index);
-                        StopGunInfoTimeoutDet(gun_index);
-                        destroySelGun(gun_index); //jerry add
-                    }
-                    break;
-
-                case Timeout_EvseCompleteDet:
-                    if (GetTimeoutValue(chargingInfo[gun_index]->TimeoutTimer) / uSEC_VAL >= GUN_COMP_WAIT_TIMEOUT) {
-                        StopGunInfoTimeoutDet(gun_index);
-                        destroySelGun(gun_index); //jerry add
-                    }
-                    break;
-
-                case Timeout_ForCcsPrechargeDet:
-                    if (GetTimeoutValue(chargingInfo[gun_index]->TimeoutTimer) / uSEC_VAL >= GUN_PRECHARGING_TIMEOUT) {
-                        _CcsPrechargeTimeout(gun_index);
-                        StopGunInfoTimeoutDet(gun_index);
-                        destroySelGun(gun_index); //jerry add
-                    }
-                    break;
-
-                case Timeout_SelectGun: //Jerry add
-                    if (GetTimeoutValue(chargingInfo[gun_index]->TimeoutTimer) / uSEC_VAL >= SEL_GUN_TIMEOUT) {
-                        StopGunInfoTimeoutDet(gun_index);
-                        destroySelGun(gun_index); //jerry add
-                    }
-                    break;
-                } //switch
-            } //for
-            sleep(1);
-        }//while
-    }
-}

+ 134 - 8
EVSE/Projects/DD360/Apps/CSU/Update.c → EVSE/Projects/DD360ComBox/Apps/CSU/UpgradeFW.c

@@ -3,30 +3,115 @@
 #include <string.h>
 #include <stdint.h>
 
+#include <sys/types.h>
+#include <dirent.h>
+
 #include "../Config.h"
 #include "../Log/log.h"
 #include "../Define/define.h"
 #include "../ShareMemory/shmMem.h"
 
+#include "../main.h"
+
+//------------------------------------------------------------------------------
+static char *_priPortName = "/dev/ttyS1";
+static char *_485PortName = "/dev/ttyS5";
+
 //------------------------------------------------------------------------------
-int CheckUpdateProcess(void)
+static int InitComPort(uint8_t target)
+{
+    int fd;
+    struct termios tios;
+
+    if (target == UPGRADE_PRI) {
+        fd = open(_priPortName, O_RDWR);
+    } else if (target == UPGRADE_FAN ||  target == UPGRADE_RB || target == UPGRADE_AC || target == UPGRADE_LED) {
+        fd = open(_485PortName, O_RDWR);
+    }
+
+    if (fd <= 0) {
+#ifdef SystemLogMessage
+        log_error("open 407 Communication port NG \n");
+#endif
+        return -1;
+    }
+    ioctl (fd, TCGETS, &tios);
+    tios.c_cflag = B115200 | CS8 | CLOCAL | CREAD;
+    tios.c_lflag = 0;
+    tios.c_iflag = 0;
+    tios.c_oflag = 0;
+    tios.c_cc[VMIN] = 0;
+    tios.c_cc[VTIME] = (uint8_t)1;
+    tios.c_lflag = 0;
+    tcflush(fd, TCIFLUSH);
+    ioctl (fd, TCSETS, &tios);
+
+    return fd;
+}
+
+static int InitCanBus(void)
+{
+    int fd = -1;
+    int nbytes;
+    struct timeval tv;
+    struct ifreq ifr0;
+    struct sockaddr_can addr0;
+
+    system("/sbin/ip link set can0 down");
+    system("/sbin/ip link set can0 type can bitrate 500000 restart-ms 100");
+    system("/sbin/ip link set can0 up");
+
+    fd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
+
+    tv.tv_sec = 0;
+    tv.tv_usec = 10000;
+    if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct  timeval)) < 0) {
+#ifdef SystemLogMessage
+        log_error("Set SO_RCVTIMEO NG");
+#endif
+    }
+    nbytes = 40960;
+    if (setsockopt(fd, SOL_SOCKET,  SO_RCVBUF, &nbytes, sizeof(int)) < 0) {
+#ifdef SystemLogMessage
+        log_error("Set SO_RCVBUF NG");
+#endif
+    }
+    nbytes = 40960;
+    if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &nbytes, sizeof(int)) < 0) {
+#ifdef SystemLogMessage
+        log_error("Set SO_SNDBUF NG");
+#endif
+    }
+
+    strcpy(ifr0.ifr_name, "can0");
+    ioctl(fd, SIOCGIFINDEX, &ifr0); /* ifr.ifr_ifindex gets filled with that device's index */
+    addr0.can_family = AF_CAN;
+    addr0.can_ifindex = ifr0.ifr_ifindex;
+    bind(fd, (struct sockaddr *)&addr0, sizeof(addr0));
+
+    return fd;
+}
+
+static int CheckUpdateProcess(void)
 {
     //bool isPass = true;
     uint8_t retSucc = 0;
     uint8_t retFail = 0;
     uint8_t index = 0;
     uint8_t target = 0;
+    char Buf[256];
     char *new_str = NULL;
     uint8_t *ptr = NULL;
     int fd = 0;
     int CanFd = 0;
     int uartFd = 0;
     unsigned int Type = 0;
-    long int MaxLen = (48 * 1024 * 1024, ImageLen = 0);
+    long int MaxLen = 48 * 1024 * 1024, ImageLen = 0;
     DIR *d;
     struct dirent *dir;
     struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
-    struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
+    DcCommonInfo *ShmDcCommonData = (DcCommonInfo *)GetShmDcCommonData();
+    struct ChargingInfoData *pDcChargingInfo = NULL;
 
     d = opendir("/mnt/");
     if (d) {
@@ -84,14 +169,47 @@ int CheckUpdateProcess(void)
                 case 0x10000008:
                 case 0x10000009:
                 case 0x1000000A:
+                    CanFd = InitCanBus();
+                    if (CanFd > 0) {
+                        for (index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+                            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+                            if (pDcChargingInfo->Type == _Type_CCS_2) {
+                                uint8_t targetID = pDcChargingInfo->Evboard_id;
+
+                                if (pSysConfig->TotalConnectorCount == 1 &&
+                                        ShmDcCommonData->CcsVersion == _CCS_VERSION_CHECK_TAG_V015S0) {
+                                    targetID += 1;
+                                }
+
+                                system("echo 3 > /proc/sys/vm/drop_caches");
+                                sleep(2);
+                                log_info("Upgrade CCS Processing..target id = %d \n", targetID);
+                                if (Upgrade_CCS(CanFd,
+                                                Type,
+                                                targetID,
+                                                new_str,
+                                                (char *)pSysConfig->ModelName) == FAIL) {
+                                    log_info("Upgrade CCS Failed \n");
+                                    retFail++;
+                                } else {
+                                    retSucc++;
+                                }
+                            }
+                        }
+                        close(CanFd);
+                    }
+                    memset(Buf, 0, sizeof(Buf));
+                    sprintf(Buf, "rm -rvf /mnt/%s", new_str);
+                    system(Buf);
                     //isPass = true;
+#if 0
                     CanFd = InitCanBus();
                     if (CanFd > 0) {
                         for (index = 0; index < pSysConfig->TotalConnectorCount; index++) {
                             //if (!isPass) {
                             //    break;
                             //}
-
                             if (chargingInfo[index]->Type == _Type_CCS_2) {
                                 if (Upgrade_CCS(CanFd, Type, chargingInfo[index]->Evboard_id, new_str, (char *)pSysConfig->ModelName) == FAIL) {
                                     //isPass = false;
@@ -112,6 +230,7 @@ int CheckUpdateProcess(void)
                         retSucc++;
                     }
                     //return isPass;
+#endif //0
                     break;
 
                 case 0x10000006:
@@ -157,13 +276,15 @@ int CheckUpdateProcess(void)
                     CanFd = InitCanBus();
                     if (CanFd > 0) {
                         for (index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+                            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
                             //if (!isPass) {
                             //    break;
                             //}
 
-                            if ((Type == 0x1000000B && chargingInfo[index]->Type == _Type_Chademo) ||
-                                    (Type == 0x1000000C && chargingInfo[index]->Type == _Type_GB)) {
-                                if (Upgrade_CAN(CanFd, Type, chargingInfo[index]->Evboard_id, new_str, (char *)pSysConfig->ModelName) == PASS) {
+                            if ((Type == 0x1000000B && pDcChargingInfo->Type == _Type_Chademo) ||
+                                    (Type == 0x1000000C && pDcChargingInfo->Type == _Type_GB)) {
+                                if (Upgrade_CAN(CanFd, Type, pDcChargingInfo->Evboard_id, new_str, (char *)pSysConfig->ModelName) == PASS) {
                                     //isPass = PASS;
                                     retSucc++;
                                 } else {
@@ -201,6 +322,8 @@ void CheckFwUpdateFunction(void)
 {
     struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
     struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
+    struct OCPP16Data *ShmOCPP16Data = (struct OCPP16Data *)GetShmOCPP16Data();
+    struct ChargingInfoData *pAcChargingInfo = NULL;
 
     //log_info("pSysInfo->FirmwareUpdate = %d \n", pSysInfo->FirmwareUpdate);
     if (pSysInfo->FirmwareUpdate == YES) {
@@ -240,8 +363,11 @@ void CheckFwUpdateFunction(void)
             for (uint8_t _index = 0; _index < pSysConfig->TotalConnectorCount; _index++) {
                 setChargerMode(_index, MODE_UPDATE);
             }
+
             for (uint8_t _index = 0; _index < pSysConfig->AcConnectorCount; _index++) {
-                ac_chargingInfo[_index]->SystemStatus = MODE_UPDATE;
+                pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(_index);
+
+                pAcChargingInfo->SystemStatus = MODE_UPDATE;
             }
 
             uint8_t updateResult = CheckUpdateProcess();

+ 48 - 0
EVSE/Projects/DD360ComBox/Apps/CSU/WatchDog.c

@@ -0,0 +1,48 @@
+#include <stdio.h>      /*標準輸入輸出定義*/
+#include <stdlib.h>     /*標準函數庫定義*/
+#include <string.h>
+#include <stdint.h>
+
+#include "../Config.h"
+#include "../Log/log.h"
+#include "../Define/define.h"
+#include "../ShareMemory/shmMem.h"
+
+//------------------------------------------------------------------------------
+static int gWatchDogfd = -1;
+
+//------------------------------------------------------------------------------
+void WriteWatchDogState(char *value)
+{
+    write(gWatchDogfd, value, 1);
+}
+
+static int initWatchDog(void)
+{
+    int fd;
+    system("/usr/bin/fuser -k /dev/watchdog");
+    sleep(1);
+    system("echo V > /dev/watchdog");
+    sleep(1);
+    fd = open("/dev/watchdog", O_RDWR);
+
+    if (fd <= 0) {
+        log_error("System watch dog initial fail.\r\n");
+    }
+
+    return fd;
+}
+
+void CreateWatchdog(void)
+{
+    struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
+    struct AlarmCodeData *pAlarmCode = (struct AlarmCodeData *)GetShmAlarmCodeData();
+
+    if (pSysConfig->SwitchDebugFlag == NO) {
+        gWatchDogfd = initWatchDog();
+
+        if (gWatchDogfd < 0) {
+            pAlarmCode->AlarmEvents.bits.CsuInitFailed = 1;
+        }
+    }
+}

+ 15 - 0
EVSE/Projects/DD360ComBox/Apps/CSU/ZipFile.c

@@ -1,7 +1,21 @@
+#include <stdio.h>      /*標準輸入輸出定義*/
+#include <stdlib.h>     /*標準函數庫定義*/
+#include <string.h>
+#include <stdint.h>
 
+#include <sys/types.h>
+#include <dirent.h>
+
+#include "../Config.h"
+#include "../Log/log.h"
+#include "../Define/define.h"
+#include "../ShareMemory/shmMem.h"
+
+//------------------------------------------------------------------------------
 void zipLogFiles(void)
 {
     const char *logPath = "/Storage/SystemLog";
+
     // 獲取目錄
     DIR *pDir = opendir(logPath);
     if (pDir != NULL) {
@@ -57,6 +71,7 @@ void zipLogFiles(void)
             }
         }
     }
+
     // Close folder
     closedir(pDir);
 }

+ 7407 - 0
EVSE/Projects/DD360ComBox/Apps/CSU/main.c

@@ -0,0 +1,7407 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/mman.h>
+#include <linux/wireless.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include <unistd.h>
+#include <stdarg.h>
+#include <stdio.h>      /*標準輸入輸出定義*/
+#include <stdlib.h>     /*標準函數庫定義*/
+#include <unistd.h>     /*Unix 標準函數定義*/
+#include <fcntl.h>      /*檔控制定義*/
+#include <termios.h>    /*PPSIX 終端控制定義*/
+#include <errno.h>      /*錯誤號定義*/
+#include <errno.h>
+#include <string.h>
+#include <stdint.h>
+#include <time.h>
+#include <ctype.h>
+#include <ifaddrs.h>
+#include <math.h>
+#include "./Define/define.h"
+#include <stdbool.h>
+#include <dirent.h>
+
+#include "Config.h"
+#include "main.h"
+#include "common.h"
+#include "timeout.h"
+
+#include "./Log/log.h"
+#include "./Define/define.h"
+#include "./ShareMemory/shmMem.h"
+
+#if defined DD360 ||defined DD360Audi || defined DD360ComBox
+#include "./SelectGun/SelectGun.h"
+#endif //defined DD360Audi
+
+//------------------------------------------------------------------------------
+char *valid_Internet[2] = {"8.8.8.8", "180.76.76.76"};
+uint8_t mask_table[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
+int whileLoopTime = 10000; // 10 ms
+//int wtdFd = -1;
+//uint8_t _authorizeIndex = NO_DEFINE;
+
+//struct SysConfigAndInfo         *ShmSysConfigAndInfo;
+//struct StatusCodeData           *ShmStatusCodeData;
+static struct SysInfoData *pSysInfo = NULL;
+static struct SysConfigData *pSysConfig = NULL;
+static struct WARNING_CODE_INFO *pSysWarning = NULL;
+
+static struct AlarmCodeData *pAlarmCode = NULL;
+static struct FaultCodeData *pFaultCode = NULL;
+static struct InfoCodeData  *pInfoCode = NULL;
+
+static struct PsuData *ShmPsuData = NULL;
+static struct CHAdeMOData *ShmCHAdeMOData = NULL;
+static struct GBTData *ShmGBTData = NULL;
+static struct CcsData *ShmCcsData = NULL;
+static struct PrimaryMcuData *ShmPrimaryMcuData = NULL;
+static struct FanModuleData *ShmFanModuleData = NULL;
+static struct RelayModuleData *ShmRelayModuleData = NULL;
+static struct LedModuleData *ShmLedModuleData = NULL;
+static struct OCPP16Data *ShmOCPP16Data = NULL;
+static DcCommonInfo *ShmDcCommonData = NULL;
+
+static struct ChargingInfoData *pDcChargingInfo = NULL;
+static struct ChargingInfoData *pAcChargingInfo = NULL;
+
+//struct ChargingInfoData *chargingInfo[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
+//struct ChargingInfoData *ac_chargingInfo[AC_QUANTITY];
+struct timeb startChargingTime[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
+struct timeb endChargingTime[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
+
+#if defined DD360 ||defined DD360Audi || defined DD360ComBox
+static SelectGunInfo             *gAudiCustInfo = NULL; //Jerry add
+#endif //defined DD360Audi
+static EvBoardErrMsg gEvBoardErr = {0};
+
+// for initial index to check EV board type is correct
+//uint8_t _gunIndex = 0;
+//uint8_t _acgunIndex = 0;
+//uint8_t _chademoIndex = 0;
+//uint8_t _ccsIndex = 0;
+//uint8_t _gb_Index = 0;
+//uint8_t _ac_Index = 0;
+uint8_t bd0_1_status = 0;
+uint8_t bd0_2_status = 0;
+uint8_t bd1_1_status = 0;
+uint8_t bd1_2_status = 0;
+
+//static uint8_t restartFlag = 0;
+
+//bool isCardScan = false;
+//bool isModelNameMatch = true;
+
+//int rfidFd = -1;
+//char *rfidPortName = "/dev/ttyS2";
+char *fwVersion = "V1.08.00.0000.00"; // "V0.16.00.0000.00";
+
+//sqlite3 *localDb;
+bool isDb_ready;
+
+//------------------------------------------------------------------------------
+//bool IsAuthorizingMode();
+//void ClearAuthorizedFlag();
+//bool isDetectPlugin();
+void ClearDetectPluginFlag();
+
+long long DiffTimebWithNow(struct timeb ST);
+uint8_t DetectBitValue(uint8_t _byte, uint8_t _bit);
+void SetBitValue(uint8_t *_byte, uint8_t _bit, uint8_t value);
+//void ChargingTerminalProcess(uint8_t gunIndex);
+//void ChkPrimaryStatus();
+//void StartSystemTimeoutDet(uint8_t flag);
+//void StopSystemTimeoutDet();
+//void StartGunInfoTimeoutDet(uint8_t gunIndex, uint8_t flag);
+//void StopGunInfoTimeoutDet(uint8_t gunIndex);
+//int StoreLogMsg_1(const char *fmt, ...);
+unsigned long GetTimeoutValue(struct timeval _sour_time);
+void gpio_set_value(unsigned int gpio, unsigned int value);
+//void ChangeGunSelectByIndex(uint8_t sel);
+void InformOcppErrOccur(uint8_t codeType);
+
+void RecordAlarmCode(uint8_t gunIndex, char *code);
+void RecordWarningCode(uint8_t gunIndex, char *code);
+void ReleaseWarningCodeByString(uint8_t gunIndex, char *code);
+void ReleaseAlarmCode(uint8_t gunIndex);
+void ResetChargerAlarmCode(uint8_t gunIndex, char *code);
+
+void AdjustChargerCurrent();
+
+//------------------------------------------------------------------------------
+//Primary.c
+extern void PrimaryLedIndicatorCtrlFork(void);
+extern void ChkPrimaryStatus(void);
+
+//RFID.c
+extern void CreateRfidFork(void);
+extern void ScannerCardProcess(void);
+extern bool GetIsCardScan(void);
+extern void SetIsCardScan(bool value);
+
+//SelfTest.c
+extern void SelfTestRun(void);
+
+//UpgradeFW.c
+extern void CheckFwUpdateFunction(void);
+
+//Ethernet.c
+extern void InitEthernet(void);
+extern void GetMacAddress(void);
+
+//WatchDog.c
+extern void CreateWatchdog(void);
+extern void WriteWatchDogState(char *value);
+
+//ZipFile.c
+extern void zipLogFiles(void);
+
+///DataBase/DataBase.c
+extern int DB_Open(void);
+extern int DB_Insert_Record(int gun_index);
+extern int DB_Update_Operactive(uint8_t gun_index, uint8_t IsAvailable);
+extern int DB_Get_Operactive(uint8_t gun_index);
+extern int DB_Reboot_Record(void);
+
+//------------------------------------------------------------------------------
+//--- share memory value ---
+//------------------------------------------------------------------------------
+static void changeLcmPage(uint8_t index)
+{
+    pSysInfo->SystemPage = index;
+}
+
+static uint8_t getCurLcmPage(void)
+{
+    return pSysInfo->SystemPage;
+}
+
+//------------------------------------------------------------------------------
+void destroySelGun(uint8_t curGun)
+{
+    uint8_t i = 0;
+    uint8_t totalGun = pSysConfig->TotalConnectorCount;
+
+#if !defined DD360Audi
+    return;
+#endif //!defined DD360Audi
+
+    //for status timeout
+    if (curGun == DESTROY_ALL_SEL) {
+        gAudiCustInfo->SelGunInfo.RightGun = SEL_GUN_RELEASE;
+        gAudiCustInfo->SelGunInfo.LeftGun = SEL_GUN_RELEASE;
+        log_info("destroy all gun = %d, %d\r\n",
+                 gAudiCustInfo->SelGunInfo.LeftGun,
+                 gAudiCustInfo->SelGunInfo.RightGun);
+        for (i = 0; i < totalGun; i++) {
+            StopGunInfoTimeoutDet(i);
+            memset(&gAudiCustInfo->PricesInfo[i], 0, sizeof(PricesInfo));
+        }
+        pSysInfo->CurGunSelected = 0;
+        strcpy((char *)pSysConfig->UserId, "");
+        //changeLcmPage(_LCM_SELECT_GUN);
+        return;
+    }
+
+    //for charging timeout or complete
+    if ((curGun == LEFT_GUN_NUM) && (gAudiCustInfo->SelGunInfo.LeftGun != SEL_GUN_RELEASE)) {
+        if (gAudiCustInfo->SelGunInfo.LeftGun == SEL_GUN_CONFIRM ||
+                gAudiCustInfo->SelGunInfo.LeftGun == SEL_GUN_ATHOR) {
+            changeLcmPage(_LCM_SELECT_GUN);
+        }
+        gAudiCustInfo->SelGunInfo.LeftGun = SEL_GUN_RELEASE;
+        StopGunInfoTimeoutDet(LEFT_GUN_NUM);
+        if (ShmOCPP16Data->SpMsg.bits.AuthorizeConf != NO) {
+            ClearAuthorizedFlag();
+        }
+
+        log_info("destroy left gun, cur page = %d\r\n", getCurLcmPage());
+        if (getCurLcmPage() == pSysInfo->SystemPage) {
+            log_info("clear left balance\r\n");
+            memset(&gAudiCustInfo->PricesInfo[curGun], 0, sizeof(PricesInfo));
+            gAudiCustInfo->PricesInfo[curGun].Balance = FAIL_BALANCE_PRICES;
+        }
+    }
+
+    if ((curGun == RIGHT_GUN_NUM) && (gAudiCustInfo->SelGunInfo.RightGun != SEL_GUN_RELEASE)) {
+        if (gAudiCustInfo->SelGunInfo.RightGun == SEL_GUN_CONFIRM ||
+                gAudiCustInfo->SelGunInfo.RightGun == SEL_GUN_ATHOR) {
+            changeLcmPage(_LCM_SELECT_GUN);
+        }
+        gAudiCustInfo->SelGunInfo.RightGun = SEL_GUN_RELEASE;
+        StopGunInfoTimeoutDet(RIGHT_GUN_NUM);
+        if (ShmOCPP16Data->SpMsg.bits.AuthorizeConf != NO) {
+            ClearAuthorizedFlag();
+        }
+
+        log_info("destroy right gun, cur page = %d\r\n", getCurLcmPage());
+        if (getCurLcmPage() == pSysInfo->SystemPage) {
+            log_info("clear right balance\r\n");
+            memset(&gAudiCustInfo->PricesInfo[curGun], 0, sizeof(PricesInfo));
+            gAudiCustInfo->PricesInfo[curGun].Balance = FAIL_BALANCE_PRICES;
+        }
+    }
+}
+
+static int waitRightGunPlugIt(uint8_t curGun)
+{
+#if !defined DD360Audi
+    return;
+#endif //!defined DD360Audi
+
+    if ((curGun == RIGHT_GUN_NUM) && (gAudiCustInfo->SelGunInfo.RightGun == SEL_GUN_ATHOR)) {
+        return PASS;
+    }
+
+    return FAIL;
+}
+
+static int waitLeftGunPlugIt(uint8_t curGun)
+{
+#if !defined DD360Audi
+    return;
+#endif //!defined DD360Audi
+
+    if ((curGun == LEFT_GUN_NUM) && (gAudiCustInfo->SelGunInfo.LeftGun == SEL_GUN_ATHOR)) {
+        return PASS;
+    }
+
+    return FAIL;
+}
+
+void setSelGunWaitToAuthor(uint8_t curSel)
+{
+#if !defined DD360Audi
+    return;
+#endif //!defined DD360Audi
+
+    if (curSel == LEFT_GUN_NUM && gAudiCustInfo->SelGunInfo.LeftGun == SEL_GUN_CONFIRM) {
+        gAudiCustInfo->SelGunInfo.LeftGun = SEL_GUN_ATHOR;
+        //printf("setSelGunWaitToAuthor left\r\n");
+        StopGunInfoTimeoutDet(curSel);
+    } else if (curSel == RIGHT_GUN_NUM && gAudiCustInfo->SelGunInfo.RightGun == SEL_GUN_CONFIRM) {
+        gAudiCustInfo->SelGunInfo.RightGun = SEL_GUN_ATHOR;
+        //printf("setSelGunWaitToAuthor right\r\n");
+        StopGunInfoTimeoutDet(curSel);
+    }
+}
+
+int getConfirmSelectedGun(uint8_t curSel)
+{
+#if !defined DD360Audi
+    return;
+#endif //!defined DD360Audi
+
+    if (((curSel == LEFT_GUN_NUM) && (gAudiCustInfo->SelGunInfo.LeftGun >= SEL_GUN_CONFIRM)) ||
+            ((curSel == RIGHT_GUN_NUM) && (gAudiCustInfo->SelGunInfo.RightGun >= SEL_GUN_CONFIRM))) {
+        return PASS;
+    }
+
+    return FAIL;
+}
+
+void confirmSelGun(uint8_t selGun)
+{
+#if !defined DD360Audi
+    return;
+#endif //!defined DD360Audi
+
+    if (selGun == LEFT_GUN_NUM) {
+        gAudiCustInfo->SelGunInfo.LeftGun = SEL_GUN_CONFIRM;
+        StopGunInfoTimeoutDet(selGun);
+        //printf("confirmSelGun left\r\n");
+    } else if (selGun == RIGHT_GUN_NUM) {
+        gAudiCustInfo->SelGunInfo.RightGun = SEL_GUN_CONFIRM;
+        StopGunInfoTimeoutDet(selGun);
+        //printf("confirmSelGun right\r\n");
+    }
+
+    changeLcmPage(_LCM_IDLE);
+
+    StartGunInfoTimeoutDet(selGun, Timeout_SelectGun);
+}
+
+static void checkGunOTPState(uint8_t _index)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_index);
+
+    switch (pDcChargingInfo->Type) {
+    case _Type_Chademo:
+        if (pDcChargingInfo->ConnectorTemp != UNDEFINED_TEMP) {
+            if (pDcChargingInfo->ConnectorTemp >= GUN_OTP_VALUE) {
+                RecordAlarmCode(_index, "012229");
+            } else if (pDcChargingInfo->ConnectorTemp != 0 &&
+                       pDcChargingInfo->ConnectorTemp < GUN_OTP_RECOVERY) {
+                ResetChargerAlarmCode(_index, "012229");
+            }
+        } else {
+            // 沒接上 Sensor or 異常
+            //RecordAlarmCode(_index, "011018");
+            ResetChargerAlarmCode(_index, "012229");
+        }
+        break;
+
+    case _Type_CCS_2:
+        // CCS 不管甚麼輸出都會有槍溫偵測!!~
+        if (pDcChargingInfo->ConnectorTemp != UNDEFINED_TEMP) {
+            ResetChargerAlarmCode(_index, "011019");
+
+            if (pDcChargingInfo->ConnectorTemp >= GUN_OTP_VALUE) {
+                RecordAlarmCode(_index, "012230");
+            } else if (pDcChargingInfo->ConnectorTemp != 0 &&
+                       pDcChargingInfo->ConnectorTemp < GUN_OTP_RECOVERY) {
+                ResetChargerAlarmCode(_index, "012230");
+            }
+
+            //ResetChargerAlarmCode(_index, "011019");
+        } else {
+            // 沒接上 Sensor or 異常
+            RecordAlarmCode(_index, "011019");
+            ResetChargerAlarmCode(_index, "012230");
+        }
+        break;
+
+    case _Type_GB:
+        if (pDcChargingInfo->ConnectorTemp != UNDEFINED_TEMP) {
+            if (pDcChargingInfo->ConnectorTemp >= GUN_OTP_VALUE) {
+                RecordAlarmCode(_index, "012231");
+            } else if (pDcChargingInfo->ConnectorTemp != 0 &&
+                       pDcChargingInfo->ConnectorTemp < GUN_OTP_RECOVERY) {
+                ResetChargerAlarmCode(_index, "012231");
+            }
+        } else {
+            // 沒接上 Sensor or 異常
+            RecordAlarmCode(_index, "011020");
+            ResetChargerAlarmCode(_index, "012231");
+        }
+        break;
+    }
+}
+
+static void collectError(uint8_t gunIndex)
+{
+    gEvBoardErr.GunErrMessage |= ShmDcCommonData->ConnectErrList[gunIndex].GunErrMessage;
+}
+
+static void checkGBTAlarmState(uint8_t gunType)
+{
+    // GFD Trip
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 0)) {
+        pAlarmCode->AlarmEvents.bits.GbGfdTrip = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.GbGfdTrip = NO;
+    }
+
+    // UVP
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 1)) {
+        pAlarmCode->AlarmEvents.bits.GbtOutputUVPFail = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.GbtOutputUVPFail = NO;
+    }
+
+    // OTP
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 2)) {
+        pAlarmCode->AlarmEvents.bits.GbConnectorOTP = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.GbConnectorOTP = NO;
+    }
+
+    // OVP
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 3)) {
+        pAlarmCode->AlarmEvents.bits.SystemGbOutputOVP = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.SystemGbOutputOVP = NO;
+    }
+
+    // GFD Warning
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 4)) {
+        pAlarmCode->AlarmEvents.bits.GbGroundfaultWarning = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.GbGroundfaultWarning = NO;
+    }
+
+    // Relay Welding
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 5)) {
+        pFaultCode->FaultEvents.bits.GbOutputRelayWelding = YES;
+    } else {
+        pFaultCode->FaultEvents.bits.GbOutputRelayWelding = NO;
+    }
+
+    // Relay Driving
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 6)) {
+        pFaultCode->FaultEvents.bits.GbOutputRelayDrivingFault = YES;
+    } else {
+        pFaultCode->FaultEvents.bits.GbOutputRelayDrivingFault = NO;
+    }
+
+    // Connect temp Sensor broken
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 7)) {
+        pFaultCode->FaultEvents.bits.GbConnectorTempSensorBroken = YES;
+    } else {
+        pFaultCode->FaultEvents.bits.GbConnectorTempSensorBroken = NO;
+    }
+}
+
+static void checkCCSAlarmState(uint8_t gunType)
+{
+    // GFD Trip
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 0)) {
+        pAlarmCode->AlarmEvents.bits.CcsGfdTrip = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.CcsGfdTrip = NO;
+    }
+
+    // UVP
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 1)) {
+        pAlarmCode->AlarmEvents.bits.CcsOutputUVPFail = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.CcsOutputUVPFail = NO;
+    }
+
+    // OTP
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 2)) {
+        pAlarmCode->AlarmEvents.bits.CcsConnectorOTP = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.CcsConnectorOTP = NO;
+    }
+
+    // OVP
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 3)) {
+        pAlarmCode->AlarmEvents.bits.SystemCcsOutputOVP = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.SystemCcsOutputOVP = NO;
+    }
+
+    // GFD Warning
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 4)) {
+        pAlarmCode->AlarmEvents.bits.CcsGroundfaultWarning = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.CcsGroundfaultWarning = NO;
+    }
+
+    // Relay Welding
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 5)) {
+        pFaultCode->FaultEvents.bits.CcsOutputRelayWelding = YES;
+    } else {
+        pFaultCode->FaultEvents.bits.CcsOutputRelayWelding = NO;
+    }
+
+    // Relay Driving
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 6)) {
+        pFaultCode->FaultEvents.bits.CcsOutputRelayDrivingFault = YES;
+    } else {
+        pFaultCode->FaultEvents.bits.CcsOutputRelayDrivingFault = NO;
+    }
+
+    // Connect temp Sensor broken
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 7)) {
+        pFaultCode->FaultEvents.bits.CcsConnectorTempSensorBroken = YES;
+    } else {
+        pFaultCode->FaultEvents.bits.CcsConnectorTempSensorBroken = NO;
+    }
+}
+
+static void checkChaDeMoAlarmState(uint8_t gunType)
+{
+    // GFD Trip
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 0)) {
+        pAlarmCode->AlarmEvents.bits.ChademoGfdTrip = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.ChademoGfdTrip = NO;
+    }
+
+    // UVP
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 1)) {
+        pAlarmCode->AlarmEvents.bits.ChademoOutputUVPFail = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.ChademoOutputUVPFail = NO;
+    }
+
+    // OTP
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 2)) {
+        pAlarmCode->AlarmEvents.bits.ChademoConnectorOTP = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.ChademoConnectorOTP = NO;
+    }
+
+    // OVP
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 3)) {
+        pAlarmCode->AlarmEvents.bits.SystemChademoOutputOVP = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.SystemChademoOutputOVP = NO;
+    }
+
+    // GFD Warning
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 4)) {
+        pAlarmCode->AlarmEvents.bits.ChademoGroundWarning = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.ChademoGroundWarning = NO;
+    }
+
+    // Relay Welding
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 5)) {
+        pFaultCode->FaultEvents.bits.ChademoOutputRelayWelding = YES;
+    } else {
+        pFaultCode->FaultEvents.bits.ChademoOutputRelayWelding = NO;
+    }
+
+    // Relay Driving
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 6)) {
+        pFaultCode->FaultEvents.bits.ChademoOutputRelayDrivingFault = YES;
+    } else {
+        pFaultCode->FaultEvents.bits.ChademoOutputRelayDrivingFault = NO;
+    }
+
+    // Connect temp Sensor broken
+    if (DetectBitValue(gEvBoardErr.GunErrMessage >> (8 * gunType), 7)) {
+        pFaultCode->FaultEvents.bits.ChademoConnectorTempSensorBroken = YES;
+    } else {
+        pFaultCode->FaultEvents.bits.ChademoConnectorTempSensorBroken = NO;
+    }
+}
+
+static void checkEvBoardAlarmState(uint8_t gunType)
+{
+    switch (gunType) {
+    case _Type_Chademo:
+        checkChaDeMoAlarmState(gunType);
+        break;
+
+    case _Type_CCS_2:
+        checkCCSAlarmState(gunType);
+        break;
+
+    case _Type_GB:
+        checkGBTAlarmState(gunType);
+        break;
+    }
+}
+
+#if 0
+static uint8_t checkCabinetEthConnectState(LedConfig *ledConfig)
+{
+    uint8_t ret = NO;
+    LedConfig *pLedConfig = (LedConfig *)ledConfig;
+
+    if (pAlarmCode->AlarmEvents.bits.DisconnectedFromDo == YES) {
+        ret = YES;
+        if (pLedConfig->RedLED == YES) {
+            pLedConfig->RedLED = NO;
+        } else {
+            pLedConfig->RedLED = YES;
+        }
+    }
+
+    return ret;
+}
+
+static void PrimaryLedIndicatorCtrlFork(void)
+{
+#if !defined DD360ComBox
+    return;
+#endif //!defined DD360ComBox
+
+    pid_t pid = fork();
+    if (pid == 0) {
+        uint8_t totalGun = pSysConfig->TotalConnectorCount;
+        uint8_t gunIndex = 0;
+        int isContinue = 1;
+        LedConfig *pLedConfig = (LedConfig *)&ShmPrimaryMcuData->OutputDrv.OutputDrvValue[0];
+
+        while (isContinue) {
+            for (gunIndex = 0; gunIndex < totalGun; gunIndex++) {
+                pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+                //printf("led indicator status = %d\r\n", chargingInfo[gunIndex]->SystemStatus);
+                //printf("level = %d\r\n", pSysWarning->Level);
+                switch (pDcChargingInfo->SystemStatus) {
+                case S_BOOTING:
+                    if (pSysInfo->SelfTestSeq == _STEST_COMPLETE) {
+                        //Module_DoComm tcp disconnect
+                        if (pLedConfig->RedLED == YES ||
+                                pLedConfig->YellowLED == YES ||
+                                pLedConfig->GreenLED == YES) {
+                            pLedConfig->RedLED = NO;
+                            pLedConfig->YellowLED = NO;
+                            pLedConfig->GreenLED = NO;
+                        } else {
+                            pLedConfig->RedLED = YES;
+                            pLedConfig->YellowLED = YES;
+                            pLedConfig->GreenLED = YES;
+                        }
+                        break;
+                    }
+
+                    pLedConfig->RedLED = YES;
+                    pLedConfig->YellowLED = YES;
+                    pLedConfig->GreenLED = YES;
+                    break;
+
+                case S_IDLE:
+                    //Module_DoComm connected and system idle
+                    pLedConfig->RedLED = NO;
+                    pLedConfig->YellowLED = NO;
+                    pLedConfig->GreenLED = YES;
+                    break;
+
+                case S_RESERVATION:
+                case S_AUTHORIZING:
+                case S_REASSIGN_CHECK:
+                case S_REASSIGN:
+                case S_PREPARNING:
+                case S_PREPARING_FOR_EV:
+                case S_PREPARING_FOR_EVSE:
+                case S_CCS_PRECHARGE_ST0:
+                case S_CCS_PRECHARGE_ST1:
+                    //precharging status
+                    if (pLedConfig->GreenLED == YES) {
+                        pLedConfig->GreenLED = NO;
+                    } else {
+                        pLedConfig->GreenLED = YES;
+                    }
+                    break;
+
+                case S_CHARGING:
+                    pLedConfig->RedLED = NO;
+                    if (pLedConfig->YellowLED == YES) {
+                        pLedConfig->YellowLED = NO;
+                    } else {
+                        pLedConfig->YellowLED = YES;
+                    }
+                    pLedConfig->GreenLED = NO;
+                    break;
+
+                case S_ALARM:
+                    pLedConfig->YellowLED = NO;
+                    pLedConfig->GreenLED = NO;
+
+                    if (checkCabinetEthConnectState(pLedConfig) == YES) {
+                        break;
+                    }
+
+                    pLedConfig->RedLED = YES;
+                    break;
+
+                case S_TERMINATING:
+                case S_COMPLETE:
+                    if (pSysWarning->Level == 2) {
+                        pLedConfig->YellowLED = NO;
+                        pLedConfig->GreenLED = NO;
+                        if (checkCabinetEthConnectState(pLedConfig) == YES) {
+                            break;
+                        }
+
+                        pLedConfig->RedLED = YES;
+                    } else {
+                        pLedConfig->RedLED = NO;
+                        pLedConfig->YellowLED = YES;
+                        pLedConfig->GreenLED = NO;
+                    }
+                    break;
+
+                case S_MAINTAIN:
+                case S_FAULT:
+                    pLedConfig->YellowLED = NO;
+                    pLedConfig->GreenLED = NO;
+                    if (pSysWarning->Level == 2) {
+                        if (checkCabinetEthConnectState(pLedConfig) == YES) {
+                            break;
+                        }
+
+                        pLedConfig->RedLED = YES;
+                    }
+                    break;
+
+                case S_BOOKING:
+                case S_DEBUG:
+                case S_UPDATE:
+                case S_NONE:
+                    break;
+                }
+
+                usleep(500000);
+            }//switch
+        }//for
+    }//while
+}
+
+//================================================
+// initial can-bus
+//================================================
+int InitCanBus()
+{
+    int                     s0, nbytes;
+    struct timeval          tv;
+    struct ifreq            ifr0;
+    struct sockaddr_can     addr0;
+
+    system("/sbin/ip link set can0 down");
+    system("/sbin/ip link set can0 type can bitrate 500000 restart-ms 100");
+    system("/sbin/ip link set can0 up");
+
+    s0 = socket(PF_CAN, SOCK_RAW, CAN_RAW);
+
+    tv.tv_sec = 0;
+    tv.tv_usec = 10000;
+    if (setsockopt(s0, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct  timeval)) < 0) {
+#ifdef SystemLogMessage
+        log_error("Set SO_RCVTIMEO NG");
+#endif
+    }
+    nbytes = 40960;
+    if (setsockopt(s0, SOL_SOCKET,  SO_RCVBUF, &nbytes, sizeof(int)) < 0) {
+#ifdef SystemLogMessage
+        log_error("Set SO_RCVBUF NG");
+#endif
+    }
+    nbytes = 40960;
+    if (setsockopt(s0, SOL_SOCKET, SO_SNDBUF, &nbytes, sizeof(int)) < 0) {
+#ifdef SystemLogMessage
+        log_error("Set SO_SNDBUF NG");
+#endif
+    }
+
+    strcpy(ifr0.ifr_name, "can0" );
+    ioctl(s0, SIOCGIFINDEX, &ifr0); /* ifr.ifr_ifindex gets filled with that device's index */
+    addr0.can_family = AF_CAN;
+    addr0.can_ifindex = ifr0.ifr_ifindex;
+    bind(s0, (struct sockaddr *)&addr0, sizeof(addr0));
+    return s0;
+}
+
+//================================================
+// initial uart port
+//================================================
+char *_priPortName = "/dev/ttyS1";
+char *_485PortName = "/dev/ttyS5";
+
+int InitComPort(uint8_t target)
+{
+    int fd;
+    struct termios tios;
+
+    if (target == UPGRADE_PRI) {
+        fd = open(_priPortName, O_RDWR);
+    } else if (target == UPGRADE_FAN ||  target == UPGRADE_RB || target == UPGRADE_AC || target == UPGRADE_LED) {
+        fd = open(_485PortName, O_RDWR);
+    }
+
+    if (fd <= 0) {
+#ifdef SystemLogMessage
+        log_error("open 407 Communication port NG \n");
+#endif
+        return -1;
+    }
+    ioctl (fd, TCGETS, &tios);
+    tios.c_cflag = B115200 | CS8 | CLOCAL | CREAD;
+    tios.c_lflag = 0;
+    tios.c_iflag = 0;
+    tios.c_oflag = 0;
+    tios.c_cc[VMIN] = 0;
+    tios.c_cc[VTIME] = (uint8_t)1;
+    tios.c_lflag = 0;
+    tcflush(fd, TCIFLUSH);
+    ioctl (fd, TCSETS, &tios);
+
+    return fd;
+}
+
+//=================================
+// Common routine
+//=================================
+int StoreLogMsg_1(const char *fmt, ...)
+{
+    char Buf[4096 + 256];
+    char buffer[4096];
+    va_list args;
+    struct timeb  SeqEndTime;
+    struct tm *tm;
+
+    va_start(args, fmt);
+    int rc = vsnprintf(buffer, sizeof(buffer), fmt, args);
+    va_end(args);
+
+    memset(Buf, 0, sizeof(Buf));
+    ftime(&SeqEndTime);
+    SeqEndTime.time = time(NULL);
+    tm = localtime(&SeqEndTime.time);
+
+    if (pSysConfig->SwitchDebugFlag == YES) {
+        sprintf(Buf, "%02d:%02d:%02d:%03d - %s",
+                tm->tm_hour, tm->tm_min, tm->tm_sec, SeqEndTime.millitm, buffer);
+        printf("%s \n", Buf);
+    } else {
+        sprintf(Buf, "echo \"%04d-%02d-%02d %02d:%02d:%02d:%03d - %s\" >> /Storage/SystemLog/[%04d.%02d]SystemLog",
+                tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, SeqEndTime.millitm,
+                buffer,
+                tm->tm_year + 1900, tm->tm_mon + 1);
+        system(Buf);
+    }
+
+    return rc;
+}
+#endif //0
+
+unsigned long GetTimeoutValue(struct timeval _sour_time)
+{
+    struct timeval _end_time;
+    gettimeofday(&_end_time, NULL);
+
+    return 1000000 * (_end_time.tv_sec - _sour_time.tv_sec) + _end_time.tv_usec - _sour_time.tv_usec;
+}
+
+int DiffTimeb(struct timeb ST, struct timeb ET)
+{
+    //return milli-second
+    unsigned int StartTime, StopTime;
+
+    StartTime = (unsigned int)ST.time;
+    StopTime = (unsigned int)ET.time;
+    //return (StopTime-StartTime)*1000+ET.millitm-ST.millitm;
+    return (StopTime - StartTime);
+}
+
+bool CheckTimeOut(struct timeb ST)
+{
+    struct timeb ET;
+    unsigned int StartTime, StopTime;
+
+    ftime(&ET);
+    StartTime = (unsigned int) ST.time;
+    StopTime = (unsigned int) ET.time;
+    return (StopTime > StartTime) ? YES : NO;
+}
+
+void setChargerMode(uint8_t gun_index, uint8_t mode)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun_index);
+
+    pDcChargingInfo->SystemStatus = mode;
+}
+
+long long DiffTimebWithNow(struct timeb ST)
+{
+    //return milli-second
+    struct timeb ET;
+    long long StartTime, StopTime;
+
+    ftime(&ET);
+    StartTime = (long long)ST.time;
+    StopTime = (long long)ET.time;
+    return ((StopTime - StartTime) * 1000) + (ET.millitm - ST.millitm);
+}
+
+//==========================================
+// Log
+//==========================================
+void CheckFwSlotStatusLog()
+{
+    if (bd0_1_status == 0 && bd0_2_status == 1) {
+        log_info("Connector 1 : Chademo");
+    } else if (bd0_1_status == 1 && bd0_2_status == 0) {
+        log_info("Connector 1 : CCS");
+    } else if (bd0_1_status == 1 && bd0_2_status == 1) {
+        log_info("Connector 1 : GB");
+    }
+
+    if (bd1_1_status == 0 && bd1_2_status == 1) {
+        log_info("Connector 2 : Chademo");
+    } else if (bd1_1_status == 1 && bd1_2_status == 0) {
+        log_info("Connector 2 : CCS");
+    } else if (bd1_1_status == 1 && bd1_2_status == 1) {
+        log_info("Connector 2 : GB");
+    }
+}
+
+void CheckHwSlotStatusLog(uint8_t index)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+    if (pDcChargingInfo->Type == _Type_Chademo) {
+        log_info("Hw check : Connector %d, Type : Chademo, Evboard_id = %d \n",
+                 index, pDcChargingInfo->Evboard_id);
+    } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+        log_info("Hw check : Connector %d, Type : CCS, Evboard_id = %d \n",
+                 index, pDcChargingInfo->Evboard_id);
+    } else if (pDcChargingInfo->Type == _Type_GB) {
+        log_info("Hw check : Connector %d, Type : GB, Evboard_id = %d \n",
+                 index, pDcChargingInfo->Evboard_id);
+    }
+}
+
+//==========================================
+// Check interface status
+//==========================================
+int isInterfaceUp(const char *interface)
+{
+    int result = FAIL;
+
+    FILE *fp;
+    char cmd[256];
+    char buf[512];
+
+    strcpy(cmd, "ifconfig");
+    fp = popen(cmd, "r");
+    if (fp != NULL) {
+        while (fgets(buf, sizeof(buf), fp) != NULL) {
+            if (strstr(buf, interface) > 0) {
+                result = PASS;
+            }
+        }
+    }
+    pclose(fp);
+
+    return result;
+}
+
+#if 0
+//=================================
+// Create all share memory
+//=================================
+int CreateShareMemory()
+{
+    uint8_t rebootCount = 0;
+
+    int MeterSMId = FAIL;
+
+    if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo), IPC_CREAT | 0777)) < 0) {
+        return FAIL;
+    } else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0))  == (void *) - 1) {
+        return FAIL;
+    }
+    memset(ShmSysConfigAndInfo, 0, sizeof(struct SysConfigAndInfo));
+
+    if ((MeterSMId = shmget(ShmStatusCodeKey, sizeof(struct StatusCodeData), IPC_CREAT | 0777)) < 0) {
+        return FAIL;
+    } else if ((ShmStatusCodeData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+        return FAIL;
+    }
+
+    memset(ShmStatusCodeData, 0, sizeof(struct StatusCodeData));
+
+    //creat ShmPsuData
+    if ((MeterSMId = shmget(ShmPsuKey, sizeof(struct PsuData), IPC_CREAT | 0777)) < 0) {
+        return FAIL;
+    } else if ((ShmPsuData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+        return FAIL;
+    }
+    memset(ShmPsuData, 0, sizeof(struct PsuData));
+
+    if (CHAdeMO_QUANTITY > 0) {
+        if ((MeterSMId = shmget(ShmCHAdeMOCommKey, sizeof(struct CHAdeMOData),  IPC_CREAT | 0777)) < 0) {
+            return FAIL;
+        } else if ((ShmCHAdeMOData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+            return FAIL;
+        }
+        memset(ShmCHAdeMOData, 0, sizeof(struct CHAdeMOData));
+    }
+
+    if (GB_QUANTITY > 0) {
+        if ((MeterSMId = shmget(ShmGBTCommKey, sizeof(struct GBTData),  IPC_CREAT | 0777)) < 0) {
+            return FAIL;
+        } else if ((ShmGBTData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+            return FAIL;
+        }
+        memset(ShmGBTData, 0, sizeof(struct GBTData));
+    }
+
+    //creat ShmCcsData
+    if (CCS_QUANTITY > 0) {
+        if ((MeterSMId = shmget(ShmCcsCommKey, sizeof(struct CcsData),  IPC_CREAT | 0777)) < 0) {
+            return FAIL;
+        } else if ((ShmCcsData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+            return FAIL;
+        }
+        memset(ShmCcsData, 0, sizeof(struct CcsData));
+    }
+
+    //creat ShmPrimaryMcuData
+    if ((MeterSMId = shmget(ShmPrimaryMcuKey, sizeof(struct PrimaryMcuData), IPC_CREAT | 0777)) < 0) {
+        return FAIL;
+    } else if ((ShmPrimaryMcuData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+        return FAIL;
+    }
+    memset(ShmPrimaryMcuData, 0, sizeof(struct PrimaryMcuData));
+
+    //creat ShmFanModuleData
+    if ((MeterSMId = shmget(ShmFanBdKey, sizeof(struct FanModuleData),  IPC_CREAT | 0777)) < 0) {
+        return FAIL;
+    } else if ((ShmFanModuleData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+        return FAIL;
+    }
+    memset(ShmFanModuleData, 0, sizeof(struct FanModuleData));
+
+    //creat ShmRelayModuleData
+    if ((MeterSMId = shmget(ShmRelayBdKey, sizeof(struct RelayModuleData),  IPC_CREAT | 0777)) < 0) {
+        return FAIL;
+    } else if ((ShmRelayModuleData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+        return FAIL;
+    }
+    memset(ShmRelayModuleData, 0, sizeof(struct RelayModuleData));
+
+    if ((MeterSMId = shmget(ShmLedBdKey, sizeof(struct LedModuleData), IPC_CREAT | 0777)) < 0) {
+        return FAIL;
+    } else if ((ShmLedModuleData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+        return FAIL;
+    }
+    memset(ShmLedModuleData, 0, sizeof(struct LedModuleData));
+
+    //creat ShmOCPP16Data
+    if ((MeterSMId = shmget(ShmOcppModuleKey, sizeof(struct OCPP16Data), IPC_CREAT | 0777)) < 0) {
+        return FAIL;
+    } else if ((ShmOCPP16Data = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+        return FAIL;
+    }
+    // memset(ShmOCPP16Data,0,sizeof(struct OCPP16Data));
+
+#if defined DD360 ||defined DD360Audi || defined DD360ComBox
+    //creat Audi customization info
+    if ((MeterSMId = shmget(ShmSelectGunInfoKey, sizeof(SelectGunInfo), IPC_CREAT | 0777)) < 0) {
+        return FAIL;
+    } else if ((gAudiCustInfo = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+        return FAIL;
+    }
+    memset(gAudiCustInfo, 0, sizeof(SelectGunInfo));
+#endif //defined DD360Audi
+
+    if ((MeterSMId = shmget(ShmCommonKey, sizeof(DcCommonInfo), IPC_CREAT | 0777)) < 0) {
+        return FAIL;
+    } else if ((ShmDcCommonData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+        return FAIL;
+    }
+
+    if (ShmDcCommonData->RebootCount == 1) {
+        rebootCount = ShmDcCommonData->RebootCount;
+    }
+    memset(ShmDcCommonData, 0, sizeof(DcCommonInfo));
+
+    ShmDcCommonData->RebootCount = rebootCount;
+
+    return PASS;
+}
+
+#endif //0
+
+//=================================
+// LCM Page
+//=================================
+void ChangeLcmByIndex(uint8_t page_index)
+{
+    if (pSysWarning->Level != 2 ||
+            page_index == _LCM_COMPLETE || page_index == _LCM_FIX) {
+        pSysInfo->PageIndex = page_index;
+    }
+}
+
+//======================================================
+// Peripheral initial
+//======================================================
+void InitGPIO()
+{
+    /*****************0~3, 4 bank, bank x 32+ num*********************/
+    /***************************************************************/
+    /*************** GPIO 0 ***************************************/
+    /***************************************************************/
+    /* GPMC_AD8         =>  GPIO0_22 *//*ID BD1_1*/
+    system("echo 22 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio22/direction");
+    /* GPMC_AD9         =>  GPIO0_23 *//*ID BD1_2*/
+    system("echo 23 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio23/direction");
+    /* GPMC_AD10        =>  GPIO0_26 *//*IO BD1_1*/
+    system("echo 26 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio26/direction");
+    system("echo 1 > /sys/class/gpio/gpio26/value");
+    /* GPMC_AD11        =>  GPIO0_27 *//*IO BD1_2*/
+    system("echo 27 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio27/direction");
+    /* RMII1_REF_CLK        =>  GPIO0_29 *//*USB 0 OCP detection*/
+    system("echo 29 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio29/direction");
+    /*XDMA_EVENT_INTR0  =>  GPIO0_19 *//*AM_RFID_RST*/
+    system("echo 19 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio19/direction");
+    system("echo 1 > /sys/class/gpio/gpio19/value");
+    /*XDMA_EVENT_INTR1  =>  GPIO0_20 *//*AM_RFID_ICC*/
+    system("echo 20 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio20/direction");
+    /***************************************************************/
+    /*************** GPIO 1 ***************************************/
+    /***************************************************************/
+    /* GPMC_AD12    =>  GPIO1_12 *//*ID BD2_1*/
+    system("echo 44 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio44/direction");
+    /* GPMC_AD13    =>  GPIO1_13 *//*ID BD2_2*/
+    system("echo 45 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio45/direction");
+    /* GPMC_AD14    =>  GPIO1_14 *//*IO BD2_1*/
+    system("echo 46 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio46/direction");
+    system("echo 0 > /sys/class/gpio/gpio46/value");
+    /* GPMC_AD15    =>  GPIO1_15 *//*IO BD2_2*/
+    system("echo 47 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio47/direction");
+    /***************************************************************/
+    /*************** GPIO 2 ***************************************/
+    /***************************************************************/
+    /*LCD_AC_BIAS_EN    =>  GPIO2_25*//*RS-485 for module DE control*/
+    system("echo 89 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio89/direction");
+    system("echo 1 > /sys/class/gpio/gpio89/value");
+    /*LCD_HSYNC     =>  GPIO2_23*//*RS-485 for module RE control*/
+    system("echo 87 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio87/direction");
+    system("echo 0 > /sys/class/gpio/gpio87/value");
+    /*LCD_PCLK      =>  GPIO2_24*//*CCS communication board 1 proximity*/
+    system("echo 88 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio88/direction");
+    /*LCD_VSYNC     =>  GPIO2_22*//*CCS communication board 2 proximity*/
+    system("echo 86 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio86/direction");
+    /***************************************************************/
+    /*************** GPIO 3 ***************************************/
+    /***************************************************************/
+    /*MCASP0_FSX        =>  GPIO3_15*//*Emergency Stop button detect*/
+    system("echo 111 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio111/direction");
+    /*MCASP0_ACLKR  =>  GPIO3_18*//*USB1 OCP detect*/
+    system("echo 114 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio114/direction");
+    /*MCASP0_AHCLKR =>  GPIO3_17*//*Emergency IO for AM3352 and STM32F407*/
+    system("echo 113 > /sys/class/gpio/export");
+    system("echo \"in\" > /sys/class/gpio/gpio113/direction");
+    /*MCASP0_ACLKX  =>  GPIO3_14*//*Ethernet PHY reset*/
+    system("echo 110 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio110/direction");
+    system("echo 0 > /sys/class/gpio/gpio110/value");
+    /* MCASP0_FSR       =>  GPIO3_19 *//*SMR Enable control_1 for Pskill_1*/
+    system("echo 115 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio115/direction");
+    system("echo 0 > /sys/class/gpio/gpio115/value");
+    /* MCASP0_AXR0  =>  GPIO3_16 *//*CSU board function OK indicator.*/
+    system("echo 112 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio112/direction");
+    system("echo 1 > /sys/class/gpio/gpio112/value");
+    /* MCASP0_AXR1  =>  GPIO3_20 *//*SMR Enable control_2 for Pskill_2*/
+    system("echo 116 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio116/direction");
+    system("echo 0 > /sys/class/gpio/gpio116/value");
+
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+    /* (C14) EMU0.gpio3[7] */  /*CP open/short feature enable/disable, pull low for default enable*/
+    system("echo 103 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio103/direction");
+    system("echo 0 > /sys/class/gpio/gpio103/value");
+    /* (B14) EMU1.gpio3[8] */  /*4G module reset, pull high to reset when entry kernel, after Application start, it should be pull low.*/
+    system("echo 104 > /sys/class/gpio/export");
+    system("echo \"out\" > /sys/class/gpio/gpio104/direction");
+    system("echo 0 > /sys/class/gpio/gpio104/value");
+#endif //!defined DD360 && !defined DD360Audi
+
+    log_info("Initial GPIO OK");
+}
+
+int LoadSysConfigAndInfo(struct SysConfigData *ptr)
+{
+    int fd, wrd;
+    uint8_t *buf;
+    unsigned int ChkSum, ChkSumOrg;
+
+    if ((buf = malloc(MtdBlockSize)) == NULL) {
+        log_error("malloc buffer NG,rebooting..\r\n");
+        if (pAlarmCode != NULL) {
+            pAlarmCode->AlarmEvents.bits.CsuInitFailed = 1;
+        }
+        sleep(5);
+        system("reboot -f");
+        sleep(5);
+        system("reboot -f");
+    }
+    memset(buf, 0, MtdBlockSize);
+
+    //================================================
+    // Load configuration from mtdblock10
+    //================================================
+    fd = open("/dev/mtdblock10", O_RDWR);
+    if (fd < 0) {
+        free(buf);
+        log_error("open mtdblock10 NG,rebooting..\r\n");
+        if (pAlarmCode != NULL) {
+            pAlarmCode->AlarmEvents.bits.CsuInitFailed = 1;
+        }
+        sleep(5);
+        system("reboot -f");
+        sleep(5);
+        system("reboot -f");
+    }
+
+    wrd = read(fd, buf, MtdBlockSize);
+    close(fd);
+    if (wrd < MtdBlockSize) {
+        free(buf);
+        log_error("read SysConfigData data NG,rebooting..\r\n");
+        if (pAlarmCode != NULL) {
+            pAlarmCode->AlarmEvents.bits.CsuInitFailed = 1;
+        }
+        sleep(5);
+        system("reboot -f");
+        sleep(5);
+        system("reboot -f");
+    }
+    ChkSum = 0;
+    for (wrd = 0; wrd < MtdBlockSize - 4; wrd++) {
+        ChkSum += buf[wrd];
+    }
+    memcpy(&ChkSumOrg, buf + (0x00600000 - 4), sizeof(ChkSumOrg));
+
+    //================================================
+    // Load configuration from mtdblock11
+    //================================================
+    if (ChkSum != ChkSumOrg) {
+        log_error("Primary SysConfigData checksum NG, read backup\r\n");
+        fd = open("/dev/mtdblock11", O_RDWR);
+        if (fd < 0) {
+            free(buf);
+            log_error("open mtdblock11 (backup) NG,rebooting..\r\n");
+            if (pAlarmCode != NULL) {
+                pAlarmCode->AlarmEvents.bits.CsuInitFailed = 1;
+            }
+            sleep(5);
+            system("reboot -f");
+            sleep(5);
+            system("reboot -f");
+        }
+
+        memset(buf, 0, MtdBlockSize);
+        wrd = read(fd, buf, MtdBlockSize);
+        close(fd);
+        if (wrd < MtdBlockSize) {
+            free(buf);
+            log_error("read backup SysConfigData data NG,rebooting..\r\n");
+            if (pAlarmCode != NULL) {
+                pAlarmCode->AlarmEvents.bits.CsuInitFailed = 1;
+            }
+            sleep(5);
+            system("reboot -f");
+            sleep(5);
+            system("reboot -f");
+        }
+        ChkSum = 0;
+        for (wrd = 0; wrd < MtdBlockSize - 4; wrd++) {
+            ChkSum += buf[wrd];
+        }
+        memcpy(&ChkSumOrg, buf + (0x00600000 - 4), sizeof(ChkSumOrg));
+
+        //================================================
+        // Load configuration from mtdblock12 (Factory default)
+        //================================================
+        if (ChkSum != ChkSumOrg) {
+            log_error("backup SysConfigData checksum NG, read Factory default\r\n");
+            fd = open("/dev/mtdblock12", O_RDWR);
+            if (fd < 0) {
+                free(buf);
+                log_error("open mtdblock12 (Factory default) NG,rebooting..\r\n");
+                if (pAlarmCode != NULL) {
+                    pAlarmCode->AlarmEvents.bits.CsuInitFailed = 1;
+                }
+                sleep(5);
+                system("reboot -f");
+                sleep(5);
+                system("reboot -f");
+            }
+            memset(buf, 0, MtdBlockSize);
+            wrd = read(fd, buf, MtdBlockSize);
+            close(fd);
+            if (wrd < MtdBlockSize) {
+                free(buf);
+                log_error("read factory default  SysConfigData data NG,rebooting..\r\n");
+                if (pAlarmCode != NULL) {
+                    pAlarmCode->AlarmEvents.bits.CsuInitFailed = 1;
+                }
+                sleep(5);
+                system("reboot -f");
+                sleep(5);
+                system("reboot -f");
+            }
+            ChkSum = 0;
+            for (wrd = 0; wrd < MtdBlockSize - 4; wrd++) {
+                ChkSum += buf[wrd];
+            }
+            memcpy(&ChkSumOrg, buf + (0x00600000 - 4), sizeof(ChkSumOrg));
+            if (ChkSum != ChkSumOrg) {
+                log_error("factory default  SysConfigData checksum NG, restore factory default\r\n");
+                free(buf);
+                system("cd /root;./FactoryConfig -m");
+                system("sync");
+                sleep(5);
+                system("reboot -f");
+                sleep(5);
+                system("reboot -f");
+
+                return FAIL;
+            }
+        }
+    }
+
+    //load OK
+    memcpy((struct SysConfigData *)ptr, buf, sizeof(struct SysConfigData));
+    free(buf);
+    //log_info("Load SysConfigData OK\n");
+    return PASS;
+}
+
+#if 0
+int isRouteFail()
+{
+    int result = YES;
+    FILE *fp;
+    char buf[512];
+
+    fp = popen("route -n", "r");
+    if (fp != NULL) {
+        while (fgets(buf, sizeof(buf), fp) != NULL) {
+            if (strstr(buf, "eth0") != NULL) {
+                result = NO;
+            }
+        }
+    }
+    pclose(fp);
+
+    return result;
+}
+
+//static void eth0Down(void)
+//{
+//    char cmdbuf[256] = {0};
+//
+//    sprintf(cmdbuf, "/sbin/ifconfig eth0 down");
+//}
+
+//static void eth0Up(void)
+//{
+//    char cmdbuf[256] = {0};
+//
+//    sprintf(cmdbuf, "/sbin/ifconfig eth0 %s up", pSysConfig->Eth0Interface.EthIpAddress);
+//}
+
+int isReachableInternet()
+{
+    int result = FAIL;
+    FILE *fp;
+    char cmd[256];
+    char buf[512];
+    char tmp[512];
+
+    strcpy(cmd, "ifconfig eth0");
+    fp = popen(cmd, "r");
+
+    if (fp != NULL) {
+        while (fgets(buf, sizeof(buf), fp) != NULL) {
+            if (strstr(buf, "inet addr:") > 0) {
+                sscanf(buf, "%*s%s", tmp);
+                substr(tmp, tmp, strspn(tmp, "addr:"), strlen(buf) - strspn(tmp, "addr:"));
+
+                if (strcmp(tmp, (char *)pSysConfig->Eth0Interface.EthIpAddress) != EQUAL) {
+                    strcpy((char *) pSysConfig->Eth0Interface.EthIpAddress, tmp);
+                }
+            }
+        }
+    }
+    pclose(fp);
+
+#if defined DD360 ||defined DD360Audi || defined DD360ComBox
+    if (pAlarmCode->AlarmEvents.bits.DisconnectedFromDo == NORMAL) {
+        result = FAIL;
+    } else {
+        result = PASS;
+    }
+#else
+    memset(buf, 0x00, sizeof(buf));
+    for (int idx = 0; idx < ARRAY_SIZE(valid_Internet); idx++) {
+        sprintf(cmd, "ping -c 1 -w 3 -I eth0 %s", valid_Internet[idx]);
+        fp = popen(cmd, "r");
+        if (fp != NULL) {
+            while (fgets(buf, sizeof(buf), fp) != NULL) {
+                if (strstr(buf, "transmitted") > 0) {
+                    //sscanf(buf, "%*s%*s%*s%*s%*s%*s%s", tmp);
+
+                    if (strstr(buf, "100%") != NULL) {
+                    } else {
+                        result = PASS;
+                    }
+                    //DEBUG_INFO("%s",buf);
+                    //DEBUG_INFO("%s\n",tmp);
+                }
+            }
+        }
+        pclose(fp);
+    }
+
+#endif //defined DD360 || defined DD360Audi
+
+    return result;
+}
+
+void InitEthernet()
+{
+    char tmpbuf[256];
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+    bool ethResult = false;
+    uint8_t cnt_pingDNS_Fail = 0;
+#endif //!defined DD360 && !defined DD360Audi
+
+    system("ifconfig eth0 down");// eth0 down
+    system("ifconfig eth1 down");// eth1 down
+    sleep(2);
+
+    // /sbin/ifconfig eth0 192.168.1.10 netmask 255.255.255.0 down
+    system("echo 1 > /sys/class/gpio/gpio110/value");//reset PHY
+    sleep(2);
+    //Init Eth0 for internet
+    memset(tmpbuf, 0, 256);
+    sprintf(tmpbuf, "/sbin/ifconfig eth0 %s netmask %s up",
+            pSysConfig->Eth0Interface.EthIpAddress,
+            pSysConfig->Eth0Interface.EthSubmaskAddress);
+    //sprintf(tmpbuf,"/sbin/ifconfig eth0 192.168.100.10 netmask 255.255.255.0 up");
+    system(tmpbuf);
+
+    memset(tmpbuf, 0, 256);
+    sprintf(tmpbuf, "route add default gw %s eth0 ",
+            pSysConfig->Eth0Interface.EthGatewayAddress);
+    //sprintf(tmpbuf,"route add default gw 192.168.100.1 eth0 ");
+    system(tmpbuf);
+    //system("ifconfig lo up");
+    //  /sbin/ifconfig eth0 192.168.1.10 netmask 255.255.255.0 up
+    //Init Eth1 for administrator tool
+    memset(tmpbuf, 0, 256);
+    sprintf(tmpbuf, "/sbin/ifconfig eth1 %s netmask %s up",
+            pSysConfig->Eth1Interface.EthIpAddress,
+            pSysConfig->Eth1Interface.EthSubmaskAddress);
+    system(tmpbuf);
+
+    //Run DHCP client if enabled
+    system("killall udhcpc");
+    system("rm -rf /etc/resolv.conf");
+    system("echo nameserver 8.8.8.8 > /etc/resolv.conf");       //Google DNS server
+    system("echo nameserver 180.76.76.76 > /etc/resolv.conf");  //Baidu DNS server
+    //system("/sbin/ifconfig eth0 down;/sbin/ifconfig eth0 up");
+
+    if (pSysConfig->Eth0Interface.EthDhcpClient == 0) {
+        sprintf(tmpbuf, "/sbin/udhcpc -i eth0 -x hostname:CSU3_%s -s /root/dhcp_script/eth0.script > /dev/null &",
+                pSysConfig->SystemId);
+        system(tmpbuf);
+    }
+
+    //Upgrade system id to /etc/hostname
+    sprintf(tmpbuf, "echo %s > /etc/hostname", pSysConfig->SystemId);
+    system(tmpbuf);
+
+    pid_t pid = fork();
+    if (pid == 0) {
+        log_info("InitEthernet = %d\r\n", pid);
+        for (;;) {
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+            if (isRouteFail()) {
+                //log_info("eth0 not in route, restart eht0. \n");
+                system("/sbin/ifconfig eth0 down;/sbin/ifconfig eth0 up");
+
+                if (pSysConfig->Eth0Interface.EthDhcpClient == 0) {
+                    InitialDHCP();
+                }
+            }
+
+            if (isReachableInternet() == PASS) {
+                pSysInfo->ethInternetConn = YES;
+                cnt_pingDNS_Fail = 0;
+            } else {
+                if (++cnt_pingDNS_Fail > 3) {
+                    pSysInfo->ethInternetConn = NO;
+                }
+            }
+
+            ethResult = pSysInfo->ethInternetConn;
+
+            if (ethResult == YES) {
+                system("/sbin/ifmetric eth0 0");
+
+                if ((pSysConfig->ModelName[10] == 'W') ||
+                        (pSysConfig->ModelName[10] == 'D')) {
+                    system("/sbin/ifmetric mlan0 1");
+                }
+
+                if ((pSysConfig->ModelName[10] == 'T') ||
+                        (pSysConfig->ModelName[10] == 'D')) {
+                    system("/sbin/ifmetric ppp0 2");
+                }
+            }
+
+            if (!ethResult &&
+                    pSysConfig->AthInterface.WifiMode != _SYS_WIFI_MODE_DISABLE &&
+                    (pSysConfig->ModelName[10] == 'W' ||
+                     pSysConfig->ModelName[10] == 'D')) {
+                //ethResult = pSysConfig->AthInterface.WifiNetworkConn;
+                ethResult = pInfoCode->InfoEvents.bits.InternetDisconnectViaWiFi == YES ? NO : YES;
+
+                if (ethResult) {
+                    if ((pSysConfig->ModelName[10] == 'W') ||
+                            (pSysConfig->ModelName[10] == 'D')) {
+                        system("/sbin/ifmetric eth0 1");
+                        system("/sbin/ifmetric mlan0 0");
+                    }
+
+
+                    if ((pSysConfig->ModelName[10] == 'T') ||
+                            (pSysConfig->ModelName[10] == 'D')) {
+                        system("/sbin/ifmetric ppp0 2");
+                    }
+                }
+            }
+
+            if (!ethResult &&
+                    pSysConfig->TelecomInterface.TelcomEnabled == YES &&
+                    (pSysConfig->ModelName[10] == 'T' ||
+                     pSysConfig->ModelName[10] == 'D')) {
+                //ethResult = pSysConfig->TelecomInterface.TelcomNetworkConn;
+                ethResult = pInfoCode->InfoEvents.bits.InternetDisconnectVia4Gi == YES ? NO : YES;
+
+                if (ethResult) {
+                    if ((pSysConfig->ModelName[10] == 'W') ||
+                            (pSysConfig->ModelName[10] == 'D')) {
+                        system("/sbin/ifmetric mlan0 2");
+                    }
+
+                    if ((pSysConfig->ModelName[10] == 'T') ||
+                            (pSysConfig->ModelName[10] == 'D')) {
+                        system("/sbin/ifmetric eth0 1");
+                        system("/sbin/ifmetric ppp0 0");
+                    }
+                }
+            }
+
+            pSysInfo->InternetConn = ethResult;
+#else
+            isReachableInternet();
+#endif //!defined DD360 && !defined DD360
+
+            sleep(5);
+        }
+    }
+
+    log_info("Initial Ethernet OK\r\n");
+}
+
+int InitialRfidPort()
+{
+    int uartO2 = open(rfidPortName, O_RDWR);
+    struct termios tios;
+
+    if (uartO2 != FAIL) {
+        ioctl (uartO2, TCGETS, &tios);
+        tios.c_cflag = B19200 | CS8 | CLOCAL | CREAD;
+        tios.c_lflag = 0;
+        tios.c_iflag = 0;
+        tios.c_oflag = 0;
+        tios.c_cc[VMIN] = 0;
+        tios.c_cc[VTIME] = (uint8_t) 1;
+        tios.c_lflag = 0;
+        tcflush(uartO2, TCIFLUSH);
+        ioctl(uartO2, TCSETS, &tios);
+    }
+
+    if (uartO2 < 0) {
+        pAlarmCode->AlarmEvents.bits.RfidModuleCommFail = 1;
+    }
+
+    return uartO2;
+}
+
+void GetMacAddress()
+{
+    for (uint8_t index = 0; index < 2; index++) {
+        int fd;
+        struct ifreq ifr;
+        char tarEth[5];
+        char Mac[18];
+
+        sprintf(tarEth, "eth%d", index);
+        fd = socket(AF_INET, SOCK_DGRAM, 0);
+
+        ifr.ifr_addr.sa_family = AF_INET;
+        strncpy(ifr.ifr_name, tarEth, IFNAMSIZ - 1);
+
+        ioctl(fd, SIOCGIFHWADDR, &ifr);
+        close(fd);
+
+        sprintf(Mac, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
+                ifr.ifr_hwaddr.sa_data[0], ifr.ifr_hwaddr.sa_data[1], ifr.ifr_hwaddr.sa_data[2],
+                ifr.ifr_hwaddr.sa_data[3], ifr.ifr_hwaddr.sa_data[4], ifr.ifr_hwaddr.sa_data[5]);
+
+        if (index == 0) {
+            strcpy((char *) pSysConfig->Eth0Interface.EthMacAddress, Mac);
+        } else {
+            strcpy((char *) pSysConfig->Eth1Interface.EthMacAddress, Mac);
+        }
+    }
+}
+
+void GetFirmwareVersion()
+{
+    // Get CSU root file system version
+    sprintf((char *)pSysInfo->CsuRootFsFwRev, fwVersion);
+
+    uint8_t count = 0, chademo = 0, ccs = 0, gb = 0;
+    for (uint8_t idx = 0; idx < 3; idx++) {
+        if (pSysConfig->ModelName[7 + idx] == 'J') {
+            chademo++;
+            count++;
+        } else if (pSysConfig->ModelName[7 + idx] == 'G') {
+            gb++;
+            count++;
+        } else if (pSysConfig->ModelName[7 + idx] == 'U' ||
+                   pSysConfig->ModelName[7 + idx] == 'V' ||
+                   pSysConfig->ModelName[7 + idx] == 'E') {
+            ccs++;
+            count++;
+        }
+    }
+
+    if (count == 1) {
+        if (chademo > 0) {
+            pSysInfo->CsuRootFsFwRev[7] = '1';
+        } else if (ccs > 0) {
+            pSysInfo->CsuRootFsFwRev[7] = '2';
+        } else if (gb > 0) {
+            pSysInfo->CsuRootFsFwRev[7] = '3';
+        }
+    } else {
+        if (chademo > 0 && ccs > 0) {
+            pSysInfo->CsuRootFsFwRev[7] = '4';
+        } else if (chademo > 0 && gb > 0) {
+            pSysInfo->CsuRootFsFwRev[7] = '5';
+        } else if (ccs > 0 && gb > 0) {
+            pSysInfo->CsuRootFsFwRev[7] = '6';
+        }
+    }
+
+    // Get network option from model name
+    switch (pSysConfig->ModelName[10]) {
+    case 'B':
+    case 'U':
+        //Blue tooth
+        pSysInfo->CsuRootFsFwRev[9] = '3';
+        break;
+    case 'W':
+        // WIFI
+        pSysInfo->CsuRootFsFwRev[9] = '1';
+        break;
+    case 'T':
+        // 3G/4G
+        pSysInfo->CsuRootFsFwRev[9] = '2';
+        break;
+    case 'D': //DS60-120 add
+        pSysInfo->CsuRootFsFwRev[9] = '5';
+        break;
+    default:
+        // LAN
+        pSysInfo->CsuRootFsFwRev[9] = '0';
+        break;
+    }
+    // Get rating power from model name
+    memcpy(&pSysInfo->CsuRootFsFwRev[10], &pSysConfig->ModelName[4], 0x03);
+
+    // Get IEC or UL
+    char _buf[3] = {0};
+    memcpy(_buf, &pSysConfig->ModelName[2], 2);
+
+    if (strcmp(_buf, "YE") == EQUAL || strcmp(_buf, "YC") == EQUAL) {
+        pSysInfo->ChargerType = _CHARGER_TYPE_IEC;
+        log_info("IEC model");
+    } else if (strcmp(_buf, "WU") == EQUAL) {
+        pSysInfo->ChargerType = _CHARGER_TYPE_UL;
+        log_info("UL model");
+    }
+}
+
+//DS60-120 add
+void InitialGunIndexToUnUse()
+{
+    for (uint8_t index = 0; index < CHAdeMO_QUANTITY; index++) {
+        pSysInfo->ChademoChargingData[index].Index = NO_DEFINE;
+    }
+
+    for (uint8_t index = 0; index < CCS_QUANTITY; index++) {
+        pSysInfo->CcsChargingData[index].Index = NO_DEFINE;
+    }
+
+    for (uint8_t index = 0; index < GB_QUANTITY; index++) {
+        pSysInfo->GbChargingData[index].Index = NO_DEFINE;
+    }
+
+    for (uint8_t index = 0; index < AC_QUANTITY; index++) {
+        pSysInfo->AcChargingData[index].Index = NO_DEFINE;
+    }
+}
+
+void InitialShareMemoryInfo()
+{
+    FILE *fp;
+    char cmd[512];
+    char buf[512];
+
+    sprintf((char *)pSysConfig->TelecomInterface.TelcomApn, "Internet");
+    sprintf((char *)pSysConfig->TelecomInterface.TelcomChapPapId, " ");
+    sprintf((char *)pSysConfig->TelecomInterface.TelcomChapPapPwd, " ");
+
+    pSysConfig->TotalConnectorCount = 0;
+    pSysConfig->AcConnectorCount = 0;
+
+    pSysInfo->FactoryConfiguration = 0;
+    pSysInfo->InputVoltageR = 0;
+    pSysInfo->InputVoltageS = 0;
+    pSysInfo->InputVoltageT = 0;
+    pSysInfo->SystemFanRotaSpeed = 0;
+    pSysInfo->PsuFanRotaSpeed = 0;
+    pSysInfo->AuxPower5V = 0;
+    pSysInfo->AuxPower12V = 0;
+    pSysInfo->AuxPower24V = 0;
+    pSysInfo->AuxPower48V = 0;
+
+    sprintf((char *)pSysInfo->CsuHwRev, "REV:5.0");
+    memcpy(pSysInfo->CsuBootLoadFwRev, pSysConfig->CsuBootLoadFwRev, ARRAY_SIZE(pSysConfig->CsuBootLoadFwRev));
+
+    sprintf(cmd, "/bin/uname -r");
+    fp = popen(cmd, "r");
+    if (fp == NULL) {
+        sprintf((char *)pSysInfo->CsuKernelFwRev, "Unknown version");
+    } else {
+        while (fgets(buf, sizeof(buf), fp) != NULL) {
+            strcpy((char *)pSysInfo->CsuKernelFwRev, buf);
+        }
+    }
+
+    // 雙槍 CCS + Chademo
+    GetFirmwareVersion();
+    //sprintf((char *) pSysInfo->CsuRootFsFwRev, fwVersion);
+    sprintf((char *) pSysInfo->CsuPrimFwRev, " ");
+
+    sprintf((char *) pSysInfo->LcmHwRev, " ");
+    sprintf((char *) pSysInfo->LcmFwRev, " ");
+    sprintf((char *) pSysInfo->PsuHwRev, " ");
+    sprintf((char *) pSysInfo->PsuPrimFwRev, " ");
+    sprintf((char *) pSysInfo->PsuSecFwRev, " ");
+    sprintf((char *) pSysInfo->AuxPwrHwRev, " ");
+    sprintf((char *) pSysInfo->AuxPwrFwRev, " ");
+    sprintf((char *) pSysInfo->FanModuleHwRev, " ");
+    sprintf((char *) pSysInfo->FanModuleFwRev, " ");
+    sprintf((char *) pSysInfo->RelayModuleHwRev, " ");
+    sprintf((char *) pSysInfo->RelayModuleFwRev, " ");
+    sprintf((char *) pSysInfo->TelcomModemFwRev, " ");
+    pSysInfo->SystemAmbientTemp = 0;
+    pSysInfo->SystemCriticalTemp = 0;
+    pSysInfo->PsuAmbientTemp = 0;
+    pSysInfo->CcsConnectorTemp = 0;
+    pSysInfo->InternetConn = 0;
+    pSysInfo->OcppConnStatus = 0;
+    pSysInfo->OrderCharging = NO_DEFINE;
+
+    strcpy((char *) pSysConfig->UserId, "");
+
+    pAlarmCode->AlarmEvents.bits.RelayboardStestFail = NO;
+    pAlarmCode->AlarmEvents.bits.FanboardStestFail = NO;
+    pAlarmCode->AlarmEvents.bits.PrimaryStestFail = NO;
+    pAlarmCode->AlarmEvents.bits.LedboardStestFail = NO; //DS60-120 Add
+    pAlarmCode->AlarmEvents.bits.ChademoboardStestFail = NO;
+    pAlarmCode->AlarmEvents.bits.CCSboardStestFail = NO;
+    pAlarmCode->AlarmEvents.bits.AcContactStestFail = NO;
+    pAlarmCode->AlarmEvents.bits.PsuModuleStestFail = NO;
+    pAlarmCode->AlarmEvents.bits.PsuDipSwitchStestFail = NO; //DS60-120 Add
+    pSysConfig->QRCodeMadeMode = NO; //DS60-120 add
+
+    memset(pSysInfo->FanModuleFwRev, 0, ARRAY_SIZE(pSysInfo->FanModuleFwRev));
+    memset(pSysInfo->RelayModuleFwRev, 0, ARRAY_SIZE(pSysInfo->RelayModuleFwRev));
+    ShmPrimaryMcuData->SelfTest_Comp = NO;
+    ShmRelayModuleData->SelfTest_Comp = NO;
+    ShmFanModuleData->SelfTest_Comp = NO;
+    ShmLedModuleData->SelfTest_Comp = NO;
+#if defined DD360Audi
+    pSysInfo->SystemPage = _LCM_SELECT_GUN;
+#else
+    pSysInfo->SystemPage = _LCM_NONE;
+#endif //defined DD360Audi
+    pSysInfo->MainChargingMode = _MAIN_CHARGING_MODE_MAX;
+    pSysInfo->ReAssignedFlag = _REASSIGNED_NONE;
+    pSysInfo->CurGunSelectedByAc = NO_DEFINE;
+    pSysInfo->BootingStatus = BOOTTING; //DS60-120 add
+
+    ShmFanModuleData->TestFanSpeed = 0;
+
+    pAlarmCode->AlarmEvents.bits.ModelNameNoneMatchStestFail = NO;
+    pAlarmCode->AlarmEvents.bits.PsuNoResource = NO;
+
+    //--- DS60-120 remove -----
+    /*char EvsePower[2];
+
+    EvsePower[2] = '\0';
+    unsigned short buf_pow = 0;
+    if (strlen((char *) pSysConfig->ModelName) >= 6) {
+        strncpy(EvsePower, (char *)(pSysConfig->ModelName + 4), 2);
+        if (strcmp(EvsePower, "15") == EQUAL) {
+            buf_pow = 150;
+        } else if (strcmp(EvsePower, "30") == EQUAL) {
+            buf_pow = 30;
+        } else if (strcmp(EvsePower, "60") == EQUAL) {
+            buf_pow = 60;
+        } else if (strcmp(EvsePower, "12") == EQUAL) {
+            buf_pow = 120;
+        } else if (strcmp(EvsePower, "18") == EQUAL) {
+            buf_pow = 180;
+        } else if (strcmp(EvsePower, "36") == EQUAL) {
+            buf_pow = 360;
+        }
+
+        pSysConfig->RatingCurrent = (buf_pow / 30) * PSU_MIN_CUR;
+
+        if (pSysConfig->MaxChargingPower == 0 ||
+                pSysConfig->MaxChargingPower > buf_pow) {
+            pSysConfig->MaxChargingPower = buf_pow;
+        }
+    }
+    */
+    //--------------------------------------------------------------------------
+
+    InitialGunIndexToUnUse();//DS60-120 add
+
+    //ShmDcCommonData->CcsVersion = _CCS_VERSION_CHECK_TAG_V015S0;
+    //ShmDcCommonData->psuKeepCommunication = NO;
+    //ShmDcCommonData->acContactSwitch = NO;
+    ShmDcCommonData->ConnectErrList[0].GunErrMessage = 0;
+    ShmDcCommonData->ConnectErrList[1].GunErrMessage = 0;
+    //ShmDcCommonData->LcmFwVersion = 0;
+
+    pSysConfig->SwitchDebugFlag = NO;
+    pSysConfig->AlwaysGfdFlag = NO;
+
+    log_info("3InitialShareMemoryInfo done...\r\n");
+}
+#endif //0
+
+int Initialization()
+{
+    // 初始化卡號驗證的 Flag
+    ClearAuthorizedFlag();
+
+    // 初始化插槍驗證的 Flag
+    ClearDetectPluginFlag();
+
+    // UART 2 for Rfid
+    //rfidFd = InitialRfidPort();
+
+    int pinOut[2] = { 116, 115 };
+    for (uint8_t count = 0; count < pSysConfig->TotalConnectorCount; count++) {
+        pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(count);
+
+        pDcChargingInfo->RemoteStartFlag = NO;
+
+        if (pDcChargingInfo->Type == _Type_Chademo) {
+            gpio_set_value(pinOut[count], 0x00);
+            ShmCHAdeMOData->evse[pDcChargingInfo->type_index].SelfTest_Comp = NO;
+        } else if (pDcChargingInfo->Type == _Type_GB) {
+            gpio_set_value(pinOut[count], 0x00);
+            ShmGBTData->evse[pDcChargingInfo->type_index].SelfTest_Comp = NO;
+        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+            //if (ShmCcsData->CommProtocol == _CCS_COMM_V2GMessage_DIN70121) { //DS60-120 remove
+            if (pSysConfig->TotalConnectorCount == 1) {
+                gpio_set_value(pinOut[1], 0x01);
+            } else {
+                gpio_set_value(pinOut[count], 0x01);
+            }
+            ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].SelfTest_Comp = NO;
+            //}
+        }
+
+        strcpy((char *)ShmOCPP16Data->StatusNotification[count].ErrorCode, "NoError");
+    }
+
+    for (uint8_t count = 0; count < pSysConfig->AcConnectorCount; count++) {
+        pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(count);
+
+        pAcChargingInfo->RemoteStartFlag = NO;
+
+        if (pAcChargingInfo->Type == _Type_AC) {
+            pAcChargingInfo->SelfTest_Comp = NO;
+            strcpy((char *)ShmOCPP16Data->StatusNotification[count + pSysConfig->TotalConnectorCount].ErrorCode, "NoError");
+        }
+    }
+
+    //log_info("Initialization OK \n");
+    return PASS;
+}
+
+bool InitialSystemDefaultConfig()
+{
+    bool result = true;
+
+    LoadSysConfigAndInfo(pSysConfig);
+    InitGPIO();
+    InitEthernet();
+    GetMacAddress();
+
+//  system("echo 1 > /sys/class/gpio/gpio110/value"); //reset PHY
+//  sleep(3);
+//  system("/sbin/ifconfig eth0 192.168.1.10 netmask 255.255.255.0 down");
+//  sleep(1);
+//  system("/sbin/ifconfig eth1 192.168.0.10 netmask 255.255.255.0 up");
+
+    return result;
+}
+
+//顯示自檢錯誤原因,觸發對應的flag
+bool DisplaySelfTestFailReason()
+{
+    bool result = false;
+    uint8_t index = 0;
+
+    // RB、FB、407、EV 小板中有些板子無回應
+    if (ShmRelayModuleData->SelfTest_Comp == NO) {
+        pAlarmCode->AlarmEvents.bits.RelayboardStestFail = true;
+    }
+
+    if (ShmFanModuleData->SelfTest_Comp == NO) {
+        pAlarmCode->AlarmEvents.bits.FanboardStestFail = true;
+    }
+
+    if (ShmPrimaryMcuData->SelfTest_Comp == NO) {
+        pAlarmCode->AlarmEvents.bits.PrimaryStestFail = true;
+    }
+
+    if (ShmLedModuleData->SelfTest_Comp == NO) {
+        pAlarmCode->AlarmEvents.bits.LedboardStestFail = true;
+    }
+
+    for (index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+        pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+        if (pDcChargingInfo->Type == _Type_Chademo) {
+            if (ShmCHAdeMOData->evse[pDcChargingInfo->type_index].SelfTest_Comp == NO) {
+                pAlarmCode->AlarmEvents.bits.ChademoboardStestFail = true;
+            }
+        } else if (pDcChargingInfo->Type == _Type_GB) {
+            if (ShmGBTData->evse[pDcChargingInfo->type_index].SelfTest_Comp == NO) {
+                pAlarmCode->AlarmEvents.bits.GbtboardStestFail = true;
+            }
+        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+            if (ShmCcsData->CommProtocol == _CCS_COMM_V2GMessage_DIN70121) {
+                if (ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].SelfTest_Comp == NO) {
+                    pAlarmCode->AlarmEvents.bits.CCSboardStestFail = true;
+                }
+            }
+        }
+    }
+
+    for (index = 0; index < pSysConfig->AcConnectorCount; index++) {
+        pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(index);
+
+        // 先借 GBT 顯示
+        if (pAcChargingInfo->SelfTest_Comp == NO) {
+            pAlarmCode->AlarmEvents.bits.AcConnectorStestFail = true;
+        }
+    }
+
+    if (pSysInfo->AcContactorStatus == NO) {
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+        // AC Contact 未搭上
+        pAlarmCode->AlarmEvents.bits.AcContactStestFail = true;
+        result = true;
+#endif //!defined DD360 && !defined DD360Audi
+    }
+    //else if (pAlarmCode->AlarmEvents.bits.PsuDipSwitchStestFail == YES) { //DS60-120 add
+    //    result = true;
+    //}
+    else if (ShmPsuData->SystemAvailablePower <= 0 &&
+             ShmPsuData->SystemAvailableCurrent <= 0) {
+        // PSU 通訊問題
+        pAlarmCode->AlarmEvents.bits.PsuModuleStestFail = true;
+        result = true;
+    }
+
+    return result;
+}
+
+#if 0
+void SelfTestRun()
+{
+    bool evInitFlag = false;
+
+    StartSystemTimeoutDet(Timeout_SelftestChk);
+    pSysInfo->SelfTestSeq = _STEST_VERSION;
+
+    while (pSysInfo->SelfTestSeq != _STEST_COMPLETE //||
+            //GetTimeoutValue(pSysInfo->SystemTimeoutTimer) / uSEC_VAL <= 20 //DS60-120 add
+          ) {
+        if (pSysInfo->SelfTestSeq == _STEST_COMPLETE) {
+            return;
+        }
+
+        ChkPrimaryStatus();
+        if (pSysWarning->Level == 2 //||
+                //pAlarmCode->AlarmEvents.bits.PsuDipSwitchStestFail == YES //DS60-120 add
+           ) {
+            pSysInfo->SelfTestSeq = _STEST_FAIL;
+            return;
+        }
+
+        if (pSysConfig->TotalConnectorCount > 0) {
+            if (ShmPsuData->Work_Step == _NO_WORKING ||
+                    pSysInfo->SelfTestSeq == _STEST_FAIL) {
+                pSysInfo->SelfTestSeq = _STEST_FAIL;
+                return;
+            }
+
+            switch (pSysInfo->SelfTestSeq) {
+            case _STEST_VERSION: {
+                if ((strlen((char *)pSysInfo->RelayModuleFwRev) != 0 ||
+                        pSysInfo->RelayModuleFwRev[0] != '\0')
+                        && (ShmRelayModuleData->SelfTest_Comp != YES)
+                   ) {
+                    log_info("Relay Board FW Rev = %s", pSysInfo->RelayModuleFwRev);
+                    ShmRelayModuleData->SelfTest_Comp = YES;
+                }
+#if !defined NO_FAN_BOARD && !defined DD360ComBox
+                if ((strlen((char *)pSysInfo->FanModuleFwRev) != 0 ||
+                        pSysInfo->FanModuleFwRev[0] != '\0')
+                        && (ShmFanModuleData->SelfTest_Comp != YES)
+                   ) {
+                    log_info("Fan Board FW Rev = %s", pSysInfo->FanModuleFwRev);
+                    ShmFanModuleData->SelfTest_Comp = YES;
+                }
+#else
+                ShmFanModuleData->SelfTest_Comp = YES;
+#endif //NO_FAN_BOARD
+
+                if ((strlen((char *)ShmPrimaryMcuData->version) != 0 ||
+                        ShmPrimaryMcuData->version[0] != '\0')
+                        && (ShmPrimaryMcuData->SelfTest_Comp != YES)
+                   ) {
+                    log_info("Primary FW Rev = %s", pSysInfo->CsuPrimFwRev);
+                    ShmPrimaryMcuData->SelfTest_Comp = YES;
+                }
+#if 0 //DS60-120 remove
+                if ((strlen((char *)pSysInfo->LedModuleFwRev) != 0 ||
+                        pSysInfo->LedModuleFwRev[0] != '\0')
+                        && (ShmLedModuleData->SelfTest_Comp != YES)
+                   ) {
+                    log_info("LED Board FW Rev = %s", pSysInfo->LedModuleFwRev);
+                    ShmLedModuleData->SelfTest_Comp = YES;
+                }
+#endif //0
+
+                // EV 小板
+                if (!evInitFlag) {
+                    evInitFlag = YES;
+                    for (uint8_t index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+                        pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+                        //log_info("index = %d, charging index = %d, type = %d\r\n",
+                        //         index,
+                        //         chargingInfo[index]->type_index,
+                        //         chargingInfo[index]->Type);
+                        if (pDcChargingInfo->Type == _Type_Chademo) {
+                            if ((strlen((char *)ShmCHAdeMOData->evse[pDcChargingInfo->type_index].version) != 0 ||
+                                    ShmCHAdeMOData->evse[pDcChargingInfo->type_index].version[0] != '\0')
+                                    //&& (ShmCHAdeMOData->evse[pDcChargingInfo->type_index].SelfTest_Comp != YES)
+                               ) {
+                                log_info("CHAdeMO[%d] FW Rev = %s", pDcChargingInfo->type_index, ShmCHAdeMOData->evse[pDcChargingInfo->type_index].version);
+                                ShmCHAdeMOData->evse[pDcChargingInfo->type_index].SelfTest_Comp = YES;
+                            } else {
+                                //log_info("chademo fw lose...... %s \n", ShmCHAdeMOData->evse[pDcChargingInfo->type_index].version);
+                                evInitFlag = NO;
+                            }
+                        } else if (pDcChargingInfo->Type == _Type_GB) {
+                            if ((strlen((char *)ShmGBTData->evse[pDcChargingInfo->type_index].version) != 0 ||
+                                    ShmGBTData->evse[pDcChargingInfo->type_index].version[0] != '\0')
+                                    //&& (ShmGBTData->evse[pDcChargingInfo->type_index].SelfTest_Comp != YES)
+                               ) {
+                                log_info("GBT[%d] FW Rev = %s", pDcChargingInfo->type_index, ShmGBTData->evse[pDcChargingInfo->type_index].version);
+                                ShmGBTData->evse[pDcChargingInfo->type_index].SelfTest_Comp = YES;
+                            } else {
+                                //log_info("GBT fw lose...... %s \n", ShmCHAdeMOData->evse[pDcChargingInfo->type_index].version);
+                                evInitFlag = NO;
+                            }
+                        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                            if (ShmCcsData->CommProtocol == _CCS_COMM_V2GMessage_DIN70121) {
+                                if ((strlen((char *)ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].version) != 0 ||
+                                        ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].version[0] != '\0')
+                                        /*&&(ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].SelfTest_Comp != YES)*/
+                                   ) {
+                                    log_info("CCS[%d] FW Rev = %s",
+                                             pDcChargingInfo->type_index,
+                                             ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].version);
+                                    ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].SelfTest_Comp = YES;
+                                } else {
+                                    //log_info("CCS[%d] ccs fw lose...... %s \n",
+                                    //         chargingInfo[index]->type_index,
+                                    //         ShmCcsData->V2GMessage_DIN70121[chargingInfo[index]->type_index].version);
+                                    evInitFlag = NO;
+                                }
+                            }
+                        }
+                    }
+
+                    for (uint8_t index = 0; index < pSysConfig->AcConnectorCount; index++) {
+                        pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(index);
+
+                        if (pAcChargingInfo->Type == _Type_AC) {
+                            if ((strlen((char *)pAcChargingInfo->version) != 0 || pAcChargingInfo->version[0] != '\0')
+                                    && (pAcChargingInfo->SelfTest_Comp != YES)
+                               ) {
+                                log_info("AC connector[%d] FW Rev = %s", index, pAcChargingInfo->version);
+                                pAcChargingInfo->SelfTest_Comp = YES;
+                            } else {
+                                evInitFlag = NO;
+                            }
+                        }
+                    }
+                }
+
+                if ( ShmFanModuleData->SelfTest_Comp &&
+                        ShmRelayModuleData->SelfTest_Comp &&
+                        ShmPrimaryMcuData->SelfTest_Comp &&
+                        //ShmLedModuleData->SelfTest_Comp &&
+                        evInitFlag
+                   ) {
+                    pSysInfo->SelfTestSeq = _STEST_AC_CONTACTOR;
+                }
+            }
+            break;
+            case _STEST_AC_CONTACTOR: {
+                //ShmPsuData->Work_Step = _TEST_COMPLETE;
+                // 因為 30KW 以下沒有 Relay feedback 功能,所以暫時先直接跳過
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                if (pSysInfo->AcContactorStatus == YES) {
+                    pSysInfo->SelfTestSeq = _STEST_PSU_DETECT;
+                    log_info("AC contactor self test OK");
+                }
+#else
+                pSysInfo->SelfTestSeq = _STEST_PSU_DETECT;
+                log_info("Waiting for DO communication");
+#endif //!defined DD360 && !defined DD360Audi
+            }
+            break;
+            case _STEST_PSU_DETECT: {
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                if (ShmPsuData->Work_Step >= GET_SYS_CAP) {
+                    pSysInfo->SelfTestSeq = _STEST_PSU_CAP;
+                }
+#else
+                pSysInfo->SelfTestSeq = _STEST_PSU_CAP;
+#endif //defined DD360 && !defined DD360Audi
+            }
+            break;
+            case _STEST_PSU_CAP: {
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                // 此測試是要確認當前總輸出能力
+                // 如果沒有 PSU 模組請 bypass
+                if (ShmPsuData->Work_Step == BOOTING_COMPLETE) {
+                    sleep(1);
+                    pSysInfo->SelfTestSeq = _STEST_COMPLETE;
+                    pSysInfo->BootingStatus = BOOT_COMPLETE;
+                }
+#else
+                //check the power limit from DO
+                pSysInfo->SelfTestSeq = _STEST_COMPLETE;
+                pSysInfo->BootingStatus = BOOT_COMPLETE;
+                log_info("Successful Self Test");
+#endif //defined DD360 && !defined DD360Audi
+            }
+            break;
+            }
+        } else {
+            break;
+        }
+
+        usleep(100000);
+    }
+}
+#endif //0
+
+int SpawnTask()
+{
+    sleep(2);
+    system("/root/Module_EventLogging &");
+    system("/root/Module_PrimaryComm &");
+    system("/root/Module_EvComm &");
+    system("/root/Module_LcmControl &");
+    system("/root/Module_InternalComm &");
+    system("/root/Module_ProduceUtils &");
+
+#if defined DD360 ||defined DD360Audi || defined DD360ComBox
+    system("/root/Module_DoComm &");
+#else
+    system("/root/Module_PsuComm &");
+
+    if (strcmp((char *)pSysConfig->OcppServerURL, "") != EQUAL &&
+            strcmp((char *)pSysConfig->ChargeBoxId, "") != EQUAL) {
+        system("/root/OcppBackend &");
+    }
+
+    if (pSysConfig->ModelName[10] == 'T') {
+        system("/root/Module_4g &");
+    }
+
+    if (pSysConfig->ModelName[10] == 'W') {
+        system("/root/Module_Wifi &");
+    }
+
+    if (pSysConfig->ModelName[10] == 'D') {
+        system("/root/Module_4g &");
+        system("/root/Module_Wifi &");
+    }
+#endif //defined DD360 || defined DD360Audi
+
+    return PASS;
+}
+
+int StoreUsrConfigData(struct SysConfigData *UsrData)
+{
+    int result = PASS;
+    int fd, wrd;
+    unsigned int i, Chk;
+    uint8_t *ptr, *BufTmp;
+
+    Chk = 0;
+    ptr = (uint8_t *)UsrData;
+    if ((BufTmp = malloc(MtdBlockSize)) != NULL) {
+        memset(BufTmp, 0, MtdBlockSize);
+        memcpy(BufTmp, ptr, sizeof(struct SysConfigData));
+        for (i = 0; i < MtdBlockSize - 4; i++) {
+            Chk += *(ptr + i);
+        }
+
+        memcpy(BufTmp + MtdBlockSize - 4, &Chk, 4);
+        fd = open("/dev/mtdblock10", O_RDWR);
+        if (fd > 0) {
+            wrd = write(fd, BufTmp, MtdBlockSize);
+            close(fd);
+            if (wrd >= MtdBlockSize) {
+                fd = open("/dev/mtdblock11", O_RDWR);
+                if (fd > 0) {
+                    wrd = write(fd, BufTmp, MtdBlockSize);
+                    close(fd);
+                    if (wrd < MtdBlockSize) {
+                        log_error("write /dev/mtdblock11(backup) NG\r\n");
+                        result = FAIL;
+                    }
+                } else {
+                    log_error("open /dev/mtdblock11(backup) NG\r\n");
+                    result = FAIL;
+                }
+            } else {
+                log_error("write /dev/mtdblock10 NG\r\n");
+                result = FAIL;
+            }
+
+        } else {
+            log_error("open /dev/mtdblock10 NG\r\n");
+            result = FAIL;
+        }
+    } else {
+        log_error("alloc BlockSize NG\r\n");
+        result = FAIL;
+    }
+
+    if (BufTmp != NULL) {
+        free(BufTmp);
+    }
+
+    return result;
+}
+
+//===============================================
+// Common Detect Chk - Stop Charging ?
+//===============================================
+int isEvBoardStopChargeFlag(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    //printf("StopChargeFlag = %d\r\n", chargingInfo[gunIndex]->StopChargeFlag);
+    return pDcChargingInfo->StopChargeFlag;
+}
+
+bool isEvBoardNormalStopChargeFlag(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    return pDcChargingInfo->NormalStopChargeFlag;
+}
+
+//===============================================
+// 掃描插槍狀況
+//===============================================
+void ClearDetectPluginFlag()
+{
+    pSysInfo->WaitForPlugit = NO;
+
+    //DS60-120 add
+    for (uint8_t gun_index = 0; gun_index < pSysConfig->TotalConnectorCount; gun_index++) {
+        pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun_index);
+
+        if (pDcChargingInfo->RemoteStartFlag == YES) {
+            pDcChargingInfo->RemoteStartFlag = NO;
+        }
+    }
+
+    if (pSysInfo->OrderCharging != NO_DEFINE) {
+        pSysInfo->OrderCharging = NO_DEFINE;
+    }
+}
+
+void DetectPluginStart()
+{
+    pSysInfo->WaitForPlugit = YES;
+}
+
+bool isDetectPlugin()
+{
+    if (pSysInfo->WaitForPlugit == YES) {
+        return YES;
+    }
+
+    return NO;
+}
+
+//===============================================
+// Common Detect Chk - Chademo
+//===============================================
+bool isEvGunLocked_chademo(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    return (DetectBitValue(pDcChargingInfo->GunLocked , 0) == 0) ? NO : YES;
+}
+
+bool isEvContactorWelding_chademo(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    return DetectBitValue(ShmCHAdeMOData->ev[pDcChargingInfo->type_index].EvDetection, 3);
+}
+
+bool isEvStopReq_chademo(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    return DetectBitValue(ShmCHAdeMOData->ev[pDcChargingInfo->type_index].EvDetection, 4);
+}
+
+bool isEvStopCharging_chademo(uint8_t gunIndex)
+{
+    if (isEvGunLocked_chademo(gunIndex) == NO) {
+        // 無鎖槍 = 停止
+        log_info("gun locked none (%d) \n", gunIndex);
+        return YES;
+    }
+
+    return NO;
+}
+
+uint8_t isPrechargeStatus_chademo(uint8_t gunIndex)
+{
+    uint8_t result = 0x00;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    result = ShmCHAdeMOData->ev[pDcChargingInfo->type_index].PresentMsgFlowStatus;
+
+    return result;
+}
+//===============================================
+// Common Detect Chk - GB
+//===============================================
+bool isEvGunLocked_gb(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    return (DetectBitValue(pDcChargingInfo->GunLocked , 0) == 0) ? NO : YES;
+}
+
+bool isEvStopCharging_gb(uint8_t gunIndex)
+{
+    if (isEvGunLocked_gb(gunIndex) == NO) {
+        // 無鎖槍 = 停止
+        log_info("gun locked none. \n");
+        return YES;
+    }
+
+    return NO;
+}
+
+uint8_t isPrechargeStatus_gb(uint8_t gunIndex)
+{
+    uint8_t result = 0x00;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    result = ShmGBTData->ev[pDcChargingInfo->type_index].PresentMsgFlowStatus;
+
+    return result;
+}
+
+//===============================================
+// Common Detect Chk - CCS
+//===============================================
+bool isEvGunLocked_ccs(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    return (DetectBitValue(pDcChargingInfo->GunLocked , 0) == 0) ? NO : YES;
+}
+
+uint8_t isPrechargeStatus_ccs(uint8_t gunIndex)
+{
+    uint8_t result = 0x00;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (ShmCcsData->CommProtocol == _CCS_COMM_V2GMessage_DIN70121) {
+        result = ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].PresentMsgFlowStatus;
+    }
+
+    return result;
+}
+
+bool isEvStopCharging_ccs(uint8_t gunIndex)
+{
+    if (isEvGunLocked_ccs(gunIndex) == NO) {
+        // 無鎖槍 = 停止
+        log_info("gun locked none. \n");
+        return YES;
+    }
+
+    return NO;
+}
+
+//===============================================
+// Callback
+//===============================================
+void DisplayChargingInfo()
+{
+    log_info("*********** DisplayChargingInfo *********** \n");
+    for (uint8_t i = 0; i < pSysConfig->TotalConnectorCount; i++) {
+        pAcChargingInfo =  (struct ChargingInfoData *)GetAcChargingInfoData(i);
+
+        if (pAcChargingInfo->SystemStatus != S_IDLE &&
+                pAcChargingInfo->SystemStatus != S_RESERVATION) {
+            ChangeGunSelectByIndex(i);
+            return;
+        }
+    }
+
+    pAcChargingInfo =  (struct ChargingInfoData *)GetAcChargingInfoData(0);
+
+    if (pSysConfig->AcConnectorCount > 0 &&
+            pSysInfo->CurGunSelectedByAc == NO_DEFINE &&
+            pAcChargingInfo->SystemStatus >= S_PREPARNING &&
+            pAcChargingInfo->SystemStatus <= S_COMPLETE) {
+        pSysInfo->CurGunSelectedByAc = DEFAULT_AC_INDEX;
+    }
+
+    usleep(50000);
+#if defined DD360Audi
+    pSysInfo->SystemPage = _LCM_SELECT_GUN;
+#else
+    pSysInfo->SystemPage = _LCM_NONE;
+#endif //defined DD360Audi
+}
+
+void _AutoReturnTimeout()
+{
+    log_info("*********** _AutoReturnTimeout %d*********** \n", pSysInfo->PageIndex);
+    if (pSysInfo->PageIndex == _LCM_WAIT_FOR_PLUG) {
+        ClearDetectPluginFlag();
+    } else if (pSysInfo->PageIndex == _LCM_AUTHORIZ_COMP) {
+        DetectPluginStart();
+    }
+    usleep(50000);
+#if defined DD360Audi
+    pSysInfo->SystemPage = _LCM_SELECT_GUN;
+#else
+    pSysInfo->SystemPage = _LCM_NONE;
+#endif //defined DD360Audi
+}
+
+void _SelfTestTimeout()
+{
+    if (pSysInfo->BootingStatus != BOOT_COMPLETE) {
+        for (uint8_t gun_index = 0; gun_index < pSysConfig->TotalConnectorCount; gun_index++) {
+            setChargerMode(gun_index, MODE_ALARM);
+        }
+    }
+    ShmPsuData->Work_Step = _NO_WORKING;
+    pSysInfo->SelfTestSeq = _STEST_FAIL;
+    log_info("Self test timeout. \n");
+}
+
+void _AuthorizedTimeout()
+{
+    if (IsAuthorizingMode()) {
+        log_info("*********** _AuthorizedTimeout *********** \n");
+        //isCardScan = false;
+        SetIsCardScan(false);
+
+        //gAudiCustInfo->PricesInfo[pSysInfo->CurGunSelected].Balance = 0.0; //Jerry add
+        pSysInfo->SystemPage = _LCM_AUTHORIZ_FAIL;
+        //ChangeLcmByIndex(_LCM_AUTHORIZ_FAIL);
+        strcpy((char *)pSysConfig->UserId, "");
+        ClearAuthorizedFlag();
+    }
+}
+
+void _DetectPlugInTimeout()
+{
+    log_info("*********** _DetectPlugInTimeout *********** \n");
+    strcpy((char *)pSysConfig->UserId, "");
+    ClearDetectPluginFlag();
+    //usleep(50000);
+    sleep(1); //Jerry add
+#if defined DD360Audi
+    pSysInfo->SystemPage = _LCM_SELECT_GUN;
+#else
+    pSysInfo->SystemPage = _LCM_NONE;
+#endif //defined DD360Audi
+}
+
+void _DetectEvChargingEnableTimeout(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (pDcChargingInfo->Type == _Type_Chademo) {
+        if (!isEvGunLocked_chademo(gunIndex)) {
+            log_info("*********** _DetectEvChargingEnableTimeout (chademo) ***********\n");
+        }
+    } else if (pDcChargingInfo->Type == _Type_GB) {
+        if (!isEvGunLocked_ccs(gunIndex)) {
+            log_info("*********** _DetectEvChargingEnableTimeout (gb) ***********\n");
+        }
+    } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+        if (!isEvGunLocked_ccs(gunIndex)) {
+            log_info("*********** _DetectEvChargingEnableTimeout (ccs) ***********\n");
+        }
+    }
+    ChargingTerminalProcess(gunIndex);
+    _AutoReturnTimeout();
+}
+
+void _DetectEvseChargingEnableTimeout(uint8_t gunIndex)
+{
+    log_info("*********** _DetectEvseChargingEnableTimeout (GFD timeout) ***********\n");
+    //if (chargingInfo[gunIndex]->GroundFaultStatus != GFD_PASS)
+    {
+        setChargerMode(gunIndex, MODE_IDLE);
+        _AutoReturnTimeout();
+    }
+}
+
+void _PrepareTimeout(uint8_t gunIndex)
+{
+    log_info("*********** _PrepareTimeout ***********\n");
+    setChargerMode(gunIndex, MODE_IDLE);
+    pAlarmCode->AlarmEvents.bits.PsuNoResource = YES;
+    _AutoReturnTimeout();
+}
+
+void _CcsPrechargeTimeout(uint8_t gunIndex)
+{
+    log_info("*********** _CcsPrechargeTimeout ***********\n");
+    setChargerMode(gunIndex, MODE_IDLE);
+}
+
+//===============================================
+// 取得卡號與卡號驗證
+//===============================================
+#if 0
+bool canStartCharging()
+{
+    char buf2[16] = "";
+    memset(buf2, 0, ARRAY_SIZE(buf2));
+
+    for (uint8_t index = 0; index < strlen((char *)ShmOCPP16Data->Authorize.ResponseIdTagInfo.Status); index++) {
+        sprintf(buf2 + (index - 1) * 2, "%02X", ShmOCPP16Data->Authorize.ResponseIdTagInfo.Status[index]);
+    }
+    sprintf(buf2, "%s", ShmOCPP16Data->Authorize.ResponseIdTagInfo.Status);
+
+    // 因為無法得知實際的長度,所以只能用搜尋的方式
+    if (strcmp(buf2, "Accepted") == EQUAL) {
+        return true;
+    } else {
+
+    }
+
+    return false;
+}
+#endif //0
+
+void AuthorizingStart()
+{
+    ShmOCPP16Data->SpMsg.bits.AuthorizeReq = YES;
+    pSysInfo->AuthorizeFlag = YES;
+}
+
+void ClearAuthorizedFlag()
+{
+    ShmOCPP16Data->SpMsg.bits.AuthorizeConf = NO;
+    pSysInfo->AuthorizeFlag = NO;
+}
+
+bool isAuthorizedComplete()
+{
+    if (pSysInfo->AuthorizeFlag == YES) {
+        return false;
+    }
+    return true;
+}
+
+bool IsAuthorizingMode()
+{
+    if (pSysInfo->AuthorizeFlag == NO) {
+        return false;
+    }
+
+    return true;
+}
+
+//===============================================
+// 紀錄 Alarm Code
+//===============================================
+void ResetChargerAlarmCode(uint8_t gunIndex, char *code)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (strcmp(code, "012229") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaConnectOTP = NO; }
+    else if (strcmp(code, "012230") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSConnectOTP = NO; }
+    else if (strcmp(code, "012231") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTConnectOTP = NO; }
+    else if (strcmp(code, "011011") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaRelayWeldingFault = NO; }
+    else if (strcmp(code, "011013") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSRelayWeldingFault = NO; }
+    else if (strcmp(code, "011015") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTRelayWeldingFault = NO; }
+    else if (strcmp(code, "011012") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaRelayDrivingFault = NO; }
+    else if (strcmp(code, "011014") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSRelayDrivingFault = NO; }
+    else if (strcmp(code, "011016") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTRelayDrivingFault = NO; }
+    else if (strcmp(code, "011018") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaConnectTempSensorFail = NO; }
+    else if (strcmp(code, "011019") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSConnectTempSensorFail = NO; }
+    else if (strcmp(code, "011020") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTConnectTempSensorFail = NO; }
+
+    if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "", 6) != EQUAL) {
+        if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012229", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012230", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012231", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "011011", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "011013", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "011015", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "011012", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "011014", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "011016", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "011018", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "011019", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "011020", 6) == EQUAL) {
+            strncpy((char *)pDcChargingInfo->ConnectorAlarmCode, "", 6);
+        }
+    }
+}
+
+void RecordAlarmCode(uint8_t gunIndex, char *code)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "", 6) == EQUAL) {
+        memcpy(pDcChargingInfo->ConnectorAlarmCode, code, 6);
+    }
+
+    //if (strcmp(code, "012234") == EQUAL) { pAlarmCode->AlarmEvents.bits.ChademoGfdTrip = YES; }
+    //if (strcmp(code, "012235") == EQUAL) { pAlarmCode->AlarmEvents.bits.CcsGfdTrip = YES; }
+    //if (strcmp(code, "012236") == EQUAL) { pAlarmCode->AlarmEvents.bits.GbGfdTrip = YES; }
+    //if (strcmp(code, "012288") == EQUAL) { pAlarmCode->AlarmEvents.bits.CcsOutputUVPFail = YES; }
+    //if (strcmp(code, "012289") == EQUAL) { pAlarmCode->AlarmEvents.bits.ChademoOutputUVPFail = YES; }
+    //if (strcmp(code, "012290") == EQUAL) { pAlarmCode->AlarmEvents.bits.GbtOutputUVPFail = YES; }
+
+    if (strcmp(code, "012234") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaGfdTrip = YES; }
+    else if (strcmp(code, "012235") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSGfdTrip = YES; }
+    else if (strcmp(code, "012236") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTGfdTrip = YES; }
+    else if (strcmp(code, "012288") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSUvpFail = YES; }
+    else if (strcmp(code, "012289") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaUvpFail = YES; }
+    else if (strcmp(code, "012290") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTUvpFail = YES; }
+
+    else if (strcmp(code, "012229") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaConnectOTP = YES; }
+    else if (strcmp(code, "012230") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSConnectOTP = YES; }
+    else if (strcmp(code, "012231") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTConnectOTP = YES; }
+    else if (strcmp(code, "012296") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaGfdWarning = YES; }
+    else if (strcmp(code, "012297") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSGfdWarning = YES; }
+    else if (strcmp(code, "012298") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTGfdWarning = YES; }
+    else if (strcmp(code, "011011") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaRelayWeldingFault = YES; }
+    else if (strcmp(code, "011013") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSRelayWeldingFault = YES; }
+    else if (strcmp(code, "011015") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTRelayWeldingFault = YES; }
+    else if (strcmp(code, "011012") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaRelayDrivingFault = YES; }
+    else if (strcmp(code, "011014") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSRelayDrivingFault = YES; }
+    else if (strcmp(code, "011016") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTRelayDrivingFault = YES; }
+    else if (strcmp(code, "011018") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaConnectTempSensorFail = YES; }
+    else if (strcmp(code, "011019") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSConnectTempSensorFail = YES; }
+    else if (strcmp(code, "011020") == EQUAL) { ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTConnectTempSensorFail = YES; }
+}
+
+void RecordWarningCode(uint8_t gunIndex, char *code)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    memcpy(pDcChargingInfo->ConnectorWarningCode, code, 6);
+
+    if (strcmp(code, "012296") == EQUAL) { pAlarmCode->AlarmEvents.bits.ChademoGroundWarning = YES; }
+    if (strcmp(code, "012297") == EQUAL) { pAlarmCode->AlarmEvents.bits.CcsGroundfaultWarning = YES; }
+    if (strcmp(code, "012298") == EQUAL) { pAlarmCode->AlarmEvents.bits.GbGroundfaultWarning = YES; }
+}
+
+void ReleaseAlarmCode(uint8_t gunIndex)
+{
+#if 0
+    bool isCleanCheck = false;
+    char code[7];
+
+    if (chargingInfo[gunIndex]->Type == _Type_Chademo) {
+        if (strncmp((char *)chargingInfo[gunIndex]->ConnectorAlarmCode, "012234", 6) == EQUAL &&
+                pAlarmCode->AlarmEvents.bits.ChademoGfdTrip == YES) {
+            memcpy(code, "012234", 6);
+            memcpy(chargingInfo[gunIndex]->ConnectorAlarmCode, "", 6);
+            isCleanCheck = true;
+        } else if (strncmp((char *)chargingInfo[gunIndex]->ConnectorAlarmCode, "012289", 6) == EQUAL &&
+                   pAlarmCode->AlarmEvents.bits.ChademoOutputUVPFail == YES) {
+            memcpy(code, "012289", 6);
+            memcpy(chargingInfo[gunIndex]->ConnectorAlarmCode, "", 6);
+            isCleanCheck = true;
+        } else if (pAlarmCode->AlarmEvents.bits.ChademoGroundWarning == YES) {
+            ReleaseWarningCodeByString(gunIndex, "012296");
+        } else if (pAlarmCode->AlarmEvents.bits.SystemChademoOutputOVP == YES) {
+            memcpy(code, "012217", 6);
+            memcpy(chargingInfo[gunIndex]->ConnectorAlarmCode, "", 6);
+            isCleanCheck = true;
+        }
+    } else if (chargingInfo[gunIndex]->Type == _Type_GB) {
+        if (strncmp((char *)chargingInfo[gunIndex]->ConnectorAlarmCode, "012236", 6) == EQUAL &&
+                pAlarmCode->AlarmEvents.bits.GbGfdTrip == YES) {
+            memcpy(code, "012236", 6);
+            memcpy(chargingInfo[gunIndex]->ConnectorAlarmCode, "", 6);
+            isCleanCheck = true;
+        } else if (strncmp((char *)chargingInfo[gunIndex]->ConnectorAlarmCode, "012290", 6) == EQUAL &&
+                   pAlarmCode->AlarmEvents.bits.GbtOutputUVPFail == YES) {
+            memcpy(code, "012290", 6);
+            memcpy(chargingInfo[gunIndex]->ConnectorAlarmCode, "", 6);
+            isCleanCheck = true;
+        } else if (pAlarmCode->AlarmEvents.bits.GbGroundfaultWarning == YES) {
+            ReleaseWarningCodeByString(gunIndex, "012298");
+        } else if (pAlarmCode->AlarmEvents.bits.SystemGbOutputOVP == YES) {
+            memcpy(code, "012221", 6);
+            memcpy(chargingInfo[gunIndex]->ConnectorAlarmCode, "", 6);
+            isCleanCheck = true;
+        }
+    } else if (chargingInfo[gunIndex]->Type == _Type_CCS_2) {
+        if (strncmp((char *)chargingInfo[gunIndex]->ConnectorAlarmCode, "012235", 6) == EQUAL &&
+                pAlarmCode->AlarmEvents.bits.CcsGfdTrip == YES) {
+            memcpy(code, "012235", 6);
+            memcpy(chargingInfo[gunIndex]->ConnectorAlarmCode, "", 6);
+            isCleanCheck = true;
+        } else if (strncmp((char *)chargingInfo[gunIndex]->ConnectorAlarmCode, "012288", 6) == EQUAL &&
+                   pAlarmCode->AlarmEvents.bits.CcsOutputUVPFail == YES) {
+            memcpy(code, "012288", 6);
+            memcpy(chargingInfo[gunIndex]->ConnectorAlarmCode, "", 6);
+            isCleanCheck = true;
+        } else if (pAlarmCode->AlarmEvents.bits.CcsGroundfaultWarning == YES) {
+            ReleaseWarningCodeByString(gunIndex, "012297");
+        } else if (pAlarmCode->AlarmEvents.bits.SystemCcsOutputOVP == YES) {
+            memcpy(code, "012219", 6);
+            memcpy(chargingInfo[gunIndex]->ConnectorAlarmCode, "", 6);
+            isCleanCheck = true;
+        }
+    }
+
+    if (isCleanCheck) {
+        for (uint8_t index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+            if (index != gunIndex || pSysConfig->TotalConnectorCount == 1) {
+                if (strncmp((char *)chargingInfo[index]->ConnectorAlarmCode, code, 6) != EQUAL) {
+                    if (strncmp(code, "012234", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.ChademoGfdTrip = NO; }
+                    if (strncmp(code, "012289", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.ChademoOutputUVPFail = NO; }
+                    if (strncmp(code, "012217", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.SystemChademoOutputOVP = NO; }
+
+                    if (strncmp(code, "012236", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.GbGfdTrip = NO; }
+                    if (strncmp(code, "012290", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.GbtOutputUVPFail = NO; }
+                    if (strncmp(code, "012221", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.SystemGbOutputOVP = NO; }
+
+                    if (strncmp(code, "012235", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.CcsGfdTrip = NO; }
+                    if (strncmp(code, "012288", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.CcsOutputUVPFail = NO; }
+                    if (strncmp(code, "012219", 6) == EQUAL) {pAlarmCode->AlarmEvents.bits.SystemCcsOutputOVP = NO;}
+                }
+            }
+        }
+    }
+#endif //0
+
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    // 回 idle 後主要清除  GFD Trip、UVP、OVP、GFD Warning
+    if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "", 6) != EQUAL) {
+        if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012251", 6) == EQUAL ||
+                strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012252", 6) == EQUAL) {
+            memcpy(pDcChargingInfo->ConnectorAlarmCode, "", 6);
+        }
+    }
+
+    if (pDcChargingInfo->Type == _Type_Chademo) {
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaGfdTrip = NO;
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaUvpFail = NO;
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaConnectOVP = NO;
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaGfdWarning = NO;
+
+        if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "", 6) != EQUAL) {
+            if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012234", 6) == EQUAL ||
+                    strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012289", 6) == EQUAL ||
+                    strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012217", 6) == EQUAL ||
+                    strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012296", 6) == EQUAL) {
+                memcpy(pDcChargingInfo->ConnectorAlarmCode, "", 6);
+            }
+        }
+    } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSGfdTrip = NO;
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSUvpFail = NO;
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSConnectOVP = NO;
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSGfdWarning = NO;
+
+        if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "", 6) != EQUAL) {
+            if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012235", 6) == EQUAL ||
+                    strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012288", 6) == EQUAL ||
+                    strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012219", 6) == EQUAL ||
+                    strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012297", 6) == EQUAL) {
+                memcpy(pDcChargingInfo->ConnectorAlarmCode, "", 6);
+            }
+        }
+    } else if (pDcChargingInfo->Type == _Type_GB) {
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTGfdTrip = NO;
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTUvpFail = NO;
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTConnectOVP = NO;
+        ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTGfdWarning = NO;
+
+        if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "", 6) != EQUAL) {
+            if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012236", 6) == EQUAL ||
+                    strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012290", 6) == EQUAL ||
+                    strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012221", 6) == EQUAL ||
+                    strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012298", 6) == EQUAL) {
+                memcpy(pDcChargingInfo->ConnectorAlarmCode, "", 6);
+            }
+        }
+    }
+
+    if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012251", 6) == EQUAL ||
+            strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012252", 6) == EQUAL ||
+            strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012238", 6) == EQUAL ||
+            strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "012304", 6) == EQUAL
+       ) {
+        memset(pDcChargingInfo->ConnectorAlarmCode, 0, sizeof(pDcChargingInfo->ConnectorAlarmCode));
+    }
+}
+
+void ReleaseWarningCodeByString(uint8_t gunIndex, char *code)
+{
+    bool isCleanCheck = false;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (strncmp((char *)pDcChargingInfo->ConnectorWarningCode, code, 6) == EQUAL &&
+            pAlarmCode->AlarmEvents.bits.ChademoGroundWarning == YES) {
+        memcpy(pDcChargingInfo->ConnectorWarningCode, "", 6);
+        isCleanCheck = true;
+    } else if (strncmp((char *)pDcChargingInfo->ConnectorWarningCode, code, 6) == EQUAL &&
+               pAlarmCode->AlarmEvents.bits.CcsGroundfaultWarning == YES) {
+        memcpy(pDcChargingInfo->ConnectorWarningCode, "", 6);
+        isCleanCheck = true;
+    } else if (strncmp((char *)pDcChargingInfo->ConnectorWarningCode, code, 6) == EQUAL &&
+               pAlarmCode->AlarmEvents.bits.GbGroundfaultWarning == YES) {
+        memcpy(pDcChargingInfo->ConnectorWarningCode, "", 6);
+        isCleanCheck = true;
+    }
+
+    if (isCleanCheck) {
+        for (uint8_t index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+            if (index != gunIndex || pSysConfig->TotalConnectorCount == 1) {
+                if (strncmp((char *)pDcChargingInfo->ConnectorWarningCode, code, 6) != EQUAL) {
+                    if (strncmp(code, "012296", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.ChademoGroundWarning = NO; }
+                    if (strncmp(code, "012297", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.CcsGroundfaultWarning = NO; }
+                    if (strncmp(code, "012298", 6) == EQUAL) { pAlarmCode->AlarmEvents.bits.GbGroundfaultWarning = NO; }
+                }
+            }
+        }
+    }
+}
+//===============================================
+// EmergencyStop and Charging Stop
+//===============================================
+void ChargingTerminalProcess(uint8_t gunIndex)
+{
+    setChargerMode(gunIndex, MODE_TERMINATING);
+}
+
+void ChargingAlarmProcess(uint8_t gunIndex)
+{
+    setChargerMode(gunIndex, MODE_ALARM);
+}
+
+void AcChargingTerminalProcess(void)
+{
+    pAcChargingInfo =  (struct ChargingInfoData *)GetAcChargingInfoData(0);
+
+    pAcChargingInfo->SystemStatus = MODE_TERMINATING;
+}
+
+void StopChargingProcessByString(uint8_t level)
+{
+    if (level > pSysWarning->Level) {
+        pSysWarning->Level = level;
+    }
+}
+
+void ReleaseChargingProcessByString(uint8_t level)
+{
+    if (level >= pSysWarning->Level) {
+        pSysWarning->Level = 0;
+    }
+}
+
+// 一般錯誤停止充電處理函式
+void BoardErrOccurByString(uint8_t index, char *code)
+{
+    uint8_t level = 1;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+    if ((pDcChargingInfo->SystemStatus > S_IDLE && pDcChargingInfo->SystemStatus < S_TERMINATING) ||
+            (pDcChargingInfo->SystemStatus >= S_CCS_PRECHARGE_ST0 && pDcChargingInfo->SystemStatus <= S_CCS_PRECHARGE_ST1)) {
+        if (strncmp(code, "023730", 6) == EQUAL && pInfoCode->InfoEvents.bits.ChademoChargerGetEmergencyStop == NO) {
+            pInfoCode->InfoEvents.bits.ChademoChargerGetEmergencyStop = YES;
+        }
+        ChargingTerminalProcess(index);
+    }
+
+    StopChargingProcessByString(level);
+}
+
+void ReleaseBoardErrOccurByString(uint8_t index, char *code)
+{
+    bool isTrigger = false;
+    uint8_t level = 1;
+
+    if (strncmp(code, "023730", 6) == 0 && pInfoCode->InfoEvents.bits.ChademoChargerGetEmergencyStop == YES) {
+        isTrigger = true;
+        pInfoCode->InfoEvents.bits.ChademoChargerGetEmergencyStop = NO;
+    }
+
+    if (isTrigger) {
+        ReleaseChargingProcessByString(level);
+    }
+}
+
+// 急停狀況的停止充電處理函式
+void EmcOccureByString(char *code)
+{
+    uint8_t level = 2;
+    // 嚴重的急停有以下幾種 : EMC 按鈕、Mainbreak、Dooropen
+    // 其錯誤等級為 2
+
+#if defined DD360 ||defined DD360Audi || defined DD360ComBox
+    //DS60-120 remove
+    if (strncmp(code, "012251", 6) == EQUAL ||
+            strncmp(code, "012252", 6) == EQUAL ||
+            strncmp(code, "012238", 6) == EQUAL ||
+            strncmp(code, "042251", 6) == EQUAL ||
+            strncmp(code, "042252", 6) == EQUAL ||
+            strncmp(code, "012304", 6) == EQUAL ||
+            strncmp(code, "042200", 6) == EQUAL ||
+            strncmp(code, "042201", 6) == EQUAL ||
+            strncmp(code, "042202", 6) == EQUAL ||
+            strncmp(code, "042267", 6) == EQUAL)
+#endif //defined DD360 || defined DD360Audi
+    {
+        for (uint8_t gun = 0; gun < pSysConfig->TotalConnectorCount; gun++) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun);
+
+            //strncpy((char *)ShmOCPP16Data->StatusNotification[gun].VendorErrorCode, code, 6);
+
+            if ((pDcChargingInfo->SystemStatus > S_IDLE &&
+                    pDcChargingInfo->SystemStatus < S_TERMINATING) ||
+                    (pDcChargingInfo->SystemStatus >= S_CCS_PRECHARGE_ST0 &&
+                     pDcChargingInfo->SystemStatus <= S_CCS_PRECHARGE_ST1)) {
+                //ChargingTerminalProcess(gun);
+                ChargingAlarmProcess(gun);
+            }
+        }
+#if defined DD360 ||defined DD360Audi || defined DD360ComBox
+        StopChargingProcessByString(level);
+        InformOcppErrOccur(4);
+#endif //defined DD360 || defined DD360Audi
+    }
+}
+
+void ReleaseEmsOccureByString(uint8_t index, char *code)
+{
+    bool isTrigger = false;
+    uint8_t level = 2;
+
+    if (strncmp(code, "042251", 6) == 0 ) {
+        isTrigger = true;
+    } else if (strncmp(code, "012251", 6) == 0 &&
+               pAlarmCode->AlarmEvents.bits.EmergencyStopTrip == YES) {
+        isTrigger = true;
+        pAlarmCode->AlarmEvents.bits.EmergencyStopTrip = NO;
+    } else if (strncmp(code, "012252", 6) == 0 &&
+               pAlarmCode->AlarmEvents.bits.DoorOpen == YES) {
+        isTrigger = true;
+        pAlarmCode->AlarmEvents.bits.DoorOpen = NO;
+    } else if (strncmp(code, "012237", 6) == 0 &&
+               pAlarmCode->AlarmEvents.bits.SpdTrip == YES) {
+        isTrigger = true;
+        pAlarmCode->AlarmEvents.bits.SpdTrip = NO;
+    } else if (strncmp(code, "012238", 6) == 0 &&
+               pAlarmCode->AlarmEvents.bits.MainPowerBreakerTrip == YES) {
+        isTrigger = true;
+        pAlarmCode->AlarmEvents.bits.MainPowerBreakerTrip = NO;
+    }
+
+    if (isTrigger) {
+        ReleaseChargingProcessByString(level);
+        InformOcppErrOccur(6);
+    }
+}
+
+#if 0
+//===============================================
+// 確認硬體 (按鈕) 狀態
+//===============================================
+bool leftBtnPush = false;
+bool rightBtnPush = false;
+
+void ChkPrimaryStatus()
+{
+    uint8_t Rtn;
+
+    if (pSysWarning->WarningCount > 0) {
+        Rtn = 0;
+        for (uint8_t i = 0; i < pSysWarning->WarningCount; i++) {
+            if (memcmp(&pSysWarning->WarningCode[i][0], "042251", 6) == 0) {
+                EmcOccureByString("042251");
+                Rtn = 1;
+            } else if (memcmp(&pSysWarning->WarningCode[i][0], "042252", 6) == 0) {
+                EmcOccureByString("042252");
+                Rtn = 1;
+            } else if (memcmp(&pSysWarning->WarningCode[i][0], "042200", 6) == 0) {
+                EmcOccureByString("042200");
+                Rtn = 1;
+            } else if (memcmp(&pSysWarning->WarningCode[i][0], "042201", 6) == 0) {
+                EmcOccureByString("042201");
+                Rtn = 1;
+            } else if (memcmp(&pSysWarning->WarningCode[i][0], "042202", 6) == 0) {
+                EmcOccureByString("042202");
+                Rtn = 1;
+            } else if (memcmp(&pSysWarning->WarningCode[i][0], "012304", 6) == 0) {
+                EmcOccureByString("012304");
+                Rtn = 1;
+            }
+        }
+        if (Rtn == 0) {
+            ReleaseEmsOccureByString(0, "042251");
+            ReleaseEmsOccureByString(0, "042252");
+            ReleaseEmsOccureByString(0, "042200");
+            ReleaseEmsOccureByString(0, "042201");
+            ReleaseEmsOccureByString(0, "042202");
+            ReleaseEmsOccureByString(0, "012304");
+        }
+    } else {
+        ReleaseEmsOccureByString(0, "042251");
+        ReleaseEmsOccureByString(0, "042252");
+        ReleaseEmsOccureByString(0, "042200");
+        ReleaseEmsOccureByString(0, "042201");
+        ReleaseEmsOccureByString(0, "042202");
+        ReleaseEmsOccureByString(0, "012304");
+    }
+
+    if (ShmPrimaryMcuData->InputDet.bits.EmergencyButton == ABNORMAL) {
+        pAlarmCode->AlarmEvents.bits.EmergencyStopTrip = YES;
+        EmcOccureByString("012251");
+    } else {
+        ReleaseEmsOccureByString(0, "012251");
+    }
+
+    if (ShmPrimaryMcuData->InputDet.bits.AcMainBreakerDetec == ABNORMAL) {
+        pAlarmCode->AlarmEvents.bits.MainPowerBreakerTrip = YES;
+        EmcOccureByString("012238");
+    } else {
+        ReleaseEmsOccureByString(0, "012238");
+    }
+
+    if (ShmPrimaryMcuData->InputDet.bits.SpdDetec == ABNORMAL) {
+        pAlarmCode->AlarmEvents.bits.SpdTrip = YES;
+    } else {
+        pAlarmCode->AlarmEvents.bits.SpdTrip = NO;
+    }
+
+    if (ShmPrimaryMcuData->InputDet.bits.DoorOpen == ABNORMAL) {
+        pAlarmCode->AlarmEvents.bits.DoorOpen = YES;
+        EmcOccureByString("012252");
+    } else {
+        ReleaseEmsOccureByString(0, "012252");
+    }
+
+    //DS60-120 add
+    //if (ShmPrimaryMcuData->InputDet.bits.Button1 == BTN_PRESS &&
+    //        ShmPrimaryMcuData->InputDet.bits.Button2 == BTN_PRESS) {
+    //    pSysConfig->ShowInformation = YES;
+    //} else {
+    //    pSysConfig->ShowInformation = NO;
+    //}
+
+    if (ShmPrimaryMcuData->InputDet.bits.Button1 == BTN_PRESS &&
+            !leftBtnPush
+#if defined DD360Audi
+            &&
+            getCurLcmPage() != _LCM_AUTHORIZING &&
+            getCurLcmPage() != _LCM_AUTHORIZ_COMP &&
+            getCurLcmPage() != _LCM_AUTHORIZ_FAIL
+#endif //defined DD360Audi
+       ) {
+        pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(pSysInfo->CurGunSelected);
+
+        if (!leftBtnPush) {
+            leftBtnPush = true;
+            log_info("left btn down...............................%x\n",
+                     pDcChargingInfo->SystemStatus);
+            if (pSysInfo->CurGunSelectedByAc != NO_DEFINE) {
+                pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(0);
+
+                switch (pAcChargingInfo->SystemStatus) {
+                case S_IDLE: {
+                    if (isDetectPlugin()) {
+                        _DetectPlugInTimeout();
+                        StopSystemTimeoutDet();
+                    }
+                }
+                break;
+                case S_REASSIGN_CHECK:
+                case S_REASSIGN:
+                case S_PREPARNING:
+                case S_PREPARING_FOR_EV:
+                case S_PREPARING_FOR_EVSE:
+                case S_CCS_PRECHARGE_ST0:
+                case S_CCS_PRECHARGE_ST1: {
+                    // 取消充電
+                    AcChargingTerminalProcess();
+                }
+                break;
+                case S_CHARGING: {
+                    if (pSysConfig->AuthorisationMode == AUTH_MODE_DISABLE) {
+                        // 停止充電
+                        AcChargingTerminalProcess();
+                    }
+                }
+                break;
+                case S_COMPLETE:
+                {}
+                break;
+                }
+            }
+
+            switch (pDcChargingInfo->SystemStatus) {
+            case S_IDLE: {
+                if (isDetectPlugin()) {
+                    _DetectPlugInTimeout();
+                    StopSystemTimeoutDet();
+                    destroySelGun(pSysInfo->CurGunSelected);
+                }
+#if defined DD360Audi
+                else {
+                    if (getConfirmSelectedGun(pSysInfo->CurGunSelected) == PASS) {
+                        //printf("destroy gun = %d\r\n", pSysInfo->CurGunSelected);
+                        destroySelGun(pSysInfo->CurGunSelected);
+                    } else {
+                        confirmSelGun(pSysInfo->CurGunSelected);
+                        log_info("confirm select gun ............................... %d \n",
+                                 pSysInfo->CurGunSelected);
+                    }
+                }
+#endif //defined DD360Audi
+            }
+            break;
+            case S_REASSIGN_CHECK:
+            case S_REASSIGN:
+            case S_PREPARNING:
+            case S_PREPARING_FOR_EV:
+            case S_PREPARING_FOR_EVSE:
+            case S_CCS_PRECHARGE_ST0:
+            case S_CCS_PRECHARGE_ST1: {
+                // 取消充電
+                if (pSysInfo->CurGunSelectedByAc != NO_DEFINE) {
+                    AcChargingTerminalProcess();
+                } else {
+                    ChargingTerminalProcess(pSysInfo->CurGunSelected);
+                }
+            }
+            break;
+            case S_CHARGING: {
+                if (pSysConfig->StopChargingByButton == YES ||
+                        pSysConfig->AuthorisationMode == AUTH_MODE_DISABLE) {
+                    // 停止充電
+                    ChargingTerminalProcess(pSysInfo->CurGunSelected);
+                }
+            }
+            break;
+            case S_COMPLETE: {
+                // 回 IDLE
+                //log_info("right btn down.................S_COMPLETE \n");
+                //pDcChargingInfo->SystemStatus = S_IDLE;
+            }
+            break;
+            }
+        }
+    } else if (ShmPrimaryMcuData->InputDet.bits.Button1 == BTN_RELEASE) {
+        if (leftBtnPush) {
+            leftBtnPush = false;
+            //log_info("left btn up............................... \n");
+        }
+    }
+
+    if (ShmPrimaryMcuData->InputDet.bits.Button2 == BTN_PRESS &&
+            !rightBtnPush
+#if defined DD360Audi
+            &&
+            getCurLcmPage() != _LCM_IDLE &&
+            getCurLcmPage() != _LCM_AUTHORIZING &&
+            getCurLcmPage() != _LCM_AUTHORIZ_COMP &&
+            getCurLcmPage() != _LCM_AUTHORIZ_FAIL &&
+            getCurLcmPage() != _LCM_WAIT_FOR_PLUG
+#endif //defined DD360Audi
+       ) {
+        if (!rightBtnPush) {
+            rightBtnPush = true;
+            //log_info("right btn down............................... %d \n", pSysInfo->CurGunSelected);
+            if (pSysInfo->CurGunSelected + 1 < pSysConfig->TotalConnectorCount &&
+                    pSysInfo->IsAlternatvieConf == NO) {
+                pSysInfo->CurGunSelected++;
+                ChangeGunSelectByIndex(pSysInfo->CurGunSelected);
+            } else if (pSysConfig->AcConnectorCount > 0 &&
+                       pSysInfo->CurGunSelectedByAc == NO_DEFINE) {
+                pSysInfo->CurGunSelectedByAc = DEFAULT_AC_INDEX;
+            } else if (pSysInfo->IsAlternatvieConf == YES) {
+                for (uint8_t _index = 0; _index < pSysConfig->TotalConnectorCount; _index++) {
+                    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_index);
+
+                    if (pDcChargingInfo->SystemStatus != S_BOOTING &&
+                            pDcChargingInfo->SystemStatus != S_IDLE &&
+                            pDcChargingInfo->SystemStatus != S_RESERVATION) {
+                        pSysInfo->CurGunSelected = _index;
+                        ChangeGunSelectByIndex(pSysInfo->CurGunSelected);
+                        return;
+                    }
+                }
+                pSysInfo->CurGunSelected = 0;
+                ChangeGunSelectByIndex(pSysInfo->CurGunSelected);
+            } else {
+                pSysInfo->CurGunSelected = 0;
+                ChangeGunSelectByIndex(pSysInfo->CurGunSelected);
+            }
+        }
+        log_info("current select gun ............................... %d \n",
+                 pSysInfo->CurGunSelected);
+    } else if (ShmPrimaryMcuData->InputDet.bits.Button2 == BTN_RELEASE) {
+        if (rightBtnPush) {
+            rightBtnPush = false;
+            //log_info("right btn up............................... \n");
+        }
+    }
+}
+#endif //0
+
+//===============================================
+// 確認各小板偵測的錯誤狀況
+//===============================================
+void CheckErrorOccurStatus(uint8_t index)
+{
+#if 0
+    // 小板
+    if (chargingInfo[index]->Type == _Type_Chademo) {
+        if (pFaultCode->FaultEvents.bits.ChademoOutputRelayDrivingFault == YES) {
+            BoardErrOccurByString(index, "011012");
+        }
+//      else if (pAlarmCode->AlarmEvents.bits.ChademoGfdTrip == YES)
+//          BoardErrOccurByString(index, "012234");
+    } else if (chargingInfo[index]->Type == _Type_GB) {
+        if (pFaultCode->FaultEvents.bits.GbOutputRelayDrivingFault == YES) {
+            BoardErrOccurByString(index, "011016");
+        }
+//      else if (pAlarmCode->AlarmEvents.bits.GbGfdTrip == YES)
+//          BoardErrOccurByString(index, "012236");
+    } else if (chargingInfo[index]->Type == _Type_CCS_2) {
+        if (pFaultCode->FaultEvents.bits.CcsOutputRelayDrivingFault == YES) {
+            BoardErrOccurByString(index, "011014");
+        }
+//      else if (pAlarmCode->AlarmEvents.bits.CcsGfdTrip == YES)
+//          BoardErrOccurByString(index, "012235");
+    }
+#endif //0
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+    // RB
+    if (pSysConfig->PhaseLossPolicy == YES) {
+        if (pAlarmCode->AlarmEvents.bits.SystemL1InputUVP == YES ||
+                pAlarmCode->AlarmEvents.bits.SystemL2InputUVP == YES ||
+                pAlarmCode->AlarmEvents.bits.SystemL3InputUVP == YES) {
+            if (pSysWarning->ExtraErrProcess == _EXTRA_ERR_PROCESS_NONE) {
+                pSysWarning->ExtraErrProcess = _EXTRA_ERR_PROCESS_INUVP;
+                StopChargingProcessByString(2);
+                InformOcppErrOccur(13);
+            }
+
+            //DS60-120 add -----
+            if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "", 6) == EQUAL) {
+                if (pAlarmCode->AlarmEvents.bits.SystemL1InputUVP == YES) {
+                    memcpy(pDcChargingInfo->ConnectorAlarmCode, "012203", 6);
+                } else if (pAlarmCode->AlarmEvents.bits.SystemL2InputUVP == YES) {
+                    memcpy(pDcChargingInfo->ConnectorAlarmCode, "012204", 6);
+                } else if (pAlarmCode->AlarmEvents.bits.SystemL3InputUVP == YES) {
+                    memcpy(pDcChargingInfo->ConnectorAlarmCode, "012205", 6);
+                }
+            }
+            //log_info("1 CheckErrorOccurStatus\r\n");
+            pDcChargingInfo->StopChargeFlag = YES;
+            //------------------------------------------------------------------
+        } else {
+            if (pSysWarning->ExtraErrProcess == _EXTRA_ERR_PROCESS_INUVP) {
+                pSysWarning->ExtraErrProcess = _EXTRA_ERR_PROCESS_NONE;
+                ReleaseChargingProcessByString(2);
+                InformOcppErrOccur(6);
+            }
+        }
+    } else {
+        if (pSysWarning->ExtraErrProcess == _EXTRA_ERR_PROCESS_INUVP) {
+            pSysWarning->ExtraErrProcess = _EXTRA_ERR_PROCESS_NONE;
+            ReleaseChargingProcessByString(2);
+            InformOcppErrOccur(6);
+        }
+    }
+
+    if (pAlarmCode->AlarmEvents.bits.SystemL1InputOVP == YES ||
+            pAlarmCode->AlarmEvents.bits.SystemL2InputOVP == YES ||
+            pAlarmCode->AlarmEvents.bits.SystemL3InputOVP == YES) {
+        if (pSysWarning->ExtraErrProcess == _EXTRA_ERR_PROCESS_NONE) {
+            pSysWarning->ExtraErrProcess = _EXTRA_ERR_PROCESS_INOVP;
+            StopChargingProcessByString(2);
+            InformOcppErrOccur(14);
+        }
+
+        //DS60-120 -----
+        if (strncmp((char *)pDcChargingInfo->ConnectorAlarmCode, "", 6) == EQUAL) {
+            if (pAlarmCode->AlarmEvents.bits.SystemL1InputOVP == YES) {
+                memcpy(pDcChargingInfo->ConnectorAlarmCode, "012200", 6);
+            } else if (pAlarmCode->AlarmEvents.bits.SystemL2InputOVP == YES) {
+                memcpy(pDcChargingInfo->ConnectorAlarmCode, "012201", 6);
+            } else if (pAlarmCode->AlarmEvents.bits.SystemL3InputOVP == YES) {
+                memcpy(pDcChargingInfo->ConnectorAlarmCode, "012202", 6);
+            }
+        }
+        //log_info("2 CheckErrorOccurStatus\r\n");
+        pDcChargingInfo->StopChargeFlag = YES;
+        //----------------------------------------------------------------------
+    } else {
+        if (pSysWarning->ExtraErrProcess == _EXTRA_ERR_PROCESS_INOVP) {
+            pSysWarning->ExtraErrProcess = _EXTRA_ERR_PROCESS_NONE;
+            ReleaseChargingProcessByString(2);
+            InformOcppErrOccur(6);
+        }
+    }
+
+    //DS60-120 ----
+    //if (chargingInfo[index]->Type == _Type_Chademo) {
+    //    if (pFaultCode->FaultEvents.bits.ChademoOutputRelayWelding == YES) {
+    //        memcpy(chargingInfo[index]->ConnectorAlarmCode, "011011", 6);
+    //    } else if (pFaultCode->FaultEvents.bits.ChademoOutputRelayDrivingFault == YES) {
+    //        memcpy(chargingInfo[index]->ConnectorAlarmCode, "011012", 6);
+    //    } else if (pAlarmCode->AlarmEvents.bits.SystemChademoOutputOVP == YES) {
+    //        memcpy(chargingInfo[index]->ConnectorAlarmCode, "012217", 6);
+    //    }
+    //} else if (chargingInfo[index]->Type == _Type_GB) {
+    //    if (pFaultCode->FaultEvents.bits.GbOutputRelayWelding == YES) {
+    //        memcpy(chargingInfo[index]->ConnectorAlarmCode, "011015", 6);
+    //    } else if (pFaultCode->FaultEvents.bits.GbOutputRelayDrivingFault == YES) {
+    //        memcpy(chargingInfo[index]->ConnectorAlarmCode, "011016", 6);
+    //    } else if (pAlarmCode->AlarmEvents.bits.SystemGbOutputOVP == YES) {
+    //        memcpy(chargingInfo[index]->ConnectorAlarmCode, "012221", 6);
+    //    }
+    //} else if (chargingInfo[index]->Type == _Type_CCS_2) {
+    //    if (pFaultCode->FaultEvents.bits.CcsOutputRelayWelding == YES) {
+    //        memcpy(chargingInfo[index]->ConnectorAlarmCode, "011013", 6);
+    //    } else if (pFaultCode->FaultEvents.bits.CcsOutputRelayDrivingFault == YES) {
+    //        memcpy(chargingInfo[index]->ConnectorAlarmCode, "011014", 6);
+    //    } else if (pAlarmCode->AlarmEvents.bits.SystemCcsOutputOVP == YES) {
+    //        memcpy(chargingInfo[index]->ConnectorAlarmCode, "012219", 6);
+    //    }
+    //}
+
+    //--------------------------------------------------------------------------
+    if (strlen((char *)pDcChargingInfo->ConnectorAlarmCode) == 0) {
+        //Primary
+        if (pAlarmCode->AlarmEvents.bits.EmergencyStopTrip == YES) {
+            memcpy(pDcChargingInfo->ConnectorAlarmCode, "012251", 6);
+        } else if (pAlarmCode->AlarmEvents.bits.DoorOpen == YES) {
+            memcpy(pDcChargingInfo->ConnectorAlarmCode, "012252", 6);
+        } else if (pAlarmCode->AlarmEvents.bits.MainPowerBreakerTrip == YES) {
+            memcpy(pDcChargingInfo->ConnectorAlarmCode, "012238", 6);
+        } else if (pAlarmCode->AlarmEvents.bits.DisconnectedFromDo == YES) {
+            memcpy(pDcChargingInfo->ConnectorAlarmCode, "012304", 6);
+        }
+    }
+}
+
+//===============================================
+// 確認 GPIO 狀態
+//===============================================
+void gpio_set_value(unsigned int gpio, unsigned int value)
+{
+    int fd;
+    char buf[MAX_BUF];
+
+    snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);
+    fd = open(buf, O_WRONLY);
+    if (fd < 0) {
+        perror("gpio/set-value");
+        return;
+    }
+
+    if (value) {
+        write(fd, "1", 2);
+    } else {
+        write(fd, "0", 2);
+    }
+
+    close(fd);
+}
+
+int gpio_get_value(unsigned int gpio, unsigned int *value)
+{
+    int fd;
+    char buf[MAX_BUF];
+    char ch;
+
+    snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);
+
+    fd = open(buf, O_RDONLY);
+    if (fd < 0) {
+        perror("gpio/get-value");
+        return fd;
+    }
+
+    read(fd, &ch, 1);
+
+    if (ch != '0') {
+        *value = 1;
+    } else {
+        *value = 0;
+    }
+
+    close(fd);
+    return 0;
+}
+
+void CheckGunTypeFromHw()
+{
+    uint8_t i = 0;
+    int pinIn[4] = {22, 23, 44, 45};
+    unsigned int gpioValue = 0;
+    uint8_t tmp[2] = {0};
+
+    log_info("ModelName = %s", pSysConfig->ModelName);
+    for (i = 0; i < ARRAY_SIZE(pinIn); i++) {
+        gpio_get_value(pinIn[i], &gpioValue);
+        switch (pinIn[i]) {
+        //right slot
+        case 22:
+            bd1_1_status = gpioValue;
+            break;
+        case 23:
+            bd1_2_status = gpioValue;
+            break;
+
+        //left slot
+        case 44:
+            bd0_1_status = gpioValue;
+            break;
+        case 45:
+            bd0_2_status = gpioValue;
+            break;
+        }
+    }
+
+#if 1 //DS60-120 remove
+    //BD1(Left-CCS-CND1-SMR2-左槍), BD2(Right-CHADEMO-CND2-SMR1-右槍), CCS: 10 , CHAdeMO: 01 , GBT: 11
+    //CcsChargingData [0至1] 分別為 Right至Left
+    //model name 槍順序左至右分別為Right至Left
+    tmp[1] = (bd0_1_status << 4 | bd0_2_status);
+    tmp[0] = (bd1_1_status << 4 | bd1_2_status);
+    for (i = 0; i < 2; i++) {
+        switch (tmp[i]) {
+        case 0x01:
+            log_info("BD%d(%s) = %s ", i + 1, i == 0 ? "Left" : "Right", "CHAdeMO");
+            break;
+
+        case 0x10:
+            log_info("BD%d(%s) = %s ", i + 1, i == 0 ? "Left" : "Right", "CCS");
+            break;
+
+        case 0x11:
+            log_info("BD%d(%s) = %s ", i + 1, i == 0 ? "Left" : "Right", "GBT");
+            break;
+
+        case 0x00:
+            log_info("BD%d(%s) = %s ", i + 1, i == 0 ? "Left" : "Right", "None");
+            break;
+        }
+    }
+#endif //0
+}
+
+void CheckGpioInStatus()
+{
+    int pinIn[2] = { 27, 47 };//{IO BD1_2, IO BD2_2}
+    unsigned int gpioValue = 0;
+
+    for (int i = 0; i < ARRAY_SIZE(pinIn); i++) {
+        gpio_get_value(pinIn[i], &gpioValue);
+        if (gpioValue == 0x01) {
+            switch (pinIn[i]) {
+            // 小板緊急停止
+            case 47: {
+                for (int i = 0; i < pSysConfig->TotalConnectorCount; i++) {
+                    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(i);
+
+                    if (pDcChargingInfo->slotsIndex == 1) {
+                        if (pDcChargingInfo->Type == _Type_Chademo) {
+                            BoardErrOccurByString(i, "023730");
+                        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                            BoardErrOccurByString(i, "013627");
+                        }
+                        break;
+                    }
+                }
+            }
+            break;
+            case 27: {
+                for (int i = 0; i < pSysConfig->TotalConnectorCount; i++) {
+                    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(i);
+
+                    if (pDcChargingInfo->slotsIndex == 3) {
+                        if (pDcChargingInfo->Type == _Type_Chademo) {
+                            BoardErrOccurByString(i, "023730");
+                        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                            BoardErrOccurByString(i, "013627");
+                        }
+                        break;
+                    }
+                }
+            }
+            break;
+            }
+        } else {
+            switch (pinIn[i]) {
+            // 小板解除緊急停止
+            case 47: {
+                for (int i = 0; i < pSysConfig->TotalConnectorCount; i++) {
+                    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(i);
+
+                    if (pDcChargingInfo->slotsIndex == 1) {
+                        if (pDcChargingInfo->Type == _Type_Chademo) {
+                            ReleaseBoardErrOccurByString(i, "023730");
+                        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                            ReleaseBoardErrOccurByString(i, "013627");
+                        }
+                        break;
+                    }
+                }
+            }
+            break;
+            case 27: {
+                for (int i = 0; i < pSysConfig->TotalConnectorCount; i++) {
+                    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(i);
+
+                    if (pDcChargingInfo->slotsIndex == 3) {
+                        if (pDcChargingInfo->Type == _Type_Chademo) {
+                            ReleaseBoardErrOccurByString(i, "023730");
+                        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                            ReleaseBoardErrOccurByString(i, "013627");
+                        }
+                        break;
+                    }
+                }
+            }
+            break;
+            }
+        }
+    }
+}
+
+//===============================================
+// Main process
+//===============================================
+// 檢查 uint8_t 中某個 Bit 的值
+// _byte : 欲改變的 byte
+// _bit : 該 byte 的第幾個 bit
+uint8_t DetectBitValue(uint8_t _byte, uint8_t _bit)
+{
+    return ( _byte & mask_table[_bit] ) != 0x00;
+}
+
+// 設定 Byte 中某個 Bit的值
+// _byte : 欲改變的 byte
+// _bit : 該 byte 的第幾個 bit
+// value : 修改的值為 0 or 1
+void SetBitValue(uint8_t *_byte, uint8_t _bit, uint8_t value)
+{
+    if (value == 1) {
+        *_byte |= (1 << _bit);
+    } else if (value == 0) {
+        *_byte ^= (1 << _bit);
+    }
+}
+
+#if 0
+void UserScanFunction()
+{
+    bool idleReq = false;
+    uint8_t stopReq = 255;
+    pAcChargingInfo =  (struct ChargingInfoData *)GetAcChargingInfoData(0);
+
+    // 當前非驗證的狀態
+    if (!IsAuthorizingMode()) {
+#if defined DD360Audi
+        //當前沒有選槍
+        if (getConfirmSelectedGun(pSysInfo->CurGunSelected) == FAIL) { //Jerry add
+            strcpy((char *)pSysConfig->UserId, "");
+            return;
+        }
+#endif //defined DD360Audi
+
+        // 先判斷現在是否可以提供刷卡
+        // 1. 如果當前沒有槍是閒置狀態,則無提供刷卡功能
+        // 2. 停止充電
+        if (pSysInfo->PageIndex == _LCM_FIX) {
+            strcpy((char *)pSysConfig->UserId, "");
+            return;
+        }
+
+        for (uint8_t i = 0; i < pSysConfig->TotalConnectorCount; i++) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(i);
+
+            if (pDcChargingInfo->SystemStatus == S_CHARGING) {
+                stopReq = i;
+            }
+            if ((pDcChargingInfo->SystemStatus == S_IDLE &&
+                    pDcChargingInfo->IsAvailable) == YES ||
+                    (_acgunIndex > 0 && pAcChargingInfo->SystemStatus ==
+                     S_IDLE && pAcChargingInfo->IsAvailable)
+               ) {
+                idleReq = true;
+            }
+        }
+
+        if (_acgunIndex > 0 && pSysInfo->CurGunSelectedByAc == DEFAULT_AC_INDEX &&
+                pAcChargingInfo->SystemStatus == S_CHARGING) {
+            stopReq = DEFAULT_AC_INDEX;
+        }
+
+        if (strlen((char *)pSysConfig->UserId) > 0) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(pSysInfo->CurGunSelected);
+
+            if (_acgunIndex > 0 && stopReq == DEFAULT_AC_INDEX &&
+                    pSysInfo->CurGunSelectedByAc == DEFAULT_AC_INDEX) {
+                char value[32];
+
+                log_info("ac stop charging \n");
+                log_info("index = %d, card number = %s, UserId = %s \n", pSysInfo->CurGunSelectedByAc,
+                         pAcChargingInfo->StartUserId, pSysConfig->UserId);
+                memcpy(value, (uint8_t *)pAcChargingInfo->StartUserId,
+                       ARRAY_SIZE(pAcChargingInfo->StartUserId));
+                if (strcmp((char *)pSysConfig->UserId, value) == EQUAL) {
+                    AcChargingTerminalProcess();
+                }
+                strcpy((char *)pSysConfig->UserId, "");
+            } else if (stopReq < pSysConfig->TotalConnectorCount &&
+                       pDcChargingInfo->SystemStatus == S_CHARGING &&
+                       (_acgunIndex <= 0 || (_acgunIndex > 0 && pSysInfo->CurGunSelectedByAc == NO_DEFINE))) {
+                char value[32];
+
+                log_info("stop charging \n");
+                log_info("index = %d, card number = %s, UserId = %s \n",
+                         pSysInfo->CurGunSelected,
+                         pDcChargingInfo->StartUserId,
+                         pSysConfig->UserId);
+                memcpy(value, (uint8_t *)pDcChargingInfo->StartUserId,
+                       ARRAY_SIZE(pDcChargingInfo->StartUserId));
+
+                // 同一張卡直接停掉
+                if (strcmp((char *)pSysConfig->UserId, value) == EQUAL) {
+                    ChargingTerminalProcess(pSysInfo->CurGunSelected);
+                    strcpy((char *)pSysConfig->UserId, "");
+                } else {
+                    // 進驗證
+                    if (_acgunIndex > 0 && pSysInfo->CurGunSelectedByAc == DEFAULT_AC_INDEX) {
+                        _authorizeIndex = pSysInfo->CurGunSelectedByAc;
+                    } else {
+                        _authorizeIndex = pSysInfo->CurGunSelected;
+                    }
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                    StartSystemTimeoutDet(Timeout_AuthorizingForStop);
+                    AuthorizingStart();
+#else
+                    strcpy((char *)pSysConfig->UserId, "");
+#endif //!defined DD360 && !defined DD360Audi
+                }
+            } else if (idleReq) {
+                if (pSysConfig->TotalConnectorCount > 1 &&
+                        stopReq != 255 &&
+                        pSysInfo->IsAlternatvieConf == YES) {
+                    idleReq = false;
+                    strcpy((char *)pSysConfig->UserId, "");
+                } else if ((_acgunIndex > 0 && pSysInfo->CurGunSelectedByAc == DEFAULT_AC_INDEX) ||
+                           pDcChargingInfo->SystemStatus == S_IDLE) {
+                    log_info("// LCM => Authorizing \n");
+#if defined DD360Audi
+                    setSelGunWaitToAuthor(pSysInfo->CurGunSelected); //Jerry add
+#endif //defined DD360Audi
+                    // LCM => Authorizing
+                    pSysInfo->SystemPage = _LCM_AUTHORIZING;
+                    // 進入確認卡號狀態
+                    AuthorizingStart();
+                } else {
+                    strcpy((char *)pSysConfig->UserId, "");
+                }
+            } else {
+                strcpy((char *)pSysConfig->UserId, "");
+            }
+        }
+    } else {
+        // 透過後臺停止充電的判斷
+        if (isAuthorizedComplete()
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                || (pSysInfo->OcppConnStatus == NO &&
+                    pSysConfig->OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING)
+#endif //!defined DD360 && !defined DD360Audi
+           ) {
+            // 判斷後台回覆狀態
+            if (canStartCharging()
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                    || (pSysInfo->OcppConnStatus == NO &&
+                        pSysConfig->OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING)
+#endif //!defined DD360 && !defined DD360Audi
+               ) {
+                if (_authorizeIndex != NO_DEFINE) {
+                    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_authorizeIndex);
+
+                    // 先找 AC
+                    if (_authorizeIndex == DEFAULT_AC_INDEX) {
+                        if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST &&
+                                strcmp((char *)pDcChargingInfo->StartUserId, "") != EQUAL) {
+                            AcChargingTerminalProcess();
+                        }
+                    } else {
+                        if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST &&
+                                strcmp((char *)pDcChargingInfo->StartUserId, "") != EQUAL) {
+                            ChargingTerminalProcess(_authorizeIndex);
+                        }
+                    }
+                    strcpy((char *)pSysConfig->UserId, "");
+                    _authorizeIndex = NO_DEFINE;
+                }
+            } else {
+                strcpy((char *)pSysConfig->UserId, "");
+            }
+            ClearAuthorizedFlag();
+        } else if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST) {
+            // 白名單驗證
+            for (int i = 0; i < 10; i++) {
+                if (strcmp((char *)pSysConfig->LocalWhiteCard[i], "") != EQUAL) {
+                    if (strcmp((char *)pSysConfig->LocalWhiteCard[i], (char *)pSysConfig->UserId) == EQUAL) {
+                        ChargingTerminalProcess(_authorizeIndex);
+                        strcpy((char *)pSysConfig->UserId, "");
+                        ClearAuthorizedFlag();
+                        break;
+                    }
+                }
+            }
+        }
+    }
+}
+#endif //0
+
+uint8_t isModeChange(uint8_t gun_index)
+{
+    uint8_t result = NO;
+
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun_index);
+
+    if (pDcChargingInfo->SystemStatus != pDcChargingInfo->PreviousSystemStatus) {
+        result = YES;
+        pDcChargingInfo->PreviousSystemStatus = pDcChargingInfo->SystemStatus;
+        ShmDcCommonData->SystemModeChange = YES;
+    }
+
+    return result;
+}
+
+#if 0
+void ScannerCardProcess()
+{
+    if (!isDetectPlugin() && !isCardScan && pSysWarning->Level != 2 &&
+            pSysConfig->AuthorisationMode == AUTH_MODE_ENABLE) {
+        isCardScan = true;
+        // 處理刷卡及驗證卡號的動作
+        UserScanFunction();
+    }
+
+    if (pSysInfo->PageIndex == _LCM_AUTHORIZING) {
+        StartSystemTimeoutDet(Timeout_Authorizing);
+
+        // 確認驗證卡號完成沒
+        if (isAuthorizedComplete()
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                || pSysConfig->OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING
+#else
+                && gAudiCustInfo->PricesInfo[pSysInfo->CurGunSelected].Balance != FAIL_BALANCE_PRICES
+#endif //!defined DD360 && !defined DD360Audi
+           ) {
+            StopSystemTimeoutDet();
+            // 判斷後台回覆狀態
+            if (canStartCharging()
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                    || pSysConfig->OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING
+#endif //!defined DD360 && !defined DD360Audi
+               ) {
+                // LCM => Authorize complete
+                pSysInfo->SystemPage = _LCM_AUTHORIZ_COMP;
+            } else {
+                // LCM => Authorize fail
+                pSysInfo->SystemPage = _LCM_AUTHORIZ_FAIL;
+                strcpy((char *)pSysConfig->UserId, "");
+            }
+            ClearAuthorizedFlag();
+        } else if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST) {
+            // 白名單驗證
+            for (int i = 0; i < 10; i++) {
+                if (strcmp((char *)pSysConfig->LocalWhiteCard[i], "") != EQUAL) {
+                    if (strcmp((char *)pSysConfig->LocalWhiteCard[i], (char *)pSysConfig->UserId) == EQUAL) {
+                        pSysInfo->SystemPage = _LCM_AUTHORIZ_COMP;
+                        ClearAuthorizedFlag();
+                        break;
+                    }
+                }
+            }
+        }
+    } else if (pSysInfo->PageIndex == _LCM_AUTHORIZ_FAIL) {
+        StartSystemTimeoutDet(Timeout_VerifyFail);
+        isCardScan = false;
+    } else if (pSysInfo->PageIndex == _LCM_AUTHORIZ_COMP) {
+        StartSystemTimeoutDet(Timeout_VerifyComp);
+    } else if (pSysInfo->PageIndex == _LCM_WAIT_FOR_PLUG) {
+        StartSystemTimeoutDet(Timeout_WaitPlug);
+    } else {
+        isCardScan = false;
+    }
+}
+
+bool AddGunInfoByConnector(uint8_t typeValue, uint8_t slots)
+{
+    bool result = true;
+
+    switch (typeValue) {
+    case '0': // none
+        break;
+    case '1': // IEC 62196-2 Type 1/SAE J1772 Plug
+        break;
+    case '2': // IEC 62196-2 Type 1/SAE J1772 Socket
+        break;
+    case '3': // IEC 62196-2 Type 2 Plug
+    case '4': // IEC 62196-2 Type 2 Socket
+        if (AC_QUANTITY > _ac_Index) {
+            pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(_acgunIndex);
+
+            pAcChargingInfo = &pSysInfo->AcChargingData[_ac_Index];
+
+            // AC 固定 index
+            pAcChargingInfo->Index = 0;
+            pAcChargingInfo->ReservationId = -1;
+            pAcChargingInfo->SystemStatus = S_IDLE;
+            pAcChargingInfo->Type = _Type_AC;
+            pAcChargingInfo->IsAvailable = YES;
+            pAcChargingInfo->schedule.isTriggerStart = NO; //DS60-120 add
+            pAcChargingInfo->schedule.isTriggerStop = NO;  //DS60-120 add
+            _ac_Index++;
+            _acgunIndex++;
+        } else {
+            result = false;
+        }
+        break;
+    case '5': // GB/T AC Plug
+        break;
+    case '6': // GB/T AC Socket
+        break;
+    case 'J':
+    case 'K': { // CHAdeMO
+        if (CHAdeMO_QUANTITY > _chademoIndex) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_gunIndex);
+
+            pDcChargingInfo = &pSysInfo->ChademoChargingData[_chademoIndex];
+            pDcChargingInfo->Index = _gunIndex;
+            pDcChargingInfo->ReservationId = -1;
+            pDcChargingInfo->slotsIndex = slots;
+            pDcChargingInfo->SystemStatus = S_BOOTING;
+            pDcChargingInfo->Type = _Type_Chademo;
+            pDcChargingInfo->type_index = _chademoIndex;
+            pDcChargingInfo->IsAvailable = YES;
+
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_acgunIndex);
+            pDcChargingInfo->schedule.isTriggerStart = NO; //DS60-120 add
+            pDcChargingInfo->schedule.isTriggerStop = NO;  //DS60-120 add
+            _chademoIndex++;
+            _gunIndex++;
+        } else {
+            result = false;
+        }
+    }
+    break;
+
+    case 'T': //Rema CCS1
+    case 'D': //Rema CCS2
+    case 'U': // CCS1 combo
+    case 'E': // CCS2 combo
+    case 'V': // Liquid CCS1 combo
+    case 'F': { // Liquid CCS2 combo
+        if (CCS_QUANTITY > _ccsIndex) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_gunIndex);
+
+            pDcChargingInfo = &pSysInfo->CcsChargingData[_ccsIndex];
+
+            pDcChargingInfo->Index = _gunIndex;
+            pDcChargingInfo->ReservationId = -1;
+            pDcChargingInfo->slotsIndex = slots;
+            pDcChargingInfo->SystemStatus = S_BOOTING;
+            pDcChargingInfo->Type = _Type_CCS_2;
+            pDcChargingInfo->type_index = _ccsIndex;
+            pDcChargingInfo->IsAvailable = YES;
+
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_acgunIndex);
+            pDcChargingInfo->schedule.isTriggerStart = NO;//DS60-120 add
+            pDcChargingInfo->schedule.isTriggerStop = NO; //DS60-120 add
+            // 現階段預設為走 DIN70121
+            ShmCcsData->CommProtocol = _CCS_COMM_V2GMessage_DIN70121;
+            _ccsIndex++;
+            _gunIndex++;
+        } else {
+            result = false;
+        }
+    }
+    break;
+    case 'G': { // GBT DC
+        if (GB_QUANTITY > _gb_Index) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_gunIndex);
+
+            pDcChargingInfo = &pSysInfo->GbChargingData[_gb_Index];
+
+            pDcChargingInfo->Index = _gunIndex;
+            pDcChargingInfo->ReservationId = -1;
+            pDcChargingInfo->slotsIndex = slots;
+            pDcChargingInfo->SystemStatus = S_BOOTING;
+            pDcChargingInfo->Type = _Type_GB;
+            pDcChargingInfo->type_index = _gb_Index;
+            pDcChargingInfo->IsAvailable = YES;
+
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_acgunIndex);
+            pDcChargingInfo->schedule.isTriggerStart = NO;//DS60-120 add
+            pDcChargingInfo->schedule.isTriggerStop = NO; //DS60-120 add
+            _gb_Index++;
+            _gunIndex++;
+        } else {
+            result = false;
+        }
+    }
+    break;
+
+        //case 'D': // GBT DC x 2
+        //    break;
+    }
+    return result;
+}
+#endif //0
+
+static int checkSlotGpioMappingGunType(uint8_t gunIndex, uint8_t gunType)
+{
+    uint8_t slot1 = 0, slot2 = 0;
+
+    if (gunIndex == 0) {
+        slot1 = bd0_1_status;
+        slot2 = bd0_2_status;
+    } else if (gunIndex == 1) {
+        slot1 = bd1_1_status;
+        slot2 = bd1_2_status;
+    }
+
+    log_info("slot %d gpio1 = %d, gpio2 = %d, type = %d\r\n", gunIndex, slot1, slot2, gunType);
+    switch (gunType) {
+    case _Type_Chademo:
+        if (slot1 != NO && slot2 != YES) {
+            return FAIL;
+        }
+        break;
+
+    case _Type_CCS_2:
+        if (slot1 != YES && slot2 != NO) {
+            return FAIL;
+        }
+        break;
+
+    case _Type_GB:
+        if (slot1 != YES && slot2 != YES) {
+            return FAIL;
+        }
+        break;
+    }
+
+    return PASS;
+}
+
+bool CheckConnectorTypeStatus()
+{
+    bool result = true;
+
+    uint8_t gunIndex = 0;
+    struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
+    struct ChargingInfoData *pDcChargingInfo = NULL;
+
+    if (!MappingGunChargingInfo("CSU Task")) {
+        log_error("CheckConnectorTypeStatus MappingGunChargingInfo failed\r\n");
+        return false;
+    }
+
+    // 偵測槍屬於哪個 slot : 可知道插在板上的Slot 0 或 1 是 Chademo 還是 CCS
+    for (gunIndex = 0; gunIndex < pSysConfig->TotalConnectorCount; gunIndex++) {
+        pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+        if (checkSlotGpioMappingGunType(gunIndex, pDcChargingInfo->Type) == FAIL) {
+            return false;
+        }
+
+        switch (gunIndex) {
+        case 0:
+            if (pSysConfig->TotalConnectorCount == 1) {
+                if ((bd0_1_status == YES || bd0_2_status == YES) &&
+                        (bd1_1_status == NO && bd1_2_status == NO)) {
+                    pDcChargingInfo->Evboard_id = 0x01;
+                }
+
+                if ((bd0_1_status == NO && bd0_2_status == NO) &&
+                        (bd1_1_status == YES || bd1_2_status == YES)
+                   ) {
+                    pDcChargingInfo->Evboard_id = 0x02;
+                }
+                break;
+            }
+
+            pDcChargingInfo->Evboard_id = 0x01;
+            break;
+
+        case 1:
+            pDcChargingInfo->Evboard_id = 0x02;
+            break;
+        }
+
+        CheckHwSlotStatusLog(gunIndex);
+
+        if (pDcChargingInfo->Evboard_id == 0x00) {
+            return false;
+        }
+    }
+
+    AdjustChargerCurrent();
+
+#if 0
+    //log_info("bd0_1_status = %d, bd0_2_status = %d, bd1_1_status = %d, bd1_2_status = %d \n",
+    //            bd0_1_status,
+    //            bd0_2_status,
+    //            bd1_1_status,
+    //            bd1_2_status);
+
+    if (strlen((char *) pSysConfig->ModelName) >= 9) {
+        //printf("1 CheckConnectorTypeStatus\r\n");
+        uint8_t slots = 1;
+        for (uint8_t typeIndex = 7; typeIndex <= 9; typeIndex++) {
+            if (!AddGunInfoByConnector(pSysConfig->ModelName[typeIndex], slots)) {
+                return false;
+            }
+
+            slots++;
+        }
+
+        // AC index 接在 DC 後面
+        //if (AC_QUANTITY > 0) {
+        if (_ac_Index > 0) { //DS60-120 add
+            ac_chargingInfo[0]->Index += _gunIndex;
+        }
+
+        pSysConfig->TotalConnectorCount = _gunIndex;
+        pSysConfig->AcConnectorCount = _acgunIndex;
+        log_info("DC connector Quality = %d, AC connector Quality = %d",
+                 pSysConfig->TotalConnectorCount,
+                 pSysConfig->AcConnectorCount);
+        log_info("Type 0~3 = CHAdeMO, CCS, GB, AC");
+        if (pSysConfig->TotalConnectorCount == 0 &&
+                pSysConfig->AcConnectorCount == 0) {
+            result = false;
+        }
+
+        if (pSysConfig->TotalConnectorCount == 1) {
+            //DS60-120 add
+            bool isFind = false;
+            if (chargingInfo[0]->Type == _Type_Chademo) {
+                if ((bd0_1_status == 0 && bd0_2_status == 1) ||
+                        (bd1_1_status == 0 && bd1_2_status == 1)) {
+                    isFind = true;
+                }
+            } else if (chargingInfo[0]->Type == _Type_CCS_2) {
+                if ((bd0_1_status == 1 && bd0_2_status == 0) ||
+                        (bd1_1_status == 1 && bd1_2_status == 0)) {
+                    isFind = true;
+                }
+            } else if (chargingInfo[0]->Type == _Type_GB) {
+                if ((bd0_1_status == 1 && bd0_2_status == 1) ||
+                        (bd1_1_status == 1 && bd1_2_status == 1)) {
+                    isFind = true;
+                }
+            }
+
+            if (isFind) {
+                //if (strncmp((char *)&pSysConfig->ModelName[7], "0", 1) != 0) {
+                //    if (bd0_1_status == 1 || bd0_2_status == 1) {
+                //        chargingInfo[0]->Evboard_id = 0x01;
+                //    } else if (bd1_1_status == 1 || bd1_2_status == 1) {
+                //        chargingInfo[0]->Evboard_id = 0x02;
+                //    }
+                //} else if (strncmp((char *)&pSysConfig->ModelName[9], "0", 1) != 0) {
+                //    if (bd0_1_status == 1 || bd0_2_status == 1) {
+                //        chargingInfo[0]->Evboard_id = 0x01;
+                //    } else if (bd1_1_status == 1 || bd1_2_status == 1) {
+                //        chargingInfo[0]->Evboard_id = 0x02;
+                //    }
+                //} else {
+                //    chargingInfo[0]->Evboard_id = 0x01;
+                //}
+
+                if (bd0_1_status == 1 || bd0_2_status == 1) {
+                    chargingInfo[0]->Evboard_id = 0x01;
+                }
+
+                if (bd1_1_status == 1 || bd1_2_status == 1) {
+                    chargingInfo[0]->Evboard_id = 0x02;
+                }
+                CheckHwSlotStatusLog(0);
+            } else {
+                result = false;
+            }
+            //chargingInfo[0]->Evboard_id = 0x01;
+            log_info("index = %d, Type = %d, Evboard_id = %d", 0, chargingInfo[0]->Type, chargingInfo[0]->Evboard_id);
+        } else {
+            char type = NO_DEFINE; //DS60-120 add
+
+            // 偵測槍屬於哪個 slot : 可知道插在板上的Slot 0 或 1 是 Chademo 還是 CCS
+            for (uint8_t gunIndex = 0; gunIndex < pSysConfig->TotalConnectorCount; gunIndex++) {
+                if (gunIndex == 0 && bd0_1_status == 0 && bd0_2_status == 1) {
+                    // 與硬體相同 type : Chademo
+                    if (chargingInfo[gunIndex]->Type == _Type_Chademo) {
+                        chargingInfo[gunIndex]->Evboard_id = 0x01;
+                    }
+                } else if (gunIndex == 0 && bd0_1_status == 1 && bd0_2_status == 0) {
+                    // 與硬體相同 type : CCS
+                    if (chargingInfo[gunIndex]->Type == _Type_CCS_2) {
+                        chargingInfo[gunIndex]->Evboard_id = 0x01;
+                    }
+                } else if (gunIndex == 0 && bd0_1_status == 1 && bd0_2_status == 1) {
+                    // 與硬體相同 type : GB
+                    if (chargingInfo[gunIndex]->Type == _Type_GB) {
+                        chargingInfo[gunIndex]->Evboard_id = 0x01;
+                    }
+                }
+
+                if (gunIndex == 1 && bd1_1_status == 0 && bd1_2_status == 1) {
+                    // 與硬體相同 type : Chademo
+                    if (chargingInfo[gunIndex]->Type == _Type_Chademo) {
+                        chargingInfo[gunIndex]->Evboard_id = 0x02;
+                    }
+
+                    if (pSysConfig->TotalConnectorCount == 1) {
+                        chargingInfo[gunIndex]->Evboard_id = 0x01;
+                    }
+                } else if (gunIndex == 1 && bd1_1_status == 1 && bd1_2_status == 0) {
+                    // 與硬體相同 type : CCS
+                    if (chargingInfo[gunIndex]->Type == _Type_CCS_2) {
+                        chargingInfo[gunIndex]->Evboard_id = 0x02;
+                    }
+
+                    if (pSysConfig->TotalConnectorCount == 1) {
+                        chargingInfo[gunIndex]->Evboard_id = 0x01;
+                    }
+                } else if (gunIndex == 1 && bd1_1_status == 1 && bd1_2_status == 1) {
+                    // 與硬體相同 type : GB
+                    if (chargingInfo[gunIndex]->Type == _Type_GB) {
+                        chargingInfo[gunIndex]->Evboard_id = 0x02;
+                    }
+
+                    if (pSysConfig->TotalConnectorCount == 1) {
+                        chargingInfo[gunIndex]->Evboard_id = 0x01;
+                    }
+                }
+
+                log_info("index = %d, Type = %d, Evboard_id = %d",
+                         gunIndex,
+                         chargingInfo[gunIndex]->Type,
+                         chargingInfo[gunIndex]->Evboard_id);
+                CheckHwSlotStatusLog(gunIndex);
+
+                if (type == NO_DEFINE) {
+                    type = chargingInfo[gunIndex]->Type;
+                }
+
+                if (chargingInfo[gunIndex]->Evboard_id == 0x00) {
+                    result = false;
+                }
+            }
+        }
+    } else {
+        // Module Name 不正確 - 告警
+        result = false;
+    }
+#endif //0
+    return result;
+}
+
+void KillTask()
+{
+    ChangeLcmByIndex(_LCM_FIX);
+    system("killall Module_EventLogging");
+    system("killall Module_PrimaryComm");
+    system("killall Module_EvComm");
+    system("killall Module_LcmControl");
+    system("killall Module_InternalComm");
+    //system("killall Module_DoComm");
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+    system("killall Module_PsuComm");
+    system("killall OcppBackend &");
+    system("killall Module_4g &");
+    system("killall Module_Wifi &");
+#endif //!defined DD360 && !defined DD360Audi
+}
+
+void KillTaskExceptPrimary()
+{
+    ChangeLcmByIndex(_LCM_FIX);
+    system("killall Module_EvComm");
+    system("killall Module_InternalComm");
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+    system("killall Module_PsuComm");
+    system("killall Module_4g &");
+    system("killall Module_Wifi &");
+#endif //!defined DD360 && !defined DD360Audi
+}
+
+void KillAllTask()
+{
+    ChangeLcmByIndex(_LCM_FIX);
+    system("killall Module_EventLogging");
+    system("killall Module_PrimaryComm");
+    system("killall Module_EvComm");
+    system("killall Module_LcmControl");
+    system("killall Module_InternalComm");
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+    system("killall Module_PsuComm");
+    system("killall OcppBackend &");
+    system("killall Module_4g &");
+    system("killall Module_Wifi &");
+#else
+    system("killall Module_DoComm");
+#endif //!defined DD360 && !defined DD360Audi
+}
+
+#if 0
+int CheckUpdateProcess(void)
+{
+    //bool isPass = true;
+    uint8_t retSucc = 0;
+    uint8_t retFail = 0;
+    uint8_t index = 0;
+    uint8_t target = 0;
+    char Buf[256];
+    char *new_str = NULL;
+    uint8_t *ptr = NULL;
+    int fd = 0;
+    int CanFd = 0;
+    int uartFd = 0;
+    unsigned int Type = 0;
+    long int MaxLen = 48 * 1024 * 1024, ImageLen = 0;
+    DIR *d;
+    struct dirent *dir;
+
+    d = opendir("/mnt/");
+    if (d) {
+        while ((dir = readdir(d)) != NULL) {
+            if (strcmp(dir->d_name, ".") == 0 || strcmp(dir->d_name, "..") == 0) {
+                continue;
+            }
+
+            new_str = calloc(strlen("/mnt/") + strlen(dir->d_name) + 1, sizeof(char));
+            //new_str[0] = '\0';
+            strcat(new_str, "/mnt/");
+            strcat(new_str, dir->d_name);
+            log_info("%s%s\r\n", "/mnt/", dir->d_name);
+            fd = open(new_str, O_RDONLY);
+            if (fd < 0) {
+                return FAIL;
+            }
+
+            ptr = calloc(MaxLen, sizeof(char)); //-48 is take out the header
+            //memset(ptr, 0xFF, MaxLen);  //-48 is take out the header
+
+            //get the image length
+            ImageLen = read(fd, ptr, MaxLen);
+            for (uint8_t i = 0; i < 16; i++) {
+                if (pSysConfig->ModelName[i] != ptr[i]) {
+                    return FAIL;
+                }
+            }
+
+            log_info("model name check pass. \n");
+            if (ImageLen > 20) {
+                Type = (((unsigned int)ptr[16]) << 24 |
+                        ((unsigned int)ptr[17]) << 16 |
+                        ((unsigned int)ptr[18]) << 8  |
+                        ((unsigned int)ptr[19]));
+                log_info("Typed...%x \r\n", Type);
+
+                switch (Type) {
+                case 0x10000001:
+                case 0x10000002:
+                case 0x10000003:
+                case 0x10000004:
+                case 0x10000005:
+                    if (Upgrade_Flash(Type, new_str, (char *)pSysConfig->ModelName) == PASS) {
+                        //return PASS;
+                        retSucc++;
+                    } else {
+                        log_info("Upgrade %x Failed\r\n", Type);
+                        //return FAIL;
+                        retFail++;
+                    }
+                    break;
+
+                case 0x10000007:
+                case 0x10000008:
+                case 0x10000009:
+                case 0x1000000A:
+                    CanFd = InitCanBus();
+                    if (CanFd > 0) {
+                        for (index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+                            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+                            if (pDcChargingInfo->Type == _Type_CCS_2) {
+                                uint8_t targetID = pDcChargingInfo->Evboard_id;
+
+                                if (pSysConfig->TotalConnectorCount == 1 &&
+                                        ShmDcCommonData->CcsVersion == _CCS_VERSION_CHECK_TAG_V015S0) {
+                                    targetID += 1;
+                                }
+
+                                system("echo 3 > /proc/sys/vm/drop_caches");
+                                sleep(2);
+                                log_info("Upgrade CCS Processing..target id = %d \n", targetID);
+                                if (Upgrade_CCS(CanFd, Type, targetID, new_str, (char *)pSysConfig->ModelName) == FAIL) {
+                                    log_info("Upgrade CCS Failed \n");
+                                    retFail++;
+                                } else {
+                                    retSucc++;
+                                }
+                            }
+                        }
+                        close(CanFd);
+                    }
+                    memset(Buf, 0, sizeof(Buf));
+                    sprintf(Buf, "rm -rvf /mnt/%s", new_str);
+                    system(Buf);
+                    //isPass = true;
+#if 0
+                    CanFd = InitCanBus();
+                    if (CanFd > 0) {
+                        for (index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+                            //if (!isPass) {
+                            //    break;
+                            //}
+                            if (chargingInfo[index]->Type == _Type_CCS_2) {
+                                if (Upgrade_CCS(CanFd, Type, chargingInfo[index]->Evboard_id, new_str, (char *)pSysConfig->ModelName) == FAIL) {
+                                    //isPass = false;
+                                    log_info("Upgrade %x Failed\r\n", Type);
+                                    retFail++;
+                                }
+                            }
+                        }
+                    } else {
+                        log_error("Upgrade CCS open CAN FD fail.\n");
+                        //isPass = false;
+                        return FAIL;
+                    }
+
+                    if (retFail != 0) {
+                        break;
+                    } else {
+                        retSucc++;
+                    }
+                    //return isPass;
+#endif //0
+                    break;
+
+                case 0x10000006:
+                case 0x1000000D:
+                case 0x1000000E:
+                case 0x20000002:
+                case 0x10000014:
+                    // CSU_PRIMARY_CONTROLLER : 0x10000006
+                    target = 0x00;
+
+                    if (Type == 0x10000006) {
+                        target = UPGRADE_PRI;
+                    } else if (Type == 0x1000000D) {
+                        target = UPGRADE_RB;
+                    } else if (Type == 0x1000000E) {
+                        target = UPGRADE_FAN;
+                    } else if (Type == 0x20000002) {
+                        target = UPGRADE_AC;
+                    } else if (Type == 0x10000014) {
+                        target = UPGRADE_LED;
+                    }
+
+                    uartFd = InitComPort(target);
+
+                    if (Upgrade_UART(uartFd, Type, target, new_str, (char *)pSysConfig->ModelName) == PASS) {
+                        //return PASS;
+                        retSucc++;
+                    } else {
+                        log_info("Upgrade %x Failed\r\n", Type);
+                        //return FAIL;
+                        return FAIL;
+                    }
+
+                    if (uartFd > 0) {
+                        close(uartFd);
+                    }
+                    break;
+
+                case 0x1000000B:
+                case 0x1000000C:
+                    // CHAdeMO_BOARD : 0x1000000B, GBT : 0x1000000C
+                    //bool isPass = true;
+                    CanFd = InitCanBus();
+                    if (CanFd > 0) {
+                        for (index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+                            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+                            //if (!isPass) {
+                            //    break;
+                            //}
+
+                            if ((Type == 0x1000000B && pDcChargingInfo->Type == _Type_Chademo) ||
+                                    (Type == 0x1000000C && pDcChargingInfo->Type == _Type_GB)) {
+                                if (Upgrade_CAN(CanFd, Type, pDcChargingInfo->Evboard_id, new_str, (char *)pSysConfig->ModelName) == PASS) {
+                                    //isPass = PASS;
+                                    retSucc++;
+                                } else {
+                                    log_info("Upgrade %x Failed\r\n", Type);
+                                    //isPass = FAIL;
+                                    retFail++;
+                                }
+                            }
+                        }
+                    } else {
+                        log_info("Upgrad FD fail. \n");
+                        //isPass = false;
+                        return FAIL;
+                    }
+
+                    //return isPass;
+                    break;
+                }
+            }
+            free(new_str);
+            free(ptr);
+        }
+    }
+    free(dir);
+    closedir(d);
+
+    if (retFail != 0) {
+        return FAIL;
+    }
+
+    return PASS;
+}
+
+void CreateRfidFork()
+{
+    pid_t rfidRecPid;
+
+    rfidRecPid = fork();
+    log_info("CreateRfidFork = %d\r\n", rfidRecPid);
+    if (rfidRecPid == 0) {
+        while (true) {
+            // 刷卡判斷
+            RFID rfid;
+            if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_NO_CHARGING ||
+                    !pSysConfig->isRFID)
+            {}
+            else if (getRequestCardSN(rfidFd, 0, &rfid)) {
+                //log_info("Get Card..-%s- \n", pSysConfig->UserId);
+                if (strlen((char *)pSysConfig->UserId) == 0) {
+                    if (pSysConfig->RfidCardNumEndian == RFID_ENDIAN_LITTLE) {
+                        switch (rfid.snType) {
+                        case RFID_SN_TYPE_6BYTE:
+                            sprintf((char *) pSysConfig->UserId,
+                                    "%02X%02X%02X%02X%02X%02X",
+                                    rfid.currentCard[0], rfid.currentCard[1],
+                                    rfid.currentCard[2], rfid.currentCard[3],
+                                    rfid.currentCard[4], rfid.currentCard[5]);
+                            break;
+                        case RFID_SN_TYPE_7BYTE:
+                            sprintf((char *) pSysConfig->UserId,
+                                    "%02X%02X%02X%02X%02X%02X%02X",
+                                    rfid.currentCard[0], rfid.currentCard[1],
+                                    rfid.currentCard[2], rfid.currentCard[3],
+                                    rfid.currentCard[4], rfid.currentCard[5],
+                                    rfid.currentCard[6]);
+                            break;
+                        case RFID_SN_TYPE_10BYTE:
+                            sprintf((char *) pSysConfig->UserId,
+                                    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
+                                    rfid.currentCard[0], rfid.currentCard[1],
+                                    rfid.currentCard[2], rfid.currentCard[3],
+                                    rfid.currentCard[4], rfid.currentCard[5],
+                                    rfid.currentCard[6], rfid.currentCard[7],
+                                    rfid.currentCard[8], rfid.currentCard[9]);
+                            break;
+                        case RFID_SN_TYPE_4BYTE:
+                            sprintf((char *) pSysConfig->UserId,
+                                    "%02X%02X%02X%02X",
+                                    rfid.currentCard[0], rfid.currentCard[1],
+                                    rfid.currentCard[2], rfid.currentCard[3]);
+                            break;
+                        }
+                    } else if (pSysConfig->RfidCardNumEndian == RFID_ENDIAN_BIG) {
+                        switch (rfid.snType) {
+                        case RFID_SN_TYPE_6BYTE:
+                            sprintf((char *) pSysConfig->UserId,
+                                    "%02X%02X%02X%02X%02X%02X",
+                                    rfid.currentCard[5], rfid.currentCard[4],
+                                    rfid.currentCard[3], rfid.currentCard[2],
+                                    rfid.currentCard[1], rfid.currentCard[0]);
+                            break;
+                        case RFID_SN_TYPE_7BYTE:
+                            sprintf((char *) pSysConfig->UserId,
+                                    "%02X%02X%02X%02X%02X%02X%02X",
+                                    rfid.currentCard[6], rfid.currentCard[5],
+                                    rfid.currentCard[4], rfid.currentCard[3],
+                                    rfid.currentCard[2], rfid.currentCard[1],
+                                    rfid.currentCard[0]);
+                            break;
+                        case RFID_SN_TYPE_10BYTE:
+                            sprintf((char *) pSysConfig->UserId,
+                                    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
+                                    rfid.currentCard[9], rfid.currentCard[8],
+                                    rfid.currentCard[7], rfid.currentCard[6],
+                                    rfid.currentCard[5], rfid.currentCard[4],
+                                    rfid.currentCard[3], rfid.currentCard[2],
+                                    rfid.currentCard[1], rfid.currentCard[0]);
+                            break;
+                        case RFID_SN_TYPE_4BYTE:
+                            sprintf((char *) pSysConfig->UserId,
+                                    "%02X%02X%02X%02X",
+                                    rfid.currentCard[3], rfid.currentCard[2],
+                                    rfid.currentCard[1], rfid.currentCard[0]);
+                            break;
+                        }
+                    }
+                    log_info("card number = %s\n", pSysConfig->UserId);
+                }
+            }
+            usleep(500000);
+        }
+    }
+}
+#endif //0
+
+void StartSystemTimeoutDet(uint8_t flag)
+{
+    if (pSysInfo->SystemTimeoutFlag != flag) {
+        gettimeofday(&pSysInfo->SystemTimeoutTimer, NULL);
+    }
+    pSysInfo->SystemTimeoutFlag = flag;
+}
+
+void StopSystemTimeoutDet()
+{
+    gettimeofday(&pSysInfo->SystemTimeoutTimer, NULL);
+    pSysInfo->SystemTimeoutFlag = Timeout_None;
+}
+
+void StartGunInfoTimeoutDet(uint8_t gunIndex, uint8_t flag)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (gunIndex < pSysConfig->TotalConnectorCount) {
+        if (pDcChargingInfo->TimeoutFlag != flag) {
+            gettimeofday(&pDcChargingInfo->TimeoutTimer, NULL);
+        }
+        pDcChargingInfo->TimeoutFlag = flag;
+    }
+}
+
+void StopGunInfoTimeoutDet(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (gunIndex < pSysConfig->TotalConnectorCount) {
+        pDcChargingInfo->TimeoutFlag = Timeout_None;
+    }
+}
+
+void CheckConnectionTimeout(void)
+{
+#if defined DD360 || defined DD360Audi || defined DD360ComBox
+    if (gAudiCustInfo->RemoteSetup.ConnectionTimeout != 0) { //Jerry add
+        _connectionTimeout = gAudiCustInfo->RemoteSetup.ConnectionTimeout;
+    } else {
+        _connectionTimeout = CONN_PLUG_TIME_OUT;
+    }
+
+    return;
+#endif //defined DD360 || defined DD360Audi || defined DD360ComBox
+
+    if (system("pidof -s OcppBackend > /dev/null") != 0) {
+        _connectionTimeout = CONN_PLUG_TIME_OUT;
+    } else {
+        if (strcmp((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[ConnectionTimeOut].ItemData, "") != 0) {
+            _connectionTimeout = atoi((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[ConnectionTimeOut].ItemData);
+            if (_connectionTimeout <= 0) {
+                _connectionTimeout = CONN_PLUG_TIME_OUT;
+            }
+        } else {
+            _connectionTimeout = CONN_PLUG_TIME_OUT;
+        }
+    }
+}
+
+void CreateTimeoutFork()
+{
+    pid_t timeoutPid;
+
+    timeoutPid = fork();
+    log_info("CreateTimeoutFork = %d\r\n", timeoutPid);
+    if (timeoutPid == 0) {
+        gettimeofday(&_cmdSubPriority_time, NULL);
+        CheckConnectionTimeout();
+
+        while (1) {
+            if ((GetTimeoutValue(_cmdSubPriority_time) / 1000) > 5000) {
+                CheckConnectionTimeout();
+                gettimeofday(&_cmdSubPriority_time, NULL);
+            }
+
+            //printf("Timeout ***********SystemTimeoutFlag = %d, ********\n", pSysInfo->SystemTimeoutFlag);
+            // 系統
+            switch (pSysInfo->SystemTimeoutFlag) {
+            case Timeout_SelftestChk:
+                if (GetTimeoutValue(pSysInfo->SystemTimeoutTimer) / uSEC_VAL >= SELFTEST_TIMEOUT) {
+                    _SelfTestTimeout();
+                    StopSystemTimeoutDet();
+                    destroySelGun(DESTROY_ALL_SEL); //jerry add
+                }
+                break;
+
+            case Timeout_Authorizing:
+                if (GetTimeoutValue(pSysInfo->SystemTimeoutTimer) / uSEC_VAL >= AUTHORIZE_TIMEOUT) {
+                    _AuthorizedTimeout();
+                    StopSystemTimeoutDet();
+                    destroySelGun(pSysInfo->CurGunSelected);
+                    if (gAudiCustInfo->AuthorStateFromCabinet[pSysInfo->CurGunSelected] == YES) { //DoComm no ask cabinet balance
+                        gAudiCustInfo->AuthorStateFromCabinet[pSysInfo->CurGunSelected] = NO;
+                        pAlarmCode->AlarmEvents.bits.DisconnectedFromDo = ABNORMAL;
+                        log_error("Author timeout restart DoComm\r\n");
+                        system("killall Module_DoComm");
+                        sleep(1);
+                        system("/root/Module_DoComm &");
+                    }
+                }
+                break;
+
+            case Timeout_VerifyFail:
+                if (GetTimeoutValue(pSysInfo->SystemTimeoutTimer) / uSEC_VAL >= AUTHORIZE_FAIL_TIMEOUT) {
+                    _AutoReturnTimeout();
+                    StopSystemTimeoutDet();
+                    destroySelGun(pSysInfo->CurGunSelected);
+                    if (gAudiCustInfo->AuthorStateFromCabinet[pSysInfo->CurGunSelected] == YES) { //DoComm no ask cabinet balance
+                        gAudiCustInfo->AuthorStateFromCabinet[pSysInfo->CurGunSelected] = NO;
+                        pAlarmCode->AlarmEvents.bits.DisconnectedFromDo = ABNORMAL;
+                        log_error("Author timeout restart DoComm\r\n");
+                        system("killall Module_DoComm");
+                        sleep(1);
+                        system("/root/Module_DoComm &");
+                    }
+                }
+                break;
+
+            case Timeout_VerifyComp:
+                if (GetTimeoutValue(pSysInfo->SystemTimeoutTimer) / uSEC_VAL >= AUTHORIZE_COMP_TIMEOUT) {
+                    _AutoReturnTimeout();
+                    StopSystemTimeoutDet();
+                }
+                break;
+
+            case Timeout_WaitPlug:
+                if (GetTimeoutValue(pSysInfo->SystemTimeoutTimer) / uSEC_VAL >= _connectionTimeout) {
+                    _DetectPlugInTimeout();
+                    StopSystemTimeoutDet();
+                    destroySelGun(pSysInfo->CurGunSelected);
+                }
+                break;
+
+            case Timeout_ReturnToChargingGunDet:
+                if (GetTimeoutValue(pSysInfo->SystemTimeoutTimer) / uSEC_VAL >= RETURN_TO_CHARGING_PAGE) {
+#if defined DD360Audi
+                    if (getCurLcmPage() != _LCM_PRE_CHARGE &&
+                            getCurLcmPage() != _LCM_CHARGING &&
+                            getCurLcmPage() != _LCM_COMPLETE) {
+                        destroySelGun(pSysInfo->CurGunSelected); //jerry add
+
+                    }
+#endif //defined DD360Audi
+                    DisplayChargingInfo();
+                    StopSystemTimeoutDet();
+                }
+                break;
+
+            case Timeout_AuthorizingForStop:
+                if (GetTimeoutValue(pSysInfo->SystemTimeoutTimer) / uSEC_VAL >= AUTHORIZE_STOP_TIMEOUT) {
+                    strcpy((char *)pSysConfig->UserId, "");
+                    ClearAuthorizedFlag();
+                    StopSystemTimeoutDet();
+                }
+                break;
+
+            }
+            // 各槍
+            for (uint8_t gun_index = 0; gun_index < pSysConfig->TotalConnectorCount; gun_index++) {
+                pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun_index);
+
+                //printf("Timeout ***********TimeoutFlag = %d, ********\n", chargingInfo[gun_index]->TimeoutFlag);
+                switch (pDcChargingInfo->TimeoutFlag) {
+                case Timeout_Preparing:
+                    if (GetTimeoutValue(pDcChargingInfo->TimeoutTimer) / uSEC_VAL >= GUN_PREPARE_TIMEOUT) {
+                        _PrepareTimeout(gun_index);
+                        StopGunInfoTimeoutDet(gun_index);
+                        destroySelGun(gun_index); //jerry add
+                    }
+                    break;
+
+                case Timeout_EvChargingDet:
+                    if (GetTimeoutValue(pDcChargingInfo->TimeoutTimer) / uSEC_VAL >= GUN_EV_WAIT_TIMEOUT) {
+                        _DetectEvChargingEnableTimeout(gun_index);
+                        StopGunInfoTimeoutDet(gun_index);
+                        destroySelGun(gun_index); //jerry add
+                    }
+                    break;
+
+                case Timeout_EvseChargingDet:
+                    if (GetTimeoutValue(pDcChargingInfo->TimeoutTimer) / uSEC_VAL >= GUN_EVSE_WAIT_TIMEOUT) {
+                        _DetectEvseChargingEnableTimeout(gun_index);
+                        StopGunInfoTimeoutDet(gun_index);
+                        destroySelGun(gun_index); //jerry add
+                    }
+                    break;
+
+                case Timeout_EvseCompleteDet:
+                    if (GetTimeoutValue(pDcChargingInfo->TimeoutTimer) / uSEC_VAL >= GUN_COMP_WAIT_TIMEOUT) {
+                        StopGunInfoTimeoutDet(gun_index);
+                        destroySelGun(gun_index); //jerry add
+                    }
+                    break;
+
+                case Timeout_ForCcsPrechargeDet:
+                    if (GetTimeoutValue(pDcChargingInfo->TimeoutTimer) / uSEC_VAL >= GUN_PRECHARGING_TIMEOUT) {
+                        _CcsPrechargeTimeout(gun_index);
+                        StopGunInfoTimeoutDet(gun_index);
+                        destroySelGun(gun_index); //jerry add
+                    }
+                    break;
+
+                case Timeout_SelectGun: //Jerry add
+                    if (GetTimeoutValue(pDcChargingInfo->TimeoutTimer) / uSEC_VAL >= SEL_GUN_TIMEOUT) {
+                        log_info("Timeout_SelectGun\r\n");
+                        StopGunInfoTimeoutDet(gun_index);
+                        destroySelGun(gun_index); //jerry add
+                    }
+                    break;
+                }
+            }
+            sleep(1);
+        }
+    }
+}
+
+#if 0
+void GetSystemTime()
+{
+    struct timeb csuTime;
+    struct tm *tmCSU;
+
+    ftime(&csuTime);
+    tmCSU = localtime(&csuTime.time);
+    log_info("Time : %04d-%02d-%02d %02d:%02d:%02d \n", tmCSU->tm_year + 1900,
+             tmCSU->tm_mon + 1, tmCSU->tm_mday, tmCSU->tm_hour, tmCSU->tm_min,
+             tmCSU->tm_sec);
+
+//  uint8_t date[14];
+//
+//
+//       //sprintf(&date, "%d", );
+//
+//       date[0] = '0' + ((tmCSU->tm_year + 1900) / 1000 % 10);
+
+//  date[0] = (tmCSU->tm_year + 1900) / 1000 % 10;
+//  date[1] = (tmCSU->tm_year + 1900) / 100 % 10;
+//  date[2] = (tmCSU->tm_year + 1900) / 10 % 10;
+//  date[3] = (tmCSU->tm_year + 1900) / 1 % 10;
+//
+//  date[4] = (tmCSU->tm_mon + 1) / 10 % 10;
+//  date[5] = (tmCSU->tm_mon + 1) / 1 % 10;
+//
+//  date[6] = (tmCSU->tm_mday) / 10 % 10;
+//  date[7] = (tmCSU->tm_mday) / 1 % 10;
+//
+//  date[8] = (tmCSU->tm_hour) / 10 % 10;
+//  date[9] = (tmCSU->tm_hour) / 1 % 10;
+//
+//  date[10] = (tmCSU->tm_min) / 10 % 10;
+//  date[11] = (tmCSU->tm_min) / 1 % 10;
+//
+//  date[12] = (tmCSU->tm_sec) / 10 % 10;
+//  date[13] = (tmCSU->tm_sec) / 1 % 10;
+
+//  log_info("%x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x \n", date[0], date[1], date[2], date[3],
+//          date[4], date[5], date[6], date[7],
+//          date[8], date[9], date[10], date[11],
+//          date[12], date[13]);
+}
+#endif //0
+
+void CheckFactoryConfigFunction(void)
+{
+    char Buf[256] = {0};
+
+    if (pSysInfo->FactoryConfiguration) {
+        sprintf(Buf, "cd /root;./FactoryConfig -m %s %s",
+                pSysConfig->ModelName,
+                pSysConfig->SerialNumber);
+        system(Buf);
+
+        system("rm -f /Storage/OCPP/OCPPConfiguration");
+        system("sync");
+        sleep(5);
+        system("reboot -f");
+        sleep(5);
+        system("reboot -f");
+    }
+}
+
+#if 0
+void CheckFwUpdateFunction()
+{
+    //log_info("pSysInfo->FirmwareUpdate = %d \n", pSysInfo->FirmwareUpdate);
+    if (pSysInfo->FirmwareUpdate == YES) {
+        log_info("ftp : update start. \n");
+        for (uint8_t gun_index = 0; gun_index < pSysConfig->TotalConnectorCount; gun_index++) {
+            setChargerMode(gun_index, MODE_UPDATE);
+        }
+
+        uint8_t updateResult = CheckUpdateProcess();
+
+        if (updateResult == PASS) {
+            log_info("ftp : update complete. \n");
+        } else if (updateResult == MODELNAME_FAIL) {
+            log_info("ftp : model name is none match. \n");
+            KillAllTask();
+            pSysInfo->FirmwareUpdate = NO;
+            sleep(5);
+            system("/usr/bin/run_evse_restart.sh");
+            return;
+        } else {
+            log_info("ftp : update fail. \n");
+        }
+
+        pSysInfo->FirmwareUpdate = NO;
+        sleep(5);
+        system("reboot -f");
+    } else if (ShmOCPP16Data->MsMsg.bits.UpdateFirmwareReq == YES) {
+        ShmOCPP16Data->MsMsg.bits.UpdateFirmwareReq = NO;
+
+        if (strcmp((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "Downloaded") == EQUAL) {
+            log_info("Backend : update start. \n");
+            strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "");
+            strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "Installing");
+            ShmOCPP16Data->SpMsg.bits.FirmwareStatusNotificationReq = YES;
+            KillTask();
+
+            for (uint8_t _index = 0; _index < pSysConfig->TotalConnectorCount; _index++) {
+                setChargerMode(_index, MODE_UPDATE);
+            }
+
+            for (uint8_t _index = 0; _index < pSysConfig->AcConnectorCount; _index++) {
+                pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(_index);
+
+                pAcChargingInfo->SystemStatus = MODE_UPDATE;
+            }
+
+            uint8_t updateResult = CheckUpdateProcess();
+
+            if (updateResult == PASS) {
+                log_info("Backend : update complete. \n");
+                strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "Installed");
+            } else if (updateResult == MODELNAME_FAIL) {
+                log_info("Backend : model name is none match. \n");
+                KillAllTask();
+                strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "InstallationFailed");
+                ShmOCPP16Data->SpMsg.bits.FirmwareStatusNotificationReq = YES;
+                sleep(5);
+                system("/usr/bin/run_evse_restart.sh");
+                return;
+            } else {
+                log_info("Backend : update fail. \n");
+                strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "InstallationFailed");
+            }
+
+            strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "Installed");
+            ShmOCPP16Data->SpMsg.bits.FirmwareStatusNotificationReq = YES;
+            sleep(5);
+            system("reboot -f");
+        }
+    }
+}
+#endif //0
+
+//===============================================
+// Check reservation date is expired
+//===============================================
+int isReservationExpired(uint8_t gun_index)
+{
+    int result = NO;
+    struct tm expiredDate;
+    struct timeb expiredTime;
+
+    if (sscanf((char *) ShmOCPP16Data->ReserveNow[gun_index].ExpiryDate,
+               "%4d-%2d-%2dT%2d:%2d:%2d", &expiredDate.tm_year,
+               &expiredDate.tm_mon, &expiredDate.tm_mday, &expiredDate.tm_hour,
+               &expiredDate.tm_min, &expiredDate.tm_sec) == 6) {
+        expiredDate.tm_year -= 1900;
+        expiredDate.tm_mon -= 1;
+
+        expiredTime.time = mktime(&expiredDate);
+        if (!CheckTimeOut(expiredTime)) {
+            result = YES;
+        }
+    }
+
+    return result;
+}
+
+//===============================================
+// OCPP
+//===============================================
+void CheckOcppStatus(void)
+{
+    bool canReset = true;
+    //bool canHardReset = true; //DS60-120 add
+
+    if (ShmOCPP16Data->SpMsg.bits.BootNotificationConf == YES) {
+        ShmOCPP16Data->SpMsg.bits.BootNotificationConf = NO;
+    }
+
+    if (ShmOCPP16Data->MsMsg.bits.ResetReq == YES) {
+        if (pSysWarning->Level != 2) {
+            for (uint8_t _index = 0; _index < pSysConfig->TotalConnectorCount; _index++) {
+                pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_index);
+
+                if (pDcChargingInfo->SystemStatus != S_IDLE &&
+                        pDcChargingInfo->SystemStatus != S_RESERVATION &&
+                        pDcChargingInfo->SystemStatus != S_MAINTAIN) {
+                    canReset = false;
+                    if (pDcChargingInfo->SystemStatus >= S_REASSIGN &&
+                            pDcChargingInfo->SystemStatus < S_TERMINATING) {
+                        //canHardReset = false;
+                        ChargingTerminalProcess(_index);
+                        //restartFlag = 1;
+                    }
+                }
+            }
+        }
+
+        if (canReset) {
+            ShmOCPP16Data->MsMsg.bits.ResetReq = NO;
+            sprintf((char *)ShmOCPP16Data->Reset.ResponseStatus, "Accepted");
+            if (strcmp((char *)ShmOCPP16Data->Reset.Type, "Hard") == EQUAL) {
+                log_error("****** Hard Reboot ****** \n");
+                ShmOCPP16Data->MsMsg.bits.ResetConf = YES;
+                sleep(3);
+                system("reboot -f");
+            } else if (strcmp((char *)ShmOCPP16Data->Reset.Type, "Soft") == EQUAL) {
+                log_error("****** Soft Reboot ****** \n");
+                ShmOCPP16Data->MsMsg.bits.ResetConf = YES;
+                sleep(3);
+                system("killall OcppBackend &");
+                KillAllTask();
+                system("/usr/bin/run_evse_restart.sh");
+            }
+        }
+    }
+}
+
+void OcppStartTransation(uint8_t gunIndex)
+{
+    uint8_t _OcppGunIndex = gunIndex;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    // 如果有 AC 槍,而現在是 DC 第二把槍進入充電
+    if (pSysConfig->AcConnectorCount == 1 && gunIndex == 1) {
+        _OcppGunIndex = 2;
+    }
+
+    if (strcmp((char *)pDcChargingInfo->StartUserId, "") == EQUAL) {
+        strcpy((char *)ShmOCPP16Data->StartTransaction[_OcppGunIndex].IdTag, (char *)ShmOCPP16Data->StartTransaction[_OcppGunIndex].IdTag);
+    } else {
+        strcpy((char *)ShmOCPP16Data->StartTransaction[_OcppGunIndex].IdTag, (char *)pDcChargingInfo->StartUserId);
+    }
+
+    log_info("IdTag = %s \n", ShmOCPP16Data->StartTransaction[_OcppGunIndex].IdTag);
+    ShmOCPP16Data->CpMsg.bits[_OcppGunIndex].StartTransactionReq = YES;
+}
+
+void OcppStopTransation(uint8_t gunIndex)
+{
+    uint8_t _OcppGunIndex = gunIndex;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    // 如果有 AC 槍,而現在是 DC 第二把槍進入充電
+    if (pSysConfig->AcConnectorCount == 1 && gunIndex == 1) {
+        _OcppGunIndex = 2;
+    }
+
+    if (strcmp((char *)pDcChargingInfo->StartUserId, "") == EQUAL) {
+        strcpy((char *)ShmOCPP16Data->StopTransaction[_OcppGunIndex].IdTag, (char *)ShmOCPP16Data->StopTransaction[_OcppGunIndex].IdTag);
+    } else {
+        strcpy((char *)ShmOCPP16Data->StopTransaction[_OcppGunIndex].IdTag, (char *)pDcChargingInfo->StartUserId);
+    }
+
+    log_info("IdTag = %s \n", ShmOCPP16Data->StopTransaction[_OcppGunIndex].IdTag);
+    ShmOCPP16Data->CpMsg.bits[_OcppGunIndex].StopTransactionReq = YES;
+}
+
+bool OcppRemoteStop(uint8_t gunIndex)
+{
+    uint8_t acDirIndex = pSysConfig->AcConnectorCount;
+
+    // 有 AC 槍的話
+    if (acDirIndex > 0 && gunIndex > 0) {
+        gunIndex += acDirIndex;
+    }
+
+    bool result = ShmOCPP16Data->CsMsg.bits[gunIndex].RemoteStopTransactionReq;
+
+    if (ShmOCPP16Data->CsMsg.bits[gunIndex].RemoteStopTransactionReq == YES) {
+        strcpy((char *)ShmOCPP16Data->StopTransaction[gunIndex].StopReason, "Remote");
+        ShmOCPP16Data->CsMsg.bits[gunIndex].RemoteStopTransactionReq = NO;
+    }
+
+    return result;
+}
+
+bool WifiScheduleStop(uint8_t gunIndex)
+{
+    bool result = false;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    result = pDcChargingInfo->schedule.isTriggerStop;
+    pDcChargingInfo->schedule.isTriggerStop = NO;
+
+    return result;
+}
+
+void OcppRemoteStartChk()
+{
+    if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_NO_CHARGING)
+    {}
+    else if (!isDetectPlugin()) {
+        // 如果有 AC 槍,則固定是第 2 把槍,所以索引固定為 1
+        uint8_t acDirIndex = pSysConfig->AcConnectorCount;
+
+        for (uint8_t ac_index = 0; ac_index < pSysConfig->AcConnectorCount; ac_index++) {
+            pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(ac_index);
+
+            if (ShmOCPP16Data->CsMsg.bits[acDirIndex].RemoteStartTransactionReq == YES) {
+                if (pAcChargingInfo->SystemStatus == S_IDLE ||
+                        pAcChargingInfo->SystemStatus == S_RESERVATION) {
+                    ShmOCPP16Data->CsMsg.bits[acDirIndex].RemoteStartTransactionReq = NO;
+                    pAcChargingInfo->RemoteStartFlag = YES;
+                    pSysInfo->OrderCharging = YES;
+                    //pSysInfo->OrderCharging = DEFAULT_AC_INDEX;
+                    ShmOCPP16Data->CsMsg.bits[pSysConfig->TotalConnectorCount + ac_index].RemoteStartTransactionReq = NO;
+                    DetectPluginStart();
+                    return;
+                }
+                ShmOCPP16Data->CsMsg.bits[acDirIndex].RemoteStartTransactionReq = NO;
+            }
+        }
+
+        uint8_t threeGunIndex = 0;
+        uint8_t dcIndex = 0;
+        bool isGunUsingStatus = false;
+
+        for (uint8_t _index = 0; _index < pSysConfig->TotalConnectorCount; _index++) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_index);
+
+            // 如果有 AC 槍,且 DC 槍也有兩把
+            if (acDirIndex == 1 && _index == 1) {
+                threeGunIndex = 1;
+            }
+
+            if (ShmOCPP16Data->CsMsg.bits[_index + threeGunIndex].RemoteStartTransactionReq == YES) {
+                dcIndex = _index;
+            }
+
+            if (pDcChargingInfo->SystemStatus != S_IDLE) {
+                isGunUsingStatus = true;
+            }
+        }
+
+        // 如果是雙槍單模,只認閒置狀態的槍,如果有預約~ 則預約也算被使用
+        if (isGunUsingStatus && pSysInfo->IsAlternatvieConf) {
+            if (dcIndex == 0) {
+                threeGunIndex = 0;
+            }
+
+            ShmOCPP16Data->CsMsg.bits[dcIndex + threeGunIndex].RemoteStartTransactionReq = NO;
+            return;
+        }
+
+        if (dcIndex == 0) {
+            threeGunIndex = 0;
+        }
+
+        pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(dcIndex);
+
+        if (ShmOCPP16Data->CsMsg.bits[dcIndex + threeGunIndex].RemoteStartTransactionReq == YES) {
+            if (pDcChargingInfo->SystemStatus == S_IDLE ||
+                    pDcChargingInfo->SystemStatus == S_RESERVATION) {
+                pDcChargingInfo->RemoteStartFlag = YES;
+                pSysInfo->OrderCharging = YES;
+                //pSysInfo->OrderCharging = gun_index;
+                ShmOCPP16Data->CsMsg.bits[dcIndex + threeGunIndex].RemoteStartTransactionReq = NO;
+                DetectPluginStart();
+#if defined DD360Audi
+                setSelGunWaitToAuthor(dcIndex); //Jerry add
+#endif //defined DD360Audi
+            }
+            ShmOCPP16Data->CsMsg.bits[dcIndex + threeGunIndex].RemoteStartTransactionReq = NO;
+        }
+    }
+}
+
+void ChkOcppStatus(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (pDcChargingInfo->SystemStatus == S_IDLE &&
+            ShmOCPP16Data->CsMsg.bits[gunIndex].ReserveNowReq == YES) {
+        ShmOCPP16Data->CsMsg.bits[gunIndex].ReserveNowReq = NO;
+        if (isReservationExpired(gunIndex)) {
+            log_info("***************ChkOcppStatus : OcppReservedStatus******************** \n");
+            log_error("***************ChkOcppStatus : OcppReservedStatus******************** \n");
+            pDcChargingInfo->ReservationId = ShmOCPP16Data->ReserveNow[gunIndex].ReservationId;
+            pDcChargingInfo->SystemStatus = S_RESERVATION;
+        }
+        ShmOCPP16Data->CsMsg.bits[gunIndex].ReserveNowConf = YES;
+    }
+
+    if (pDcChargingInfo->SystemStatus == S_RESERVATION &&
+            ShmOCPP16Data->CsMsg.bits[gunIndex].CancelReservationReq == YES) {
+        ShmOCPP16Data->CsMsg.bits[gunIndex].CancelReservationReq = NO;
+        if (isReservationExpired(gunIndex)) {
+            log_info("***************ChkOcppStatus : Cancel OcppReservedStatus******************** \n");
+            log_error("***************ChkOcppStatus : Cancel OcppReservedStatus******************** \n");
+            pDcChargingInfo->ReservationId = 0;
+            pDcChargingInfo->SystemStatus = S_IDLE;
+        }
+        ShmOCPP16Data->CsMsg.bits[gunIndex].CancelReservationConf = YES;
+    }
+
+    if (ShmOCPP16Data->CsMsg.bits[gunIndex].ChangeAvailabilityReq == YES) {
+        log_info("***************ChkOcppStatus : OcppChangeAvailability******************** \n");
+        log_error("***************ChkOcppStatus : OcppChangeAvailability******************** \n");
+        ShmOCPP16Data->CsMsg.bits[gunIndex].ChangeAvailabilityReq = NO;
+        if (strcmp((char *)ShmOCPP16Data->ChangeAvailability[gunIndex].Type, "Operative") == EQUAL) {
+            if (isDb_ready) {
+                DB_Update_Operactive(gunIndex, true);
+            }
+
+            pDcChargingInfo->IsAvailable = YES;
+            if (pDcChargingInfo->SystemStatus == S_IDLE ||
+                    pDcChargingInfo->SystemStatus == S_RESERVATION ||
+                    pDcChargingInfo->SystemStatus == S_MAINTAIN) {
+                setChargerMode(gunIndex, MODE_IDLE);
+            }
+        } else if (strcmp((char *)ShmOCPP16Data->ChangeAvailability[gunIndex].Type, "Inoperative") == EQUAL) {
+            if (isDb_ready) {
+                DB_Update_Operactive(gunIndex, false);
+            }
+
+            pDcChargingInfo->IsAvailable = NO;
+            if (pDcChargingInfo->SystemStatus == S_IDLE ||
+                    pDcChargingInfo->SystemStatus == S_RESERVATION ||
+                    pDcChargingInfo->SystemStatus == S_MAINTAIN) {
+                setChargerMode(gunIndex, MODE_MAINTAIN);
+            }
+        }
+    }
+
+    if (ShmOCPP16Data->CsMsg.bits[gunIndex].UnlockConnectorReq == YES) {
+        ShmOCPP16Data->CsMsg.bits[gunIndex].UnlockConnectorReq = NO;
+        if (pDcChargingInfo->SystemStatus >= S_REASSIGN_CHECK && // DS60-120 add ||
+                pDcChargingInfo->SystemStatus <= S_CHARGING) {
+            // 充電中,需停止充電
+            strcpy((char *)ShmOCPP16Data->StopTransaction[gunIndex].StopReason, "UnlockCommand");
+            ChargingTerminalProcess(gunIndex);
+        }
+        strcpy((char *)ShmOCPP16Data->UnlockConnector[gunIndex].ResponseStatus, "Unlocked");
+        ShmOCPP16Data->CsMsg.bits[gunIndex].UnlockConnectorConf = YES;
+    }
+}
+
+bool CheckBackendChargingTimeout(uint8_t gunIndex)
+{
+    bool result = false;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (pSysConfig->AuthorisationMode == AUTH_MODE_ENABLE) {
+        if (pSysConfig->MaxChargingDuration > 0) {
+            if (pDcChargingInfo->PresentChargedDuration > (pSysConfig->MaxChargingDuration * 60)) {
+                result = true;
+            }
+        }
+    } else if (pSysConfig->AuthorisationMode == AUTH_MODE_DISABLE) {
+        // 隨插即充電的要看 offline
+        if (pSysConfig->OfflineMaxChargeDuration > 0) {
+            if (pDcChargingInfo->PresentChargedDuration > (pSysConfig->OfflineMaxChargeDuration * 60)) {
+                result = true;
+            }
+        }
+    }
+
+    return result;
+}
+
+bool CheckBackendChargingEnergy(uint8_t gunIndex)
+{
+    bool result = false;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (pSysConfig->AuthorisationMode == AUTH_MODE_ENABLE) {
+        if (pSysConfig->MaxChargingEnergy > 0) {
+            if (pDcChargingInfo->PresentChargedEnergy > pSysConfig->MaxChargingEnergy) {
+                result = true;
+            }
+        }
+    } else if (pSysConfig->AuthorisationMode == AUTH_MODE_DISABLE) {
+        // 隨插即充電的要看 offline
+        if (pSysConfig->OfflineMaxChargeEnergy > 0) {
+            if (pDcChargingInfo->PresentChargedEnergy > (pSysConfig->OfflineMaxChargeEnergy)) {
+                result = true;
+            }
+        }
+    }
+
+    return result;
+}
+
+void InformOcppErrOccur(uint8_t codeType)
+{
+    char _error[25];
+
+    switch (codeType) {
+    case 4: strcpy(_error, "InternalError"); break;
+    case 6: strcpy(_error, "NoError"); break;
+    case 7: strcpy(_error, "OtherError"); break;
+    case 13: strcpy(_error, "UnderVoltage"); break;
+    case 14: strcpy(_error, "OverVoltage"); break;
+    }
+
+    for (uint8_t gun_index = 0; gun_index < pSysConfig->TotalConnectorCount; gun_index++) {
+        strcpy((char *)ShmOCPP16Data->StatusNotification[gun_index].ErrorCode, _error);
+    }
+}
+
+#if 0
+//===============================================
+// SQLite3 related routine
+//===============================================
+int DB_Open(sqlite3 *db)
+{
+    int result = PASS;
+    char *errMsg = NULL;
+    char *createRecordSql = "CREATE TABLE IF NOT EXISTS charging_record("
+                            "idx integer primary key AUTOINCREMENT, "
+                            "reservationId text, "
+                            "transactionId text, "
+                            "startMethod text, "
+                            "userId text, "
+                            "dateTimeStart text, "
+                            "dateTimeStop text,"
+                            "socStart text, "
+                            "socStop text, "
+                            "chargeEnergy text, "
+                            "stopReason text"
+                            ");";
+
+    /*char *createCfgSql = "CREATE TABLE IF NOT EXISTS `config` ( "
+                         "`idx` INTEGER PRIMARY KEY AUTOINCREMENT, "
+                         "`IsAvailable` TEXT NOT NULL, "
+                         "`connector` INTEGER NOT NULL, "
+                         "`val` TEXT NOT NULL, unique(IsAvailable,connector) on conflict replace);";
+    */
+    //DS60-120 add
+    char *createCfgSql = "CREATE TABLE IF NOT EXISTS `config` ( "
+                         "`idx` INTEGER PRIMARY KEY AUTOINCREMENT, "
+                         "`item` TEXT NOT NULL, "
+                         "`connector` INTEGER NOT NULL, "
+                         "`val` TEXT NOT NULL, unique(item,connector) on conflict replace);";
+
+    char *createrecordSql = "CREATE TABLE IF NOT EXISTS `event_record` ( "
+                            "`idx` INTEGER PRIMARY KEY AUTOINCREMENT, "
+                            "`occurDatetime` TEXT NOT NULL, "
+                            "`statusCode` TEXT NOT NULL, unique(occurDatetime,statusCode) on conflict replace);";
+
+    char *createrebootSql = "CREATE TABLE IF NOT EXISTS `reboot_record` ( "
+                            "`idx` INTEGER PRIMARY KEY AUTOINCREMENT, "
+                            "`rebootDatetime` TEXT NOT NULL, unique(rebootDatetime) on conflict replace);";
+
+    if (sqlite3_open(DB_FILE, &db)) {
+        result = FAIL;
+        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(db));
+        sqlite3_close(db);
+    } else {
+        log_info( "Local charging record database open successfully.\r\n");
+
+        if (sqlite3_exec(db, createRecordSql, 0, 0, &errMsg) != SQLITE_OK) {
+            result = FAIL;
+            log_info( "Create local charging record table error message: %s\n", errMsg);
+        } else {
+            log_info( "Opened local charging record table successfully\n");
+        }
+
+        if (sqlite3_exec(db, createCfgSql, 0, 0, &errMsg) != SQLITE_OK) {
+            result = FAIL;
+            log_info( "Create local config table error message: %s\n", errMsg);
+        } else {
+            log_info( "Opened local config table successfully\n");
+        }
+
+        //DS60-120
+        if (sqlite3_exec(db, createrecordSql, 0, 0, &errMsg) != SQLITE_OK) {
+            result = FAIL;
+            log_info( "Create local record table error message: %s\n", errMsg);
+        } else {
+            log_info( "Opened local record table successfully\n");
+        }
+
+        if (sqlite3_exec(db, createrebootSql, 0, 0, &errMsg) != SQLITE_OK) {
+            result = FAIL;
+            log_info( "Create reboot record table error message: %s\n", errMsg);
+        } else {
+            log_info( "Opened reboot record table successfully\n");
+        }
+        //-----
+
+        sqlite3_close(db);
+    }
+
+    return result;
+}
+
+int DB_Insert_Record(sqlite3 *db, int gun_index)
+{
+    int result = PASS;
+    char *errMsg = NULL;
+    char insertSql[1024];
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun_index);
+
+    sprintf(insertSql, "insert into charging_record(reservationId, transactionId, startMethod, userId, dateTimeStart, dateTimeStop, socStart, socStop, chargeEnergy, stopReason) "
+            "values('%d', '%d', '%d', '%s', '%s', '%s', '%d', '%d', '%f', '%s');",
+            pDcChargingInfo->ReservationId, //DS60-120 add
+            ShmOCPP16Data->StartTransaction[gun_index].ResponseTransactionId,
+            pDcChargingInfo->StartMethod,
+            pDcChargingInfo->StartUserId,
+            pDcChargingInfo->StartDateTime,
+            pDcChargingInfo->StopDateTime,
+            pDcChargingInfo->EvBatteryStartSoc,
+            pDcChargingInfo->EvBatterySoc,
+            pDcChargingInfo->PresentChargedEnergy,
+            //DS60-120 remove
+            //pSysInfo->AcChargingData[gun_index].ReservationId,
+            //ShmOCPP16Data->StartTransaction[gun_index].ResponseTransactionId,
+            //pSysInfo->AcChargingData[gun_index].StartMethod,
+            //pSysInfo->AcChargingData[gun_index].StartUserId,
+            //pSysInfo->AcChargingData[gun_index].StartDateTime,
+            //pSysInfo->AcChargingData[gun_index].StopDateTime,
+            //pSysInfo->AcChargingData[gun_index].EvBatterySoc,
+            //pSysInfo->AcChargingData[gun_index].EvBatterySoc,
+            //pSysInfo->AcChargingData[gun_index].PresentChargedEnergy,
+            ShmOCPP16Data->StopTransaction[gun_index].StopReason);
+
+    //if (sqlite3_open("/Storage/ChargeLog/localCgargingRecord.db", &db)) {
+    if (sqlite3_open(DB_FILE, &db)) { //DS60-120 add
+        result = FAIL;
+        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(db));
+        sqlite3_close(db);
+    } else {
+        log_info( "Local charging record database open successfully.\r\n");
+        if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
+            result = FAIL;
+            log_info( "Insert local charging record error message: %s\n", errMsg);
+        } else {
+            log_info( "Insert local charging record successfully\n");
+        }
+
+        //DS60-120 add
+        sprintf(insertSql, "delete from charging_record where idx < (select idx from charging_record order by idx desc limit 1)-2000;");
+        if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
+            result = FAIL;
+            log_info( "delete local charging error message: %s\n", errMsg);
+        } else {
+            log_info( "delete local charging record successfully\n");
+        }
+
+        sqlite3_close(db);
+    }
+
+    return result;
+}
+
+int DB_Update_Operactive(sqlite3 *db, uint8_t gun_index, uint8_t IsAvailable)
+{
+    uint8_t result = false;
+    char *errMsg = NULL;
+    char sqlStr[1024];
+    srand(time(NULL));
+
+    if (sqlite3_open(DB_FILE, &db)) {
+        result = FAIL;
+        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(db));
+        sqlite3_close(db);
+    } else {
+        log_info( "Local charging record database open successfully (%d).\r\n", IsAvailable);
+
+        //sprintf(sqlStr, "insert or replace into config (IsAvailable, connector, val) values('IsAvailable', %d, %d);", gun_index, IsAvailable);
+        sprintf(sqlStr, "insert or replace into config (item, connector, val) values('IsAvailable', %d, %d);", gun_index, IsAvailable); //DS60-120 add
+        log_info("sqlStr= %s\r\n", sqlStr);
+        if (sqlite3_exec(db, sqlStr, 0, 0, &errMsg) != SQLITE_OK) {
+            result = FAIL;
+            log_info( "update config error message: %s\n", errMsg);
+        } else {
+            log_info("update connector-%d config item isOperactive to %d\r\n", gun_index, IsAvailable);
+        }
+
+        sqlite3_close(db);
+    }
+
+    return result;
+}
+
+int DB_Get_Operactive(sqlite3 *db, uint8_t gun_index)
+{
+    uint8_t result = true;
+    char *errMsg = NULL;
+    char sqlStr[1024];
+    char **rs;
+    int  rows, cols;
+
+    //sprintf(sqlStr, "select * from config where IsAvailable='IsAvailable' and connector=%d;", gun_index);
+    sprintf(sqlStr, "select * from config where item='IsAvailable' and connector=%d;", gun_index); //DS60-120 add
+    //DEBUG_INFO("sqlStr= %s\r\n", sqlStr);
+
+    if (sqlite3_open(DB_FILE, &db)) {
+        result = FAIL;
+        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(db));
+        sqlite3_close(db);
+    } else {
+        log_info( "Local config query database open successfully.\r\n");
+        sqlite3_get_table(db, sqlStr, &rs, &rows, &cols, &errMsg);
+        if (rows > 0) {
+            for (int idxRow = 1; idxRow <= rows; idxRow++) {
+                if (strcmp(rs[(idxRow * cols) + 3], "0") == 0) {
+                    result = false;
+                }
+                log_info("Query connector-%d isOperactive: %s\r\n", gun_index, rs[(idxRow * cols) + 3]);
+            }
+        } else {
+            log_info("Query connector-%d fail, set default value to operactive.\r\n", gun_index);
+        }
+
+        sqlite3_free_table(rs);
+        sqlite3_close(db);
+    }
+
+    return result;
+}
+
+int DB_Reboot_Record(sqlite3 *db)
+{
+    int result = PASS;
+    char *errMsg = NULL;
+    char insertSql[256];
+
+    sprintf(insertSql, "insert into reboot_record(rebootDatetime) values(CURRENT_TIMESTAMP);");
+
+    if (sqlite3_open(DB_FILE, &db)) {
+        result = FAIL;
+        log_info( "Can't open database: %s\n", sqlite3_errmsg(db));
+        sqlite3_close(db);
+    } else {
+        log_info( "Local charging record database open successfully.\n");
+        if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
+            result = FAIL;
+            log_info( "Insert reboot record error message: %s\n", errMsg);
+        } else {
+            log_info( "Insert reboot record successfully\n");
+        }
+
+        sprintf(insertSql, "delete from reboot_record where idx < (select idx from charging_record order by idx desc limit 1)-2000;");
+        if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
+            result = FAIL;
+            log_info( "delete reboot record error message: %s\n", errMsg);
+        } else {
+            log_info( "delete reboot record successfully\n");
+        }
+
+        sqlite3_close(db);
+    }
+
+    return result;
+}
+#endif //0
+
+//===============================================
+// Config process
+//===============================================
+void AddPlugInTimes(uint8_t gunIndex)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if (pDcChargingInfo->Type == _Type_Chademo) {
+        pSysConfig->ChademoPlugInTimes += 1;
+    } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+        pSysConfig->Ccs2PlugInTimes += 1;
+    } else if (pDcChargingInfo->Type == _Type_GB) {
+        pSysConfig->GbPlugInTimes += 1;
+    }
+}
+
+void ChangeStartOrStopDateTime(uint8_t isStart, uint8_t gunIndex)
+{
+    char cmdBuf[32];
+    struct timeb csuTime;
+    struct tm *tmCSU;
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    ftime(&csuTime);
+    tmCSU = localtime(&csuTime.time);
+
+    sprintf(cmdBuf, "%04d-%02d-%02d %02d:%02d:%02d", tmCSU->tm_year + 1900,
+            tmCSU->tm_mon + 1, tmCSU->tm_mday, tmCSU->tm_hour, tmCSU->tm_min,
+            tmCSU->tm_sec);
+    if (isStart) {
+        strcpy((char *)pDcChargingInfo->StartDateTime, cmdBuf);
+    } else {
+        strcpy((char *)pDcChargingInfo->StopDateTime, cmdBuf);
+    }
+}
+
+#if 0
+void zipLogFiles()
+{
+    const char *logPath = "/Storage/SystemLog";
+    // 獲取目錄
+    DIR *pDir = opendir(logPath);
+    if (pDir != NULL) {
+        struct timeb csuTime;
+        struct tm *tmCSU;
+
+        ftime(&csuTime);
+        tmCSU = localtime(&csuTime.time);
+//      log_info("Time : %04d-%02d-%02d %02d:%02d:%02d \n", tmCSU->tm_year + 1900,
+//          tmCSU->tm_mon + 1, tmCSU->tm_mday, tmCSU->tm_hour, tmCSU->tm_min,
+//          tmCSU->tm_sec);
+
+        // Read items inside the folder
+        struct dirent *pEntry = NULL;
+        while ((pEntry = readdir(pDir)) != NULL) {
+            if (strcmp(pEntry->d_name, ".") != 0 &&
+                    strcmp(pEntry->d_name, "..") != 0 &&
+                    strncmp(pEntry->d_name, "[", 1) == 0 &&
+                    strstr(pEntry->d_name, "tar") < 0) {
+                char yearC[5];
+                unsigned short year = 0;
+                char monthC[3];
+                unsigned short month = 0;
+
+                yearC[4] = '\0';
+                strncpy(yearC, pEntry->d_name + 1, 4);
+                monthC[2] = '\0';
+                strncpy(monthC, pEntry->d_name + 6, 2);
+
+                year = atoi(yearC);
+                month = atoi(monthC);
+
+                if (year != 0) {
+                    if (year < tmCSU->tm_year + 1900 ||
+                            (year >= tmCSU->tm_year + 1900 && month < tmCSU->tm_mon + 1)) {
+                        log_info("tar file name : %s \n", pEntry->d_name);
+                        char file[256];
+
+                        memset(file, 0x00, sizeof(file));
+                        strcat(file, "tar zcvf ");
+                        strcat(file, logPath);
+                        strncat(file, "/", 1);
+                        strcat(file, pEntry->d_name);
+                        strcat(file, ".tar");
+                        strncat(file, " ", 1);
+                        strcat(file, logPath);
+                        strncat(file, "/", 1);
+                        strcat(file, pEntry->d_name);
+                        log_info("zip = %s \n", file);
+                        system(file);
+                    }
+                }
+            }
+        }
+    }
+    // Close folder
+    closedir(pDir);
+}
+#endif //0
+
+void ChangeGunSelectByIndex(uint8_t sel)
+{
+    pSysInfo->CurGunSelected = sel;
+    pSysInfo->CurGunSelectedByAc = NO_DEFINE;
+}
+
+void CheckIsAlternatvieByModelName()
+{
+    // 黑白機 ?
+    /*if (strcmp((char *)pSysConfig->ModelName, "DWWU301J0UT1PH") == EQUAL ||
+            strcmp((char *)pSysConfig->ModelName, "DWYE301J0ET1PH") == EQUAL ||
+            strcmp((char *)pSysConfig->ModelName, "DSYE301J3EW2PH") == EQUAL ||
+            strcmp((char *)pSysConfig->ModelName, "DWYC301J0UW1PH") == EQUAL) {
+      */
+    if (pSysConfig->ModelName[1] == 'W') { //DS60-120
+        // 壁掛
+        pSysInfo->IsAlternatvieConf = YES;
+    } else {
+        pSysInfo->IsAlternatvieConf = NO;
+    }
+}
+
+void StopProcessingLoop()
+{
+    for (;;) {
+        CheckFactoryConfigFunction();
+        CheckFwUpdateFunction();
+        if (pSysWarning->Level == 2) {
+            ChkPrimaryStatus();
+            if (pSysWarning->Level == 0) {
+                log_info("Soft reboot for retry self-tets (Primary). \n");
+                KillAllTask();
+                sleep(3);
+                system("/usr/bin/run_evse_restart.sh");
+                return;
+            }
+        }
+        sleep(1);
+    }
+}
+
+#if 0
+int InitWatchDog(void)
+{
+    int fd;
+    system("/usr/bin/fuser -k /dev/watchdog");
+    sleep(1);
+    system("echo V > /dev/watchdog");
+    sleep(1);
+    fd = open("/dev/watchdog", O_RDWR);
+
+    if (fd <= 0) {
+        log_error("System watch dog initial fail.\r\n");
+    }
+    return fd;
+}
+
+void CreateWatchdog(void)
+{
+    if (pSysConfig->SwitchDebugFlag == NO) {
+        wtdFd = InitWatchDog();
+
+        if (wtdFd < 0) {
+            pAlarmCode->AlarmEvents.bits.CsuInitFailed = 1;
+        }
+    }
+}
+#endif //0
+
+bool IsConnectorWholeIdle()
+{
+    bool result = true;
+
+    for (uint8_t count = 0; count < pSysConfig->TotalConnectorCount; count++) {
+        pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(count);
+
+        if (pDcChargingInfo->SystemStatus != S_IDLE &&
+                pDcChargingInfo->SystemStatus != S_RESERVATION) {
+            result = false;
+            break;
+        }
+    }
+
+    for (uint8_t count = 0; count < pSysConfig->AcConnectorCount; count++) {
+        pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(count);
+
+        if (pAcChargingInfo->SystemStatus != S_IDLE &&
+                pAcChargingInfo->IsErrorOccur == NO) {
+            result = false;
+            break;
+        }
+    }
+
+    return result;
+}
+
+void ClearAlarmCodeWhenAcOff()
+{
+    if (!pSysInfo->AcContactorStatus) {
+        pAlarmCode->AlarmEvents.bits.PsuNoResource = NO;
+    }
+}
+
+//==========================================
+// Check task processing
+//==========================================
+void CheckTask()
+{
+    /*+++ 20200908, vern, disable it for DD360 +++*/
+#if 0
+    if (pSysConfig->ModelName[10] == 'T') {
+        if (system("pidof -s Module_4g > /dev/null") != 0) {
+            log_error("Module_4g not running, restart it.\r\n");
+            system("/root/Module_4g &");
+        }
+    } else if (pSysConfig->ModelName[10] == 'W') {
+        if (system("pidof -s Module_Wifi > /dev/null") != 0) {
+            log_error("Module_Wifi not running, restart it.\r\n");
+            system("/root/Module_Wifi &");
+        }
+    }
+
+    if (strcmp((char *)pSysConfig->OcppServerURL, "") != EQUAL &&
+            strcmp((char *)pSysConfig->ChargeBoxId, "") != EQUAL) {
+        if (system("pidof -s OcppBackend > /dev/null") != 0) {
+            log_error("OcppBackend not running, restart it.\r\n");
+            system("/root/OcppBackend &");
+        }
+    }
+#endif
+    /*--- 20200908, vern, disable it for DD360 ---*/
+    if (system("pidof -s Module_ProduceUtils > /dev/null") != 0) {
+        log_error("Module_ProduceUtils not running, restart it.\r\n");
+        system ("/root/Module_ProduceUtils &");
+    }
+}
+
+void InitialDHCP()
+{
+    char tmpbuf[256] = {0};
+
+    system("pgrep -f \"udhcpc -i eth0\" | xargs kill");
+    sprintf(tmpbuf, "/sbin/udhcpc -i eth0 -x hostname:CSU3_%s -s /root/dhcp_script/eth0.script > /dev/null &",
+            pSysConfig->SystemId);
+    system(tmpbuf);
+}
+
+//==========================================
+// Check Smart Charging Profile
+//==========================================
+int GetStartScheduleTime(uint8_t *time)
+{
+    int result = -1;
+    struct tm tmScheduleStart;
+    struct timeb tbScheduleStart;
+
+    if ((sscanf((char *)time, "%4d-%2d-%2dT%2d:%2d:%2d", &tmScheduleStart.tm_year, &tmScheduleStart.tm_mon, &tmScheduleStart.tm_mday, &tmScheduleStart.tm_hour, &tmScheduleStart.tm_min, &tmScheduleStart.tm_sec) == 6)) {
+        tmScheduleStart.tm_year -= 1900;
+        tmScheduleStart.tm_mon -= 1;
+        tbScheduleStart.time = mktime(&tmScheduleStart);
+        tbScheduleStart.millitm = 0;
+
+        result = DiffTimebWithNow(tbScheduleStart) / 1000;
+    }
+
+    return result;
+}
+
+void CheckSmartChargeProfile(uint8_t _index)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_index);
+
+    if (ShmOCPP16Data->CSUMsg.bits[_index].ChargingProfileConf == YES) {
+        // Get Charging Profile
+        ShmOCPP16Data->CSUMsg.bits[_index].ChargingProfileConf = NO;
+        if (strcmp((char *)ShmOCPP16Data->SmartChargingProfile[_index].ChargingProfileKind, "Absolute") == EQUAL &&
+                ShmOCPP16Data->SmartChargingProfile[_index].ChargingProfileId == YES //DS60-120 add
+           ) {
+            int _time = GetStartScheduleTime(ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.StartSchedule);
+            uint8_t _startCount = NO_DEFINE;
+            uint8_t _maxCount = ARRAY_SIZE(ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod);
+
+            for (uint8_t _count = 0; _count < _maxCount; _count++) {
+                // 預設最小輸出電流 (MIN_OUTPUT_CUR) A
+                if (_time >= ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_count].StartPeriod) {
+                    if ((_count == 0 && ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_count].Limit >= MIN_OUTPUT_CUR) ||
+                            ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_count].Limit > MIN_OUTPUT_CUR) {
+                        _startCount = _count;
+                    }
+                }
+            }
+
+            log_info("_startCount = %d \n", _startCount);
+            if (_startCount < _maxCount) {
+                //DS60-120 add
+                log_info("Profile Limit = %f \n", ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_startCount].Limit);
+                pDcChargingInfo->ChargingProfilePower = ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_startCount].Limit * AC_OUTPUT_VOL;
+                if (pDcChargingInfo->EvBatterytargetVoltage > 0 && pDcChargingInfo->PresentChargingVoltage > 0) {
+                    pDcChargingInfo->ChargingProfileCurrent = (pDcChargingInfo->ChargingProfilePower / pDcChargingInfo->PresentChargingVoltage) * 10;
+                } else {
+                    pDcChargingInfo->ChargingProfileCurrent = 0;
+                }
+
+                //DS60-120 remove
+                //log_info("*********Limit = %f \n", ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_startCount].Limit);
+                //pDcChargingInfo->ChargingProfileCurrent = ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_startCount].Limit * 10;
+                //pDcChargingInfo->ChargingProfilePower = ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_startCount].Limit * pDcChargingInfo->EvBatterytargetVoltage / 100;
+
+                //pDcChargingInfo->ChargingProfilePower = ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[_startCount].Limit * AC_OUTPUT_VOL;
+//              if ((pDcChargingInfo->EvBatterytargetVoltage * 10) > 0)
+//              {
+//                  pDcChargingInfo->ChargingProfileCurrent = pDcChargingInfo->ChargingProfilePower / (pDcChargingInfo->EvBatterytargetVoltage * 10);
+//              }
+            } else {
+                pDcChargingInfo->ChargingProfilePower = -1;
+                pDcChargingInfo->ChargingProfileCurrent = -1;
+            }
+        } else {
+            pDcChargingInfo->ChargingProfilePower = -1;
+            pDcChargingInfo->ChargingProfileCurrent = -1;
+        }
+
+        log_info("ChargingProfilePower = %f \n", pDcChargingInfo->ChargingProfilePower);
+        log_info("ChargingProfileCurrent = %f \n", pDcChargingInfo->ChargingProfileCurrent);
+    }
+//
+//      printf("-------------Schedule------------\n");
+//      printf("index = %d \n", _index);
+//      printf("StartSchedule = %s \n", ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.StartSchedule);
+//      printf("ChargingRateUnit = %s \n", ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingRateUnit);
+//      printf("----------SchedulePeriod---------\n");
+//      for (int v = 0; v < 10; v++)
+//      {
+//          printf("StartPeriod = %d \n", ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[v].StartPeriod);
+//          printf("Limit = %f \n", ShmOCPP16Data->SmartChargingProfile[_index].ChargingSchedule.ChargingSchedulePeriod[v].Limit);
+//      }
+//      printf("---------------------------------\n");
+}
+
+void ChargingProfileFlat(uint8_t _index)
+{
+    if (ShmOCPP16Data->CSUMsg.bits[_index].ChargingProfileConf == NO) {
+        if (ShmOCPP16Data->CSUMsg.bits[_index].ChargingProfileReq == NO) {
+            ShmOCPP16Data->CSUMsg.bits[_index].ChargingProfileReq = YES;
+        }
+    }
+}
+
+void CheckReturnToChargingConn()
+{
+    if ((pSysConfig->TotalConnectorCount + pSysConfig->AcConnectorCount) > 1 &&
+            pSysInfo->PageIndex != _LCM_AUTHORIZING &&
+            pSysInfo->PageIndex != _LCM_AUTHORIZ_FAIL &&
+            pSysInfo->PageIndex != _LCM_AUTHORIZ_COMP &&
+            pSysInfo->PageIndex != _LCM_WAIT_FOR_PLUG) {
+        bool isReturnTimeout = false;
+
+        for (uint8_t count = 0; count < pSysConfig->TotalConnectorCount; count++) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(count);
+
+            // 如果選的 DC 槍在充電~ 則 DC 槍不改變
+            if (count == pSysInfo->CurGunSelected) {
+                if ((pDcChargingInfo->SystemStatus >= S_REASSIGN_CHECK && pDcChargingInfo->SystemStatus <= S_COMPLETE) ||
+                        (pDcChargingInfo->SystemStatus >= S_CCS_PRECHARGE_ST0 && pDcChargingInfo->SystemStatus <= S_CCS_PRECHARGE_ST1)) {
+                    isReturnTimeout = false;
+                    break;
+                }
+            } else if (count != pSysInfo->CurGunSelected) {
+                if ((pDcChargingInfo->SystemStatus >= S_REASSIGN_CHECK && pDcChargingInfo->SystemStatus <= S_COMPLETE) ||
+                        (pDcChargingInfo->SystemStatus >= S_CCS_PRECHARGE_ST0 && pDcChargingInfo->SystemStatus <= S_CCS_PRECHARGE_ST1)) {
+                    isReturnTimeout = true;
+                    StartSystemTimeoutDet(Timeout_ReturnToChargingGunDet);
+                }
+            }
+        }
+
+        // AC 槍
+        if (!isReturnTimeout && pSysConfig->AcConnectorCount > 0) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(pSysInfo->CurGunSelected);
+            pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(0);
+
+            // 沒有選中 AC,且 AC 在充電中
+            if (pSysInfo->CurGunSelectedByAc == NO_DEFINE &&
+                    (pAcChargingInfo->SystemStatus >= S_PREPARNING &&
+                     pAcChargingInfo->SystemStatus <= S_COMPLETE)) {
+                // 當前 DC 充電槍在 idle 狀態
+                if (pDcChargingInfo->SystemStatus == S_IDLE ||
+                        pDcChargingInfo->SystemStatus == S_RESERVATION) {
+                    isReturnTimeout = true;
+                    StartSystemTimeoutDet(Timeout_ReturnToChargingGunDet);
+                }
+            } else if (pSysInfo->CurGunSelectedByAc == DEFAULT_AC_INDEX &&
+                       ((pDcChargingInfo->SystemStatus >= S_REASSIGN_CHECK &&
+                         pDcChargingInfo->SystemStatus <= S_COMPLETE) ||
+                        (pDcChargingInfo->SystemStatus >= S_CCS_PRECHARGE_ST0 &&
+                         pDcChargingInfo->SystemStatus <= S_CCS_PRECHARGE_ST1))) {
+                // 當前 DC 充電槍在 idle 狀態
+                if (pAcChargingInfo->SystemStatus == S_IDLE ||
+                        pAcChargingInfo->SystemStatus == S_RESERVATION) {
+                    isReturnTimeout = true;
+                    StartSystemTimeoutDet(Timeout_ReturnToChargingGunDet);
+                }
+            }
+        }
+
+        if (!isReturnTimeout) {
+            StopSystemTimeoutDet();
+        }
+    }
+}
+
+bool GetStartChargingByAlterMode(uint8_t _gun)
+{
+    bool result = true;
+
+    if (pSysConfig->TotalConnectorCount == 2 &&
+            pSysInfo->IsAlternatvieConf == YES) {
+        for (uint8_t _select = 0; _select < pSysConfig->TotalConnectorCount; _select++) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_select);
+
+            if (_select != _gun) {
+                if (pDcChargingInfo->SystemStatus != S_IDLE &&
+                        pDcChargingInfo->SystemStatus != S_RESERVATION) {
+                    result = false;
+                    break;
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+void TheEndCharging(uint8_t gun_index)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun_index);
+
+    ftime(&endChargingTime[gun_index]);
+
+    if (pDcChargingInfo->PresentChargedDuration != 0) {
+        pDcChargingInfo->PresentChargedDuration = DiffTimeb(startChargingTime[gun_index], endChargingTime[gun_index]);
+    }
+
+    pDcChargingInfo->isRemoteStart = NO;
+
+    StopGunInfoTimeoutDet(gun_index);
+    StartGunInfoTimeoutDet(gun_index, Timeout_EvseCompleteDet);
+    ChangeStartOrStopDateTime(NO, gun_index);
+    DB_Insert_Record(gun_index);
+}
+
+void UpdateErrorCodeToOcpp(uint8_t index)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index);
+
+    //log_info("%d = ConnectorAlarmCode = %s\r\n", index, (char *)chargingInfo[index]->ConnectorAlarmCode);
+    //log_info("%d = EvConnAlarmCode = %s\r\n", index, (char *)chargingInfo[index]->EvConnAlarmCode);
+    if (strcmp((char *)pDcChargingInfo->ConnectorAlarmCode, "") != EQUAL) {
+        //if (strlen((char *)pDcChargingInfo->ConnectorAlarmCode) == EQUAL) {
+        strcpy((char *)ShmOCPP16Data->StatusNotification[index].ErrorCode, "InternalError");
+        strcpy((char *)ShmOCPP16Data->StatusNotification[index].VendorErrorCode, (char *)pDcChargingInfo->ConnectorAlarmCode);
+    } else if (strcmp((char *)pDcChargingInfo->EvConnAlarmCode, "") != EQUAL) {
+        //} else if (strlen((char *)pDcChargingInfo->EvConnAlarmCode) == EQUAL) {
+        strcpy((char *)ShmOCPP16Data->StatusNotification[index].ErrorCode, "OtherError");
+        strcpy((char *)ShmOCPP16Data->StatusNotification[index].VendorErrorCode, (char *)pDcChargingInfo->EvConnAlarmCode);
+    }
+
+    //log_info("2 %d = VendorErrorCode = %s\r\n", index, (char *)ShmOCPP16Data->StatusNotification[index].VendorErrorCode);
+}
+
+void AdjustChargerCurrent()
+{
+    pSysConfig->RatingCurrent = ShmPsuData->SystemAvailableCurrent / 10;
+
+    // 設定的電流~ 如超過可輸出的電流,則 bypass
+    if (pSysConfig->RatingCurrent < pSysConfig->MaxChargingCurrent ||
+            pSysConfig->RatingCurrent == 0) {
+        pSysConfig->MaxChargingCurrent = 0;
+    }
+
+    log_info ("PSU : MaxChargingPower = %d, MaxChargingCurrent = %d",
+              ShmPsuData->SystemAvailablePower / 10,
+              ShmPsuData->SystemAvailableCurrent / 10
+             );
+
+    log_info ("Config : ChargingPower = %d, ChargingCurrent = %d",
+              pSysConfig->MaxChargingPower,
+              pSysConfig->MaxChargingCurrent
+             );
+}
+
+void ResetDetAlarmStatus(uint8_t gun)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun);
+
+    if (pDcChargingInfo->Type == _Type_Chademo) {
+        if (pAlarmCode->AlarmEvents.bits.SystemChademoOutputOVP == YES) {
+            pAlarmCode->AlarmEvents.bits.SystemChademoOutputOVP = NO;
+        }
+    } else if (pDcChargingInfo->Type == _Type_GB) {
+        if (pAlarmCode->AlarmEvents.bits.SystemGbOutputOVP == YES) {
+            pAlarmCode->AlarmEvents.bits.SystemGbOutputOVP = NO;
+        }
+    } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+        if (pAlarmCode->AlarmEvents.bits.SystemCcsOutputOVP == YES) {
+            pAlarmCode->AlarmEvents.bits.SystemCcsOutputOVP = NO;
+        }
+    }
+}
+
+static void powerCabinetPsuAlarmStatus(void)
+{
+    uint8_t i = 0;
+
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+    return;
+#endif //!defined DD360 && !defined DD360Audi && !defined DD360ComBox
+
+    for (i = 0; i < pSysWarning->WarningCount; i++) {
+        if (memcmp(&pSysWarning->WarningCode[i][0], "042267", 6) == 0) {
+            EmcOccureByString("042267");
+        }
+    }
+}
+
+static void autoStartChargingForComBox(uint8_t gunIndex)
+{
+#if !defined DD360ComBox
+    return ;
+#endif //!defined DD360ComBox
+
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
+
+    if ((pDcChargingInfo->ConnectorPlugIn == YES) &&
+            (pDcChargingInfo->SystemStatus == S_IDLE)
+       ) {
+        pSysInfo->CurGunSelected = gunIndex;
+        strcpy((char *)&pSysConfig->UserId, "AutoStartCharging");
+    }
+}
+
+static bool PrecheckIsPass(uint8_t gun_index)
+{
+    bool result = true;
+
+    // relay welding or driving 是反向
+    result = !ShmDcCommonData->GunRelayWeldingOccur[gun_index];
+
+    return result;
+}
+
+static void ReviewCriticalAlarm(void)
+{
+    if (ShmDcCommonData->GunRelayDrivingOccur[0] == YES ||
+            ShmDcCommonData->GunRelayDrivingOccur[1] == YES ||
+            ShmDcCommonData->GunRelayWeldingOccur[0] == YES ||
+            ShmDcCommonData->GunRelayWeldingOccur[1] == YES ||
+            pAlarmCode->AlarmEvents.bits.EmergencyStopTrip ||
+            pAlarmCode->AlarmEvents.bits.MainPowerBreakerTrip ||
+            pAlarmCode->AlarmEvents.bits.DoorOpen ||
+            pSysWarning->ExtraErrProcess != _EXTRA_ERR_PROCESS_NONE ||
+            pAlarmCode->AlarmEvents.bits.PsuFailureAlarm ||
+            pAlarmCode->AlarmEvents.bits.DisconnectedFromDo
+       ) {
+        pSysWarning->Level = 2;
+    } else {
+        pSysWarning->Level = 0;
+    }
+}
+
+static void CheckRelayWeldingOrDrivingFault(uint8_t gun_index)
+{
+    pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun_index);
+
+    // relay welding fault then stop the charging process.
+    uint8_t faultCode = RELAY_STATUS_ERROR_NONE;
+
+    if (gun_index == 0) {
+        if (ShmDcCommonData->CheckRelayStatus[RELAY_SMR1_P_STATUS] == RELAY_STATUS_ERROR_WELDING ||
+                ShmDcCommonData->CheckRelayStatus[RELAY_SMR1_N_STATUS] == RELAY_STATUS_ERROR_WELDING) {
+            faultCode = RELAY_STATUS_ERROR_WELDING;
+        } else if (ShmDcCommonData->CheckRelayStatus[RELAY_SMR1_P_STATUS] == RELAY_STATUS_ERROR_DRIVING ||
+                   ShmDcCommonData->CheckRelayStatus[RELAY_SMR1_N_STATUS] == RELAY_STATUS_ERROR_DRIVING) {
+            faultCode = RELAY_STATUS_ERROR_DRIVING;
+        }
+    } else if (gun_index == 1) {
+        if (ShmDcCommonData->CheckRelayStatus[RELAY_SMR2_P_STATUS] == RELAY_STATUS_ERROR_WELDING ||
+                ShmDcCommonData->CheckRelayStatus[RELAY_SMR2_N_STATUS] == RELAY_STATUS_ERROR_WELDING) {
+            faultCode = RELAY_STATUS_ERROR_WELDING;
+        } else if (ShmDcCommonData->CheckRelayStatus[RELAY_SMR2_P_STATUS] == RELAY_STATUS_ERROR_DRIVING ||
+                   ShmDcCommonData->CheckRelayStatus[RELAY_SMR2_N_STATUS] == RELAY_STATUS_ERROR_DRIVING) {
+            faultCode = RELAY_STATUS_ERROR_DRIVING;
+        }
+    }
+
+    if (pSysConfig->TotalConnectorCount >= 2 &&
+            !pSysInfo->IsAlternatvieConf) {
+        // 橋接
+        if (ShmDcCommonData->CheckRelayStatus[RELAY_PARA_P_STATUS] == RELAY_STATUS_ERROR_WELDING ||
+                ShmDcCommonData->CheckRelayStatus[RELAY_PARA_N_STATUS] == RELAY_STATUS_ERROR_WELDING) {
+            faultCode = RELAY_STATUS_ERROR_WELDING;
+        } else if (ShmDcCommonData->CheckRelayStatus[RELAY_PARA_P_STATUS] == RELAY_STATUS_ERROR_DRIVING ||
+                   ShmDcCommonData->CheckRelayStatus[RELAY_PARA_N_STATUS] == RELAY_STATUS_ERROR_DRIVING) {
+            faultCode = RELAY_STATUS_ERROR_DRIVING;
+        }
+    }
+
+    if (faultCode == RELAY_STATUS_ERROR_WELDING) {
+        // welding
+        if (pDcChargingInfo->Type == _Type_Chademo) {
+            RecordAlarmCode(gun_index, "011011");
+        } else if (pDcChargingInfo->Type == _Type_GB) {
+            RecordAlarmCode(gun_index, "011015");
+        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+            RecordAlarmCode(gun_index, "011013");
+        }
+
+        ShmDcCommonData->GunRelayWeldingOccur[gun_index] = YES;
+        EmcOccureByString("");
+    } else if (faultCode == RELAY_STATUS_ERROR_DRIVING) {
+        // driving
+        if (pDcChargingInfo->Type == _Type_Chademo) {
+            RecordAlarmCode(gun_index, "011012");
+        } else if (pDcChargingInfo->Type == _Type_GB) {
+            RecordAlarmCode(gun_index, "011016");
+        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+            RecordAlarmCode(gun_index, "011014");
+        }
+
+        ShmDcCommonData->GunRelayDrivingOccur[gun_index] = YES;
+        EmcOccureByString("");
+    } else {
+        ShmDcCommonData->GunRelayWeldingOccur[gun_index] = NO;
+        ShmDcCommonData->GunRelayDrivingOccur[gun_index] = NO;
+
+        if (pDcChargingInfo->Type == _Type_Chademo) {
+            ResetChargerAlarmCode(gun_index, "011012");
+            ResetChargerAlarmCode(gun_index, "011011");
+        } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+            ResetChargerAlarmCode(gun_index, "011014");
+            ResetChargerAlarmCode(gun_index, "011013");
+        } else if (pDcChargingInfo->Type == _Type_GB) {
+            ResetChargerAlarmCode(gun_index, "011016");
+            ResetChargerAlarmCode(gun_index, "011015");
+        }
+    }
+}
+
+int main(void)
+{
+    bool isModelNameMatch = true;
+    uint8_t evBoardStopState = 0;
+    uint8_t _ocppProfileChkFlag;
+
+    if (CreateAllCsuShareMemory() == FAIL) {
+        log_error("create share memory error\r\n");
+        return FAIL;
+    }
+    ClearAllShmMemParameter();
+
+    pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
+    pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
+    pSysWarning = (struct WARNING_CODE_INFO *)GetShmSysWarningInfo();
+
+    pAlarmCode = (struct AlarmCodeData *)GetShmAlarmCodeData();
+    pFaultCode = (struct FaultCodeData *)GetShmFaultCodeData();
+    pInfoCode = (struct InfoCodeData *)GetShmInfoCodeData();
+
+    ShmPsuData = (struct PsuData *)GetShmPsuData();
+
+    ShmCHAdeMOData = (struct CHAdeMOData *)GetShmCHAdeMOData();
+    ShmGBTData = (struct GBTData *)GetShmGBTData();
+    ShmCcsData = (struct CcsData *)GetShmCcsData();
+
+    ShmPrimaryMcuData = (struct PrimaryMcuData *)GetShmPrimaryMcuData();
+    ShmFanModuleData = (struct FanModuleData *)GetShmFanModuleData();
+    ShmRelayModuleData = (struct RelayModuleData *)GetShmRelayModuleData();
+    ShmLedModuleData = (struct LedModuleData *)GetShmLedModuleData();
+    ShmOCPP16Data = (struct OCPP16Data *)GetShmOCPP16Data();
+    ShmDcCommonData = (DcCommonInfo *)GetShmDcCommonData();
+    gAudiCustInfo = (SelectGunInfo *)GetShmSelectGunInfo();
+
+    log_info(" ****************  FileSystem Boot up ***************\n");
+    if (!InitialSystemDefaultConfig()) {
+        log_error("InitialSystemDefaultConfig NG \n");
+        //StopProcessingLoop();
+        sleep(5);
+        system("reboot -f");
+    }
+    CheckGunTypeFromHw();
+    CheckIsAlternatvieByModelName();
+    InitialShareMemoryInfo();
+
+    ChangeLcmByIndex(_LCM_INIT);
+    if (!CheckConnectorTypeStatus()) {
+        isModelNameMatch = false;
+    }
+
+    Initialization();
+    SpawnTask();
+    log_info("Spawned all Task");
+    if (!isModelNameMatch) {
+        pAlarmCode->AlarmEvents.bits.ModelNameNoneMatchStestFail = YES;
+        ChangeLcmByIndex(_LCM_FIX);
+        // Module Name 與硬體對應不正確
+        log_error("Module Name & HW info none match. \n");
+        sleep(3);
+        KillAllTask();
+        StopProcessingLoop();
+    }
+    CreateTimeoutFork();
+    log_info("Start self test... \n");
+    PrimaryLedIndicatorCtrlFork();
+    SelfTestRun();
+    StopSystemTimeoutDet();
+    log_info("Self test finished : SelfTestSeq = %d, Work_Step = %d ",
+             pSysInfo->SelfTestSeq,
+             ShmPsuData->Work_Step);
+
+    if (pSysInfo->SelfTestSeq == _STEST_FAIL ||
+            ShmPsuData->Work_Step == _NO_WORKING ||
+            pInfoCode->InfoEvents.bits.CcsSeccTimeoutQCA7000Comm == YES //DS60-120 add
+       ) {
+        if (pSysWarning->Level != 2) {
+            if (!DisplaySelfTestFailReason()) { //DS60-120 add
+                log_info("Soft reboot for retry self-tets. \n");
+
+                sleep(3);
+                system("killall OcppBackend &");
+                KillAllTask();
+                system("/usr/bin/run_evse_restart.sh");
+            }
+        }
+
+        for (uint8_t gun_index = 0; gun_index < pSysConfig->TotalConnectorCount; gun_index++) {
+            setChargerMode(gun_index, MODE_ALARM);
+        }
+        //ChangeLcmByIndex(_LCM_FIX);
+        sleep(3);
+        if (pSysWarning->Level == 2) { //DS60-120 add
+            KillTaskExceptPrimary();
+        } else {
+            KillTask();
+        }
+        StopProcessingLoop();
+    } else {
+        for (uint8_t gun_index = 0; gun_index < pSysConfig->TotalConnectorCount; gun_index++) {
+            setChargerMode(gun_index, MODE_IDLE);
+        }
+    }
+
+    // Local DB
+    if (DB_Open() != PASS) {
+        log_info("DB_Open fail. \n");
+        isDb_ready = false;
+    } else {
+        isDb_ready = true;
+        for (int _index = 0; _index < pSysConfig->TotalConnectorCount; _index++) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_index);
+
+            pDcChargingInfo->IsAvailable = DB_Get_Operactive(_index);
+        }
+        DB_Reboot_Record();
+    }
+    log_info("===== Create DB End ===== \n");
+
+#if defined DD360Audi
+    ChangeLcmByIndex(_LCM_SELECT_GUN);
+#else
+    ChangeLcmByIndex(_LCM_IDLE);
+#endif //defined DD360Audi
+
+    sleep(1);
+    //***** 須新增的偵測 *****//
+    // 1. Thernal - 控制風扇轉速
+    // 2. ouput fuse - 控制風扇轉速
+    CreateRfidFork();
+    // Create Watchdog
+    //CreateWatchdog();
+    // Main loop
+
+    log_info("===== Charger info ===== ");
+    log_info("SW Version = %s", fwVersion);
+    log_info("ModelName = %s", pSysConfig->ModelName);
+    CheckFwSlotStatusLog();
+    //AdjustChargerCurrent();
+    gettimeofday(&_cmdMainPriority_time, NULL);
+
+    GunIndexInfo *pGunIndexInfo = (GunIndexInfo *)GetGunIndexInfo();
+
+    for (;;) {
+        CheckOcppStatus();
+        ChkPrimaryStatus();
+        if ((IsConnectorWholeIdle() || pSysInfo->PageIndex == _LCM_FIX) &&
+                pSysInfo->SystemTimeoutFlag != Timeout_ReturnToChargingGunDet) {
+            CheckFactoryConfigFunction();
+
+            CheckFwUpdateFunction();
+        }
+
+        // OCPP 邏輯
+        OcppRemoteStartChk();
+        // 讀卡邏輯
+        ScannerCardProcess();
+        // 當 AC 沒有搭上時,清除一些錯誤碼
+        ClearAlarmCodeWhenAcOff();
+        // 確認是否要回到充電中的槍畫面邏輯判斷
+        CheckReturnToChargingConn();
+
+        //確認Power cabinet PSU Status
+        powerCabinetPsuAlarmStatus();
+
+        if (pGunIndexInfo->AcGunIndex > 0 && isDetectPlugin() && !GetIsCardScan()) {
+            pSysInfo->SystemPage = _LCM_WAIT_FOR_PLUG;
+        }
+
+        if ((GetTimeoutValue(_cmdMainPriority_time) / 1000) > 5000) {
+            CheckTask();
+
+            for (uint8_t _index = 0; _index < pSysConfig->TotalConnectorCount; _index++) {
+                pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_index);
+
+                if ((pDcChargingInfo->SystemStatus >= S_PREPARING_FOR_EVSE &&
+                        pDcChargingInfo->SystemStatus <= S_CHARGING) ||
+                        (pDcChargingInfo->SystemStatus >= S_CCS_PRECHARGE_ST0 &&
+                         pDcChargingInfo->SystemStatus <= S_CCS_PRECHARGE_ST1)) {
+                    if (pDcChargingInfo->SystemStatus == S_CHARGING &&
+                            _ocppProfileChkFlag == 12) {
+                        ChargingProfileFlat(_index);
+                        _ocppProfileChkFlag = 0;
+                    } else if (pDcChargingInfo->SystemStatus != S_CHARGING) {
+                        ChargingProfileFlat(_index);
+                        _ocppProfileChkFlag = 0;
+                    } else {
+                        _ocppProfileChkFlag++;
+                    }
+                }
+                checkGunOTPState(_index); //check gun OTP
+            }
+            gettimeofday(&_cmdMainPriority_time, NULL);
+        }
+
+        // 確認當前錯誤 Level = 2 ?
+        ReviewCriticalAlarm();
+        gEvBoardErr.GunErrMessage = 0;
+
+        for (uint8_t gun_index = 0; gun_index < pSysConfig->TotalConnectorCount; gun_index++) {
+            pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun_index);
+
+            autoStartChargingForComBox(gun_index); //for DD360ComBox
+
+            CheckGpioInStatus();
+
+            CheckErrorOccurStatus(gun_index);
+
+            // 確認 Relay Welding or Driving Fault
+            CheckRelayWeldingOrDrivingFault(gun_index);
+
+            // 收集各槍的錯誤狀態
+            collectError(gun_index);
+
+            ChkOcppStatus(gun_index);
+
+            if ((pDcChargingInfo->SystemStatus >= S_PREPARING_FOR_EVSE &&
+                    pDcChargingInfo->SystemStatus <= S_CHARGING) ||
+                    (pDcChargingInfo->SystemStatus >= S_CCS_PRECHARGE_ST0 &&
+                     pDcChargingInfo->SystemStatus <= S_CCS_PRECHARGE_ST1)) {
+                CheckSmartChargeProfile(gun_index);
+            }
+
+            //log_info("index = %d, ErrorCode = %s \n", gun_index, ShmOCPP16Data->StatusNotification[gun_index].ErrorCode);
+            switch (pDcChargingInfo->SystemStatus) {
+            case S_IDLE:
+                ReleaseAlarmCode(gun_index);
+
+                if (isModeChange(gun_index)) {
+                    log_info("S_IDLE================================== %x \n", gun_index);
+                    pDcChargingInfo->PresentChargedDuration = 0;
+                    pDcChargingInfo->RemainChargingDuration = 0;
+                    pDcChargingInfo->PresentChargingVoltage = 0;//DS60-120 add
+                    pDcChargingInfo->PresentChargingCurrent = 0;//DS60-120 add
+                    strcpy((char *)pDcChargingInfo->StartDateTime, "");
+                    strcpy((char *)pDcChargingInfo->StopDateTime, "");
+                    strcpy((char *)pDcChargingInfo->StartUserId, "");
+                    strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "");
+
+                    //Jerry add
+                    memset(&gAudiCustInfo->PricesInfo[gun_index], 0, sizeof(PricesInfo));
+                    gAudiCustInfo->PricesInfo[gun_index].Balance = FAIL_BALANCE_PRICES;
+                    destroySelGun(gun_index);
+                    ResetDetAlarmStatus(gun_index); //recovery OVP status code
+                    if (gAudiCustInfo->AuthorStateFromCabinet[gun_index] == YES) {
+                        gAudiCustInfo->AuthorStateFromCabinet[gun_index] = NO;
+                    }
+                    //strcpy((char *)ShmOCPP16Data->StatusNotification[gun_index].VendorErrorCode, "");
+                }
+
+            case S_RESERVATION:
+                if (isModeChange(gun_index)) {
+                    log_info("S_RESERVATION....................%x \n", gun_index);
+                    ShmOCPP16Data->CsMsg.bits[gun_index].ReserveNowConf = YES;
+                }
+
+                if (pDcChargingInfo->IsAvailable == NO) {
+                    setChargerMode(gun_index, MODE_MAINTAIN);
+                }
+
+            case S_MAINTAIN:
+            case S_FAULT: {
+                if (pSysWarning->Level == 2) {
+                    pDcChargingInfo =  (struct ChargingInfoData *)GetDcChargingInfoData(pSysInfo->CurGunSelected);
+
+                    if (gun_index == pSysInfo->CurGunSelected) {
+                        pSysInfo->SystemPage = _LCM_FIX;
+                    } else if (pDcChargingInfo->SystemStatus != S_IDLE &&
+                               pDcChargingInfo->SystemStatus != S_RESERVATION &&
+                               pDcChargingInfo->SystemStatus != S_MAINTAIN &&
+                               pDcChargingInfo->SystemStatus != S_FAULT) {
+                        if (pDcChargingInfo->SystemStatus == S_CHARGING) {
+                            pSysInfo->SystemPage = _LCM_COMPLETE;
+                        } else {
+#if defined DD360Audi
+                            pSysInfo->SystemPage = _LCM_SELECT_GUN;
+#else
+                            pSysInfo->SystemPage = _LCM_NONE;
+#endif //defined DD360Audi
+                        }
+                    }
+
+                    ClearDetectPluginFlag();
+//#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                    UpdateErrorCodeToOcpp(gun_index);
+//#endif //!defined DD360 && !defined DD360Audi
+                    setChargerMode(gun_index, MODE_FAULT);
+                } else {
+#if 1
+                    if (pDcChargingInfo->SystemStatus == S_FAULT) {
+#if defined DD360Audi
+                        pSysInfo->SystemPage = _LCM_SELECT_GUN;
+#else
+                        pSysInfo->SystemPage = _LCM_NONE;
+#endif //defined DD360Audi
+                        setChargerMode(gun_index, MODE_IDLE);
+                    }
+
+                    //if (pSysInfo->SystemPage == _LCM_FIX) {
+                    //    pSysInfo->SystemPage = _LCM_SELECT_GUN;//_LCM_NONE; //Jerry add
+                    //    //for (uint8_t g_index = 0; g_index < pSysConfig->TotalConnectorCount; g_index++) {
+                    //    setChargerMode(gun_index, MODE_IDLE);
+                    //    //}
+                    //}
+#endif //0
+
+                    if (pSysInfo->MainChargingMode == _MAIN_CHARGING_MODE_AVER) {
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                        if (pSysInfo->AcContactorStatus == YES)
+#else
+                        if (1)
+#endif //!defined DD360 && !defined DD360Audi
+                        {
+                            // 均充 -> 最大充
+                            if (pSysInfo->BridgeRelayStatus == NO) {
+                                if (pSysInfo->ReAssignedFlag == _REASSIGNED_NONE) {
+                                    log_info("=============Smart Charging============= Step 11 \n");
+                                    pSysInfo->ReAssignedFlag = _REASSIGNED_PREPARE_A_TO_M;
+                                }
+                            } else if (pSysInfo->ReAssignedFlag != _REASSIGNED_COMP &&
+                                       pSysInfo->ReAssignedFlag != _REASSIGNED_WAITING) {
+                                log_info("=============Smart Charging============= Step 14 \n");
+                                pSysInfo->ReAssignedFlag = _REASSIGNED_WAITING;
+                            } else if (pSysInfo->ReAssignedFlag == _REASSIGNED_COMP) {
+                                pSysInfo->MainChargingMode = _MAIN_CHARGING_MODE_MAX;
+                                pSysInfo->ReAssignedFlag = _REASSIGNED_NONE;
+                            }
+                        } else {
+                            pSysInfo->MainChargingMode = _MAIN_CHARGING_MODE_MAX;
+                            pSysInfo->ReAssignedFlag = _REASSIGNED_NONE;
+                        }
+                    } else {
+                        pSysInfo->ReAssignedFlag = _REASSIGNED_NONE;
+                    }
+
+                    if (PrecheckIsPass(gun_index)) {
+
+                        if (pDcChargingInfo->SystemStatus == S_FAULT) {
+                            pSysInfo->SystemPage = _LCM_NONE;
+                            setChargerMode(gun_index, MODE_IDLE);
+                        }
+
+                        if (pSysConfig->OfflinePolicy == _OFFLINE_POLICY_NO_CHARGING) {
+                            if (pSysInfo->CurGunSelected == gun_index) {
+#if defined DD360Audi
+                                pSysInfo->ConnectorPage = _LCM_SELECT_GUN;
+#else
+                                pSysInfo->ConnectorPage = _LCM_IDLE;
+#endif //
+                            }
+                        } else {
+                            // Idle 正常程序起點
+                            // 判斷是否有啟用檢查插槍
+                            if (isDetectPlugin()) {
+                                // 卡號驗證成功後,等待充電槍插入充電車
+                                if (pDcChargingInfo->RemoteStartFlag == YES) {
+                                    if (pDcChargingInfo->ConnectorPlugIn == YES &&
+                                            pDcChargingInfo->IsAvailable) {
+                                        log_info("-----------------1----------------- %d \n", gun_index);
+                                        pDcChargingInfo->RemoteStartFlag = NO;
+                                        pDcChargingInfo->isRemoteStart = YES; //DS60-120
+                                        ChangeGunSelectByIndex(gun_index);
+                                        AddPlugInTimes(gun_index);
+                                        setChargerMode(gun_index, MODE_REASSIGN_CHECK);
+                                        strcpy((char *)pDcChargingInfo->StartUserId, "");
+                                        ClearDetectPluginFlag();
+                                        continue;
+                                    }
+                                } else if (pSysInfo->OrderCharging == NO_DEFINE) {
+                                    if (pDcChargingInfo->ConnectorPlugIn == YES &&
+                                            pDcChargingInfo->IsAvailable &&
+                                            pDcChargingInfo->SystemStatus == S_IDLE
+#if defined DD360Audi
+                                            && (waitRightGunPlugIt(gun_index) == PASS ||
+                                                waitLeftGunPlugIt(gun_index) == PASS)
+#endif //defined DD360Audi
+                                       ) {
+                                        log_info("-----------------2----------------- \n");
+                                        ChangeGunSelectByIndex(gun_index);
+                                        AddPlugInTimes(gun_index);
+                                        strcpy((char *)pDcChargingInfo->StartUserId, (char *)pSysConfig->UserId);
+                                        log_info("index = %d, CardNumber = %s \n", gun_index, pDcChargingInfo->StartUserId);
+                                        strcpy((char *)pSysConfig->UserId, "");
+                                        // 當前操作的槍號,進入 Preparing
+                                        setChargerMode(gun_index, MODE_REASSIGN_CHECK);
+                                        ClearDetectPluginFlag();
+                                        continue;
+                                    }
+                                }
+
+                                if (!GetIsCardScan()) {
+                                    // LCM => Waiting for plugging
+                                    pSysInfo->SystemPage = _LCM_WAIT_FOR_PLUG;
+                                }
+                            } else if (pDcChargingInfo->SystemStatus == S_RESERVATION) {
+                                if (!isReservationExpired(gun_index)) {
+                                    pDcChargingInfo->SystemStatus = S_IDLE;
+                                }
+                            } else if (pSysConfig->AuthorisationMode == AUTH_MODE_DISABLE &&
+                                       (pDcChargingInfo->ConnectorPlugIn == YES && pDcChargingInfo->IsAvailable)) {
+                                log_info("-----------------3----------------- \n");
+                                bool isCanStartChargingFlag = GetStartChargingByAlterMode(gun_index);
+
+                                if (isCanStartChargingFlag) {
+                                    ChangeGunSelectByIndex(gun_index);
+                                    AddPlugInTimes(gun_index);
+                                    setChargerMode(gun_index, MODE_REASSIGN_CHECK);
+                                    ClearDetectPluginFlag();
+                                    continue;
+                                }
+                            } else {
+                                if (pSysInfo->CurGunSelected == gun_index) {
+#if defined DD360Audi
+                                    pSysInfo->ConnectorPage = _LCM_SELECT_GUN;
+#else
+                                    pSysInfo->ConnectorPage = _LCM_IDLE;
+#endif // defined DD360Audi
+                                }
+                            }
+                        } // Idle 正常程序終點
+                    } else {
+                        setChargerMode(gun_index, MODE_FAULT);
+                        if (gun_index == pSysInfo->CurGunSelected) {
+                            pSysInfo->SystemPage = _LCM_FIX;
+                        }
+                    }// PrecheckIsPass()
+                }
+            }
+            break;
+            case S_REASSIGN_CHECK: {
+                if (isModeChange(gun_index)) {
+                    log_info("S_REASSIGN_CHECK================================== %x \n", gun_index);
+#if defined DD360Audi
+                    pSysInfo->SystemPage = _LCM_SELECT_GUN;
+#else
+                    pSysInfo->SystemPage = _LCM_NONE;
+#endif //defined DD360Audi
+                    if (pSysInfo->OrderCharging != NO_DEFINE) {
+                        pSysInfo->OrderCharging = NO_DEFINE;
+                    }
+                    StopSystemTimeoutDet();
+                }
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                bool isRessign = false;
+                if (pSysConfig->TotalConnectorCount > 1 && pSysInfo->IsAlternatvieConf == NO) {
+                    if (pSysInfo->MainChargingMode == _MAIN_CHARGING_MODE_MAX) {
+                        for (byte index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+                            // 有其他槍已經分配好 psu 模塊
+                            if (pSysInfo->CurGunSelected != index &&
+                                    chargingInfo[index]->SystemStatus >= S_PREPARNING &&
+                                    chargingInfo[index]->SystemStatus != S_MAINTAIN) {
+                                log_info("=============Smart Charging============= Step 1 \n");
+                                pSysInfo->ReAssignedFlag = _REASSIGNED_PREPARE_M_TO_A;
+                                isRessign = true;
+                                break;
+                            }
+                        }
+                    } else if (pSysInfo->MainChargingMode == _MAIN_CHARGING_MODE_AVER &&
+                               pSysInfo->ReAssignedFlag != _REASSIGNED_NONE) {
+                        // 如果在切換最大充的過程中,需等待最大充切換完成後,在走均充流程
+                        if (pSysInfo->BridgeRelayStatus == YES) {
+                            if (pSysInfo->ReAssignedFlag != _REASSIGNED_COMP &&
+                                    pSysInfo->ReAssignedFlag != _REASSIGNED_WAITING) {
+                                log_info("=============Smart Charging============= Step 14 \n");
+                                pSysInfo->ReAssignedFlag = _REASSIGNED_WAITING;
+                            } else if (pSysInfo->ReAssignedFlag == _REASSIGNED_COMP) {
+                                pSysInfo->MainChargingMode = _MAIN_CHARGING_MODE_MAX;
+                                pSysInfo->ReAssignedFlag = _REASSIGNED_NONE;
+                                continue;
+                            }
+                        }
+
+                        if (pSysInfo->CurGunSelected == gun_index) {
+                            pSysInfo->ConnectorPage = _LCM_PRE_CHARGE;
+                        }
+                        continue;
+                    }
+                }
+#endif // !defined DD360 && !defined DD360Audi
+
+                if (0) { // if (isRessign)
+#if defined DD360 ||defined DD360Audi || defined DD360ComBox
+                    setChargerMode(gun_index, MODE_PRECHARGE);
+#else
+                    setChargerMode(gun_index, MODE_REASSIGN);
+#endif //defined DD360 || defined DD360Audi
+                } else {
+                    setChargerMode(gun_index, MODE_PRECHARGE);
+                }
+
+                if (pSysInfo->CurGunSelected == gun_index) {
+                    pSysInfo->ConnectorPage = _LCM_PRE_CHARGE;
+                }
+            }
+            break;
+            case S_REASSIGN: {
+                if (isModeChange(gun_index)) {
+                    log_info("S_REASSIGN================================== %x \n", gun_index);
+                    gettimeofday(&_toAverage_time, NULL);
+                }
+
+                // 重新分配,此階段主要是讓已經在充電或者準備進入充電前的緩衝
+                // 此狀態下~ 控制權在於 PSU 及 EV小板 Process
+                if (pSysInfo->ReAssignedFlag == _REASSIGNED_NONE ||
+                        pSysInfo->MainChargingMode == _MAIN_CHARGING_MODE_AVER) {
+                    if (pSysInfo->CanAverageCharging) {
+                        pSysInfo->MainChargingMode = _MAIN_CHARGING_MODE_AVER;//DS60-120 add
+                        setChargerMode(gun_index, MODE_PRECHARGE);
+                    } else {
+                        setChargerMode(gun_index, MODE_IDLE);
+                    }
+                    pSysInfo->ReAssignedFlag = _REASSIGNED_NONE; //DS60-120 add
+                } else if (pSysInfo->ReAssignedFlag == _REASSIGNED_RELAY_M_TO_A &&
+                           pSysInfo->BridgeRelayStatus == NO) {
+                    log_info("=============Smart Charging : _REASSIGNED_COMP============= Step 6 \n");
+                    pSysInfo->MainChargingMode = _MAIN_CHARGING_MODE_AVER;
+                    //pSysInfo->ReAssignedFlag = _REASSIGNED_NONE; //DS60-120 remove
+                    pSysInfo->CanAverageCharging = true; //DS60-120 add
+                }
+
+                //log_info("CurGunSelected = %d, gun_index = %d \n", pSysInfo->CurGunSelected, gun_index);
+                if (pSysInfo->CurGunSelected == gun_index) {
+                    pSysInfo->ConnectorPage = _LCM_PRE_CHARGE;
+                    // pSysInfo->SystemPage = _LCM_NONE;
+                }
+            }
+            break;
+            case S_PREPARNING: {
+                if (isModeChange(gun_index)) {
+                    log_info("S_PREPARNING================================== %x \n", gun_index);
+                    StopGunInfoTimeoutDet(gun_index);
+                    StartGunInfoTimeoutDet(gun_index, Timeout_Preparing);
+                }
+
+                if (ShmPsuData->SystemPresentPsuQuantity > 0 &&
+                        ShmPsuData->SystemAvailablePower > 10 &&
+                        GetTimeoutValue(pDcChargingInfo->TimeoutTimer) >= 5000000) {
+                    //if ((pDcChargingInfo->MaximumChargingVoltage > 0) && //DS60-120 remove
+                    //        (pDcChargingInfo->AvailableChargingCurrent > 0) &&
+                    //        (pDcChargingInfo->AvailableChargingPower > 0)) {
+                    setChargerMode(gun_index, MODE_PREPARE_FOR_EV);
+                    //}
+                }
+
+                //DS60-120 add
+                if (pSysConfig->TotalConnectorCount >= 2) {
+                    bool oughtAver = true;
+                    for (uint8_t index = 0; index < pSysConfig->TotalConnectorCount; index++) {
+                        pDcChargingInfo =  (struct ChargingInfoData *)GetDcChargingInfoData(index);
+                        // 共同進入充電邏輯
+                        if (pDcChargingInfo->SystemStatus != S_PREPARNING) {
+                            oughtAver = false;
+                            break;
+                        }
+                    }
+
+                    if (oughtAver) {
+                        log_info("********* Automatically change to aver mode ********** \n");
+                        pSysInfo->MainChargingMode = _MAIN_CHARGING_MODE_AVER;
+                        pSysInfo->ReAssignedFlag = _REASSIGNED_NONE;
+                    }
+                }
+
+                if ((evBoardStopState = isEvBoardStopChargeFlag(gun_index)) > 0) {
+                    // 板端要求停止 (錯誤)
+                    if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL) {
+                        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "EVDisconnected");
+                    }
+
+                    if (evBoardStopState == EV_BOARD_STOP_CHARGING) {
+                        ChargingAlarmProcess(gun_index);
+                    } else if (evBoardStopState == POWER_CABINET_STOP_CHARGING) {
+                        ChargingTerminalProcess(gun_index);
+                    }
+                } else if (isEvBoardNormalStopChargeFlag(gun_index) == YES) {
+                    // 板端要求停止 (正常)
+                    if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL) {
+                        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "EVDisconnected");
+                    }
+                    ChargingTerminalProcess(gun_index);
+                } else if (OcppRemoteStop(gun_index) == YES ||
+                           WifiScheduleStop(gun_index)) {
+                    // 後臺要求停止
+                    ChargingTerminalProcess(gun_index);
+                }
+
+                if (pSysInfo->CurGunSelected == gun_index) {
+                    pSysInfo->ConnectorPage = _LCM_PRE_CHARGE;
+                    // pSysInfo->SystemPage = _LCM_NONE;
+                }
+            }
+            break;
+            case S_PREPARING_FOR_EV: { // 等待車端的通訊 (EV 小板),待車端回報後,開始樁端的測試
+                if (isModeChange(gun_index)) {
+                    log_info("S_PREPARING_FOR_EV================================== %x \n", gun_index);
+                    //strcpy((char *)pSysConfig->UserId, "");
+                    StopGunInfoTimeoutDet(gun_index);
+                    StartGunInfoTimeoutDet(gun_index, Timeout_EvChargingDet);
+                }
+
+                if (pDcChargingInfo->Type == _Type_Chademo) {
+                    // 檢查車端的槍鎖是否為鎖上
+                    if (isEvGunLocked_chademo(gun_index) == YES) {
+                        setChargerMode(gun_index, MODE_PREPARE_FOR_EVSE);
+                    }
+                } else if (pDcChargingInfo->Type == _Type_GB) {
+                    // 檢查車端的 charging enable 是否為 1
+                    if (isEvGunLocked_gb(gun_index) == YES) {
+                        setChargerMode(gun_index, MODE_PREPARE_FOR_EVSE);
+                    }
+                } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                    // 檢查車端的 charging enable 是否為 1
+                    if (isEvGunLocked_ccs(gun_index) == YES) {
+                        setChargerMode(gun_index, MODE_PREPARE_FOR_EVSE);
+                    }
+                }
+
+                if ((evBoardStopState = isEvBoardStopChargeFlag(gun_index)) > 0) {
+                    // 板端要求停止 (錯誤)
+                    if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL) {
+                        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "EVDisconnected");
+                    }
+
+                    if (evBoardStopState == EV_BOARD_STOP_CHARGING) {
+                        ChargingAlarmProcess(gun_index);
+                    } else if (evBoardStopState == POWER_CABINET_STOP_CHARGING) {
+                        ChargingTerminalProcess(gun_index);
+                    }
+                } else if (isEvBoardNormalStopChargeFlag(gun_index) == YES) {
+                    // 板端要求停止 (正常)
+                    if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL) {
+                        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "EVDisconnected");
+                    }
+                    ChargingTerminalProcess(gun_index);
+                } else if (OcppRemoteStop(gun_index) == YES ||
+                           WifiScheduleStop(gun_index)) {
+                    // 後臺要求停止
+                    ChargingTerminalProcess(gun_index);
+                }
+
+                // LCM => Pre-charging
+                if (pSysInfo->CurGunSelected == gun_index) {
+                    pSysInfo->ConnectorPage = _LCM_PRE_CHARGE;
+                    // pSysInfo->SystemPage = _LCM_NONE;
+                }
+            }
+            break;
+            case S_PREPARING_FOR_EVSE: { // 等待 RB 通訊及測試,並將狀態回報, CSU 確認 Pass 後,開始進入充電
+                if (isModeChange(gun_index)) {
+                    log_info("S_PREPARING_FOR_EVSE================================== %x \n", gun_index);
+                    StopGunInfoTimeoutDet(gun_index);
+                    StartGunInfoTimeoutDet(gun_index, Timeout_EvseChargingDet);
+                }
+
+                if (pDcChargingInfo->Type == _Type_Chademo) {
+                    // 檢查樁端的 GFD 結果
+                    if (isPrechargeStatus_chademo(gun_index) > 5 && isPrechargeStatus_chademo(gun_index) < 8) {
+                        // 當前操作的槍號,進入 Charging
+                        setChargerMode(gun_index, MODE_CHARGING);
+                    }
+
+                    if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                        // GFD 錯誤停止
+                        RecordAlarmCode(gun_index, "012234");
+                    } else if (pDcChargingInfo->GroundFaultStatus == GFD_WARNING) {
+                        // GFD 警告
+                        RecordWarningCode(gun_index, "012296");
+                    }
+                } else if (pDcChargingInfo->Type == _Type_GB) {
+                    // 檢查樁端的 GFD 結果
+                    //if (isPrechargeStatus_gb(gun_index) > 5 && isPrechargeStatus_gb(gun_index) < 9) {
+                    if (isPrechargeStatus_gb(gun_index) > 9) {
+                        setChargerMode(gun_index, MODE_CHARGING);
+                    }
+
+                    if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                        // GFD 錯誤停止
+                        RecordAlarmCode(gun_index, "012236");
+                    } else if (pDcChargingInfo->GroundFaultStatus == GFD_WARNING) {
+                        // GFD 警告
+                        RecordWarningCode(gun_index, "012298");
+                    }
+                } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                    // 檢查樁端的 GFD 結果
+                    if ((pDcChargingInfo->GroundFaultStatus == GFD_PASS ||
+                            pDcChargingInfo->GroundFaultStatus == GFD_WARNING)) {
+                        setChargerMode(gun_index, MODE_CCS_PRECHARGE_STEP0);
+                    }
+
+                    if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                        // GFD 錯誤停止
+                        RecordAlarmCode(gun_index, "012235");
+                    } else if (pDcChargingInfo->GroundFaultStatus == GFD_WARNING) {
+                        // GFD 警告
+                        RecordWarningCode(gun_index, "012297");
+                    }
+                }
+
+                if ((evBoardStopState = isEvBoardStopChargeFlag(gun_index)) > 0) {
+                    // 板端要求停止 (錯誤)
+                    if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL) {
+                        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "EVDisconnected");
+                    }
+
+                    if (evBoardStopState == EV_BOARD_STOP_CHARGING) {
+                        ChargingAlarmProcess(gun_index);
+                    } else if (evBoardStopState == POWER_CABINET_STOP_CHARGING) {
+                        ChargingTerminalProcess(gun_index);
+                    }
+                } else if (isEvBoardNormalStopChargeFlag(gun_index) == YES) {
+                    // 板端要求停止 (正常)
+                    if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL) {
+                        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "EVDisconnected");
+                    }
+                    ChargingTerminalProcess(gun_index);
+                } else if (OcppRemoteStop(gun_index) == YES ||
+                           WifiScheduleStop(gun_index)) {
+                    // 後臺要求停止
+                    ChargingTerminalProcess(gun_index);
+                }
+
+                // LCM => Pre-charging
+                if (pSysInfo->CurGunSelected == gun_index) {
+                    pSysInfo->ConnectorPage = _LCM_PRE_CHARGE;
+                    // pSysInfo->SystemPage = _LCM_NONE;
+                }
+            }
+            break;
+            case S_CHARGING: { // 剛進入充電狀態,等待 EV 小板要求的輸出電流後開始輸出
+                if (isModeChange(gun_index)) {
+                    log_info("S_CHARGING================================== %x \n", gun_index);
+                    StopGunInfoTimeoutDet(gun_index);
+                    ftime(&startChargingTime[gun_index]);
+                    strcpy((char *)ShmOCPP16Data->StartTransaction[gun_index].ResponseIdTagInfo.Status, ""); //DS60-120 add
+                    ChangeStartOrStopDateTime(YES, gun_index);
+#if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
+                    OcppStartTransation(gun_index);
+#endif //!defined DD360 && !defined DD360Audi
+                }
+
+                if (ShmOCPP16Data->CpMsg.bits[gun_index].StartTransactionConf) {
+                    ShmOCPP16Data->CpMsg.bits[gun_index].StartTransactionConf = NO;
+                }
+                ftime(&endChargingTime[gun_index]);
+                pDcChargingInfo->PresentChargedDuration = DiffTimeb(startChargingTime[gun_index], endChargingTime[gun_index]);
+
+                if (pDcChargingInfo->Type == _Type_Chademo) {
+                    if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                        // GFD 錯誤停止
+                        RecordAlarmCode(gun_index, "012234");
+                    }
+                    //else if (((pDcChargingInfo->EvBatterytargetVoltage * 10) > 0 && pDcChargingInfo->EvBatterytargetVoltage < SYSTEM_MIN_VOL) ||
+                    //           (pDcChargingInfo->PresentChargedDuration >= 10 && pDcChargingInfo->PresentChargingVoltage < SYSTEM_MIN_VOL)) {
+                    //    // UVP
+                    //    RecordAlarmCode(gun_index, "012289");
+                    //    ChargingTerminalProcess(gun_index);
+                    //}
+                    else if (pDcChargingInfo->GroundFaultStatus == GFD_WARNING) {
+                        // GFD 警告
+                        RecordWarningCode(gun_index, "012296");
+                    }
+                } else if (pDcChargingInfo->Type == _Type_GB) {
+                    if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                        // GFD 錯誤停止
+                        RecordAlarmCode(gun_index, "012236");
+                    }
+                    //else if (isPrechargeStatus_gb(gun_index) == 10 &&
+                    //           (((pDcChargingInfo->EvBatterytargetVoltage * 10) > 0 && pDcChargingInfo->EvBatterytargetVoltage < SYSTEM_MIN_VOL) ||
+                    //            (pDcChargingInfo->PresentChargedDuration >= 10 && pDcChargingInfo->PresentChargingVoltage < SYSTEM_MIN_VOL))) {
+                    //    // UVP
+                    //    RecordAlarmCode(gun_index, "012290");
+                    //    ChargingTerminalProcess(gun_index);
+                    //}
+                    else if (pDcChargingInfo->GroundFaultStatus == GFD_WARNING) {
+                        // GFD 警告
+                        RecordWarningCode(gun_index, "012298");
+                    }
+                } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                    if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                        // GFD 錯誤停止
+                        RecordAlarmCode(gun_index, "012235");
+                    }
+                    //else if (((pDcChargingInfo->EvBatterytargetVoltage * 10) > 0 && pDcChargingInfo->EvBatterytargetVoltage < SYSTEM_MIN_VOL) ||
+                    //           (pDcChargingInfo->PresentChargedDuration >= 10 && pDcChargingInfo->PresentChargingVoltage < SYSTEM_MIN_VOL)) {
+                    //    // UVP
+                    //    RecordAlarmCode(gun_index, "012288");
+                    //    ChargingTerminalProcess(gun_index);
+                    //}
+                    else if (pDcChargingInfo->GroundFaultStatus == GFD_WARNING) {
+                        // GFD 警告
+                        RecordWarningCode(gun_index, "012297");
+                    }
+                }
+
+                if ((evBoardStopState = isEvBoardStopChargeFlag(gun_index)) > 0) {
+                    // 板端要求停止 (錯誤)
+                    if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL) {
+                        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "EVDisconnected");
+                    }
+                    //printf("%d evBoardStopState = %d\r\n", gun_index, evBoardStopState);
+                    if (evBoardStopState == EV_BOARD_STOP_CHARGING) {
+                        ChargingAlarmProcess(gun_index);
+                    } else if (evBoardStopState == POWER_CABINET_STOP_CHARGING) {
+                        ChargingTerminalProcess(gun_index);
+                    }
+                } else if (isEvBoardNormalStopChargeFlag(gun_index) == YES) {
+                    // 板端要求停止 (正常)
+                    if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL) {
+                        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "EVDisconnected");
+                    }
+                    ChargingTerminalProcess(gun_index);
+                } else if (OcppRemoteStop(gun_index) == YES ||
+                           WifiScheduleStop(gun_index) ||
+                           CheckBackendChargingTimeout(gun_index) ||
+                           CheckBackendChargingEnergy(gun_index) ||
+                           strcmp((char *)ShmOCPP16Data->StartTransaction[gun_index].ResponseIdTagInfo.Status, "Invalid") == EQUAL) {
+
+                    // 後臺要求停止
+                    ChargingTerminalProcess(gun_index);
+                }
+
+                // LCM => Charging
+                if (pSysInfo->CurGunSelected == gun_index) {
+                    pSysInfo->ConnectorPage = _LCM_CHARGING;
+                    // pSysInfo->SystemPage = _LCM_NONE;
+                }
+            }
+            break;
+            case S_ALARM:
+            case S_TERMINATING: {
+                if (isModeChange(gun_index)) {
+                    if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL) {
+                        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "Local");
+                    }
+
+                    if (pDcChargingInfo->SystemStatus == S_ALARM) {
+                        log_info("================== S_ALARM (%x) ================ \n", gun_index);
+                        UpdateErrorCodeToOcpp(gun_index);
+
+                        if (strcmp((char *)pDcChargingInfo->StartDateTime, "") != EQUAL) {
+                            OcppStopTransation(gun_index);
+                        }
+
+                        TheEndCharging(gun_index);
+                    } else {
+                        log_info("================== S_TERMINATING (%x) ================ \n", gun_index);
+                    }
+
+                    //log_info ("terminating......................... %x \n", gun_index);
+                    StopGunInfoTimeoutDet(gun_index);
+                }
+
+                if (pDcChargingInfo->Type == _Type_Chademo) {
+                    // 非車端的停止 : 需等待小板送出停止指令,讓車端解除槍
+                    //if (isEvStopCharging_chademo(gun_index) == YES) {
+                    //    /*+++ 20200908, vern, disable it for DD360 +++*/
+                    //    /*if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL)
+                    //        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "Local");*/
+                    //    /*--- 20200908, vern, disable it for DD360 ---*/
+                    //}
+
+                    if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                        // GFD 錯誤停止
+                        RecordAlarmCode(gun_index, "012234");
+                    } else if (pDcChargingInfo->GroundFaultStatus == GFD_WARNING) {
+                        // GFD 警告
+                        RecordWarningCode(gun_index, "012296");
+                    }
+
+                    //if (isEvStopCharging_chademo(gun_index) == YES ||
+                    //        isPrechargeStatus_chademo(gun_index) <= 0) {
+                    //    setChargerMode(gun_index, MODE_COMPLETE);
+                    //}
+                } else if (pDcChargingInfo->Type == _Type_GB) {
+                    //log_info("************ GB lock Status = %d, status = %d \n",
+                    //         isEvStopCharging_gb(gun_index),
+                    //         isPrechargeStatus_gb(gun_index));
+
+                    // 非車端的停止 : 需等待小板送出停止指令,讓車端解除槍
+                    //if (isEvStopCharging_chademo(gun_index) == YES) {
+                    //    /*+++ 20200908, vern, disable it for DD360 +++*/
+                    //    /*if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL)
+                    //            strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "Local");*/
+                    //    /*--- 20200908, vern, disable it for DD360 ---*/
+                    //}
+
+                    if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                        // GFD 錯誤停止
+                        RecordAlarmCode(gun_index, "012236");
+                    } else if (pDcChargingInfo->GroundFaultStatus == GFD_WARNING) {
+                        // GFD 警告
+                        RecordWarningCode(gun_index, "012298");
+                    }
+
+                    //if (isEvStopCharging_gb(gun_index) == YES ||
+                    //        isPrechargeStatus_gb(gun_index) <= 0) {
+                    //    setChargerMode(gun_index, MODE_COMPLETE);
+                    //}
+                } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                    // 非車端的停止 : 需等待小板送出停止指令,讓車端解除槍
+                    //if (isEvStopCharging_chademo(gun_index) == YES) {
+                    //    /*+++ 20200908, vern, disable it for DD360 +++*/
+                    //    /*if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL)
+                    //            strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "Local");*/
+                    //    /*--- 20200908, vern, disable it for DD360 ---*/
+                    //}
+
+                    if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                        // GFD 錯誤停止
+                        RecordAlarmCode(gun_index, "012235");
+                    } else if (pDcChargingInfo->GroundFaultStatus == GFD_WARNING) {
+                        // GFD 警告
+                        RecordWarningCode(gun_index, "012297");
+                    }
+
+                    //if (isEvStopCharging_ccs(gun_index) == YES &&
+                    //        (isPrechargeStatus_ccs(gun_index) >= 53 || isPrechargeStatus_ccs(gun_index) == 0 ||
+                    //         isPrechargeStatus_ccs(gun_index) == 13 || isPrechargeStatus_ccs(gun_index) == 14)) {
+                    //    setChargerMode(gun_index, MODE_COMPLETE);
+                    //}
+                }
+
+                if (pDcChargingInfo->SystemStatus == S_ALARM) {
+                    if (pDcChargingInfo->ConnectorPlugIn == NO &&
+                            GetTimeoutValue(pDcChargingInfo->TimeoutTimer) >= 10000000) {
+                        setChargerMode(gun_index, MODE_IDLE);
+                    }
+                } else {
+                    if (pDcChargingInfo->Type == _Type_Chademo) {
+                        if (isEvStopCharging_chademo(gun_index) == YES ||
+                                isPrechargeStatus_chademo(gun_index) <= 0) {
+                            setChargerMode(gun_index, MODE_COMPLETE);
+                        }
+                    } else if (pDcChargingInfo->Type == _Type_GB) {
+                        if (isEvStopCharging_gb(gun_index) == YES ||
+                                isPrechargeStatus_gb(gun_index) <= 0) {
+                            setChargerMode(gun_index, MODE_COMPLETE);
+                        }
+                    } else if (pDcChargingInfo->Type == _Type_CCS_2) {
+                        if (isEvStopCharging_ccs(gun_index) == YES &&
+                                (isPrechargeStatus_ccs(gun_index) >= 53 || isPrechargeStatus_ccs(gun_index) == 0 ||
+                                 isPrechargeStatus_ccs(gun_index) == 13 || isPrechargeStatus_ccs(gun_index) == 14)) {
+                            setChargerMode(gun_index, MODE_COMPLETE);
+                        }
+                    }
+                }
+
+                // 車端的停止
+                //if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "") == EQUAL) {
+                //    strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "EVDisconnected");
+                //}
+
+                if (pSysInfo->CurGunSelected == gun_index) {
+                    pSysInfo->ConnectorPage = _LCM_COMPLETE;
+                    // pSysInfo->SystemPage = _LCM_NONE;
+                }
+            }
+            break;
+            case S_COMPLETE: {
+                if (isModeChange(gun_index)) {
+                    log_info ("complete......................... %x \n", gun_index);
+                    if (strcmp((char *)pDcChargingInfo->StartDateTime, "") != EQUAL) {
+                        OcppStopTransation(gun_index);
+                    }
+
+                    TheEndCharging(gun_index);
+                    //ftime(&endChargingTime[gun_index]);
+                    //if (pDcChargingInfo->PresentChargedDuration != 0) {
+                    //    pDcChargingInfo->PresentChargedDuration = DiffTimeb(startChargingTime[gun_index], endChargingTime[gun_index]);
+                    //}
+
+                    //StopGunInfoTimeoutDet(gun_index);
+                    //StartGunInfoTimeoutDet(gun_index, Timeout_EvseCompleteDet);
+                    //ChangeStartOrStopDateTime(NO, gun_index);
+                }
+
+                //if (((pDcChargingInfo->ConnectorPlugIn == NO) ||
+                //        (restartFlag == 1)) &&
+                //        (GetTimeoutValue(pDcChargingInfo->TimeoutTimer) >= 10000000)) {
+                //    setChargerMode(gun_index, MODE_IDLE);
+                //    destroySelGun(gun_index); //Jerry add
+                //}
+
+                if (pDcChargingInfo->ConnectorPlugIn == NO &&
+                        GetTimeoutValue(pDcChargingInfo->TimeoutTimer) >= 10000000) {
+                    setChargerMode(gun_index, MODE_IDLE);
+#if defined DD360Audi
+                    destroySelGun(gun_index); //Jerry add
+#endif //defined DD360Audi
+                }
+
+                if (pSysInfo->CurGunSelected == gun_index) {
+                    pSysInfo->ConnectorPage = _LCM_COMPLETE;
+                    // pSysInfo->SystemPage = _LCM_NONE;
+                }
+            }
+            break;
+            case S_CCS_PRECHARGE_ST0: {
+                if (isModeChange(gun_index)) {
+                    log_info("CCS Precharge Processing 1....................%x \n", gun_index);
+                    StopGunInfoTimeoutDet(gun_index);
+                    StartGunInfoTimeoutDet(gun_index, Timeout_ForCcsPrechargeDet);
+                }
+
+                if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                    // GFD 錯誤停止
+                    RecordAlarmCode(gun_index, "012235");
+                }
+
+                if ((evBoardStopState = isEvBoardStopChargeFlag(gun_index)) > 0) {
+                    // 板端要求停止 (錯誤)
+                    if (evBoardStopState == EV_BOARD_STOP_CHARGING) {
+                        ChargingAlarmProcess(gun_index);
+                    } else if (evBoardStopState == POWER_CABINET_STOP_CHARGING) {
+                        ChargingTerminalProcess(gun_index);
+                    }
+                } else if (isEvBoardNormalStopChargeFlag(gun_index) == YES) {
+                    // 板端要求停止 (正常)
+                    ChargingTerminalProcess(gun_index);
+                } else if (OcppRemoteStop(gun_index) == YES ||
+                           WifiScheduleStop(gun_index)) {
+                    // 後臺要求停止
+                    ChargingTerminalProcess(gun_index);
+                }
+
+                // 等待 EV 小板 (CCS) 通知可以開始 Precharge
+                // 切換 D+ Relay to Precharge Relay
+                if (isPrechargeStatus_ccs(gun_index) == 39 || isPrechargeStatus_ccs(gun_index) == 40) {
+                    if (pDcChargingInfo->RelayKPK2Status == YES && pDcChargingInfo->PrechargeStatus != PRECHARGE_READY)
+                        //if (pDcChargingInfo->PrechargeStatus != PRECHARGE_PRERELAY_PASS)
+                    {
+                        //log_info("Send precharge ready 1..........%x, status = %d \n", gun_index, isPrechargeStatus_ccs(gun_index));
+                        if (isPrechargeStatus_ccs(gun_index) == 39) {
+                            log_info("Conn %x, Precharge ready, CCS status = PreChargeResponse (%d) \n", gun_index, isPrechargeStatus_ccs(gun_index));
+                        } else if (isPrechargeStatus_ccs(gun_index) == 40) {
+                            log_info("Conn %x, Precharge ready, CCS status = PowerDeliveryRequest start (%d) \n", gun_index, isPrechargeStatus_ccs(gun_index));
+                        }
+
+                        pDcChargingInfo->PrechargeStatus = PRECHARGE_READY;
+                    }
+                } else if (isPrechargeStatus_ccs(gun_index) == 45 || isPrechargeStatus_ccs(gun_index) == 46) {
+                    setChargerMode(gun_index, MODE_CCS_PRECHARGE_STEP1);
+                }
+
+                if (pSysInfo->CurGunSelected == gun_index) {
+                    pSysInfo->ConnectorPage = _LCM_PRE_CHARGE;
+                    // pSysInfo->SystemPage = _LCM_NONE;
+                }
+                break;
+            }
+            case S_CCS_PRECHARGE_ST1: {
+                if (isModeChange(gun_index)) {
+                    log_info("CCS Precharge Processing 2....................%x \n", gun_index);
+                }
+
+                if (pDcChargingInfo->GroundFaultStatus == GFD_FAIL) {
+                    // GFD 錯誤停止
+                    RecordAlarmCode(gun_index, "012235");
+                }
+
+                if ((evBoardStopState = isEvBoardStopChargeFlag(gun_index)) > 0) {
+                    // 板端要求停止 (錯誤)
+                    if (evBoardStopState == EV_BOARD_STOP_CHARGING) {
+                        ChargingAlarmProcess(gun_index);
+                    } else if (evBoardStopState == POWER_CABINET_STOP_CHARGING) {
+                        ChargingTerminalProcess(gun_index);
+                    }
+
+                } else if (isEvBoardNormalStopChargeFlag(gun_index) == YES) {
+                    // 板端要求停止 (正常)
+                    ChargingTerminalProcess(gun_index);
+                } else if (OcppRemoteStop(gun_index) == YES ||
+                           WifiScheduleStop(gun_index)) {
+                    // 後臺要求停止
+                    ChargingTerminalProcess(gun_index);
+                }
+
+                // 等待小板通知進入充電
+                // 切換 D+ Relay to Precharge Relay
+                if (pDcChargingInfo->RelayK1K2Status == YES) {
+                    pDcChargingInfo->PrechargeStatus = PRECHARGE_READY;
+                    setChargerMode(gun_index, MODE_CHARGING);
+                }
+
+                if (pSysInfo->CurGunSelected == gun_index) {
+                    pSysInfo->ConnectorPage = _LCM_PRE_CHARGE;
+                    // pSysInfo->SystemPage = _LCM_NONE;
+                }
+                break;
+            }
+            }
+        }
+
+#if defined DD360Audi
+        if (pSysInfo->SystemPage != _LCM_SELECT_GUN) {
+#else
+        if (pSysInfo->SystemPage != _LCM_NONE) {
+#endif //defined DD360Audi
+            ChangeLcmByIndex(pSysInfo->SystemPage);
+        } else {
+            bool dcPageRun = false;
+            if (pGunIndexInfo->AcGunIndex > 0 && pSysInfo->CurGunSelectedByAc != NO_DEFINE) {
+                pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(0);
+
+                if  (pAcChargingInfo->SystemStatus == S_IDLE) {
+                    ChangeLcmByIndex(_LCM_IDLE);
+                } else if (pAcChargingInfo->SystemStatus == S_PREPARNING) {
+                    ChangeLcmByIndex(_LCM_PRE_CHARGE);
+                } else if (pAcChargingInfo->SystemStatus == S_CHARGING) {
+                    ChangeLcmByIndex(_LCM_CHARGING);
+                } else if (pAcChargingInfo->SystemStatus == S_TERMINATING ||
+                           pAcChargingInfo->SystemStatus == S_COMPLETE) {
+                    ChangeLcmByIndex(_LCM_COMPLETE);
+                } else {
+                    dcPageRun = true;
+                }
+            } else {
+                dcPageRun = true;
+            }
+
+            if (dcPageRun) {
+                ChangeLcmByIndex(pSysInfo->ConnectorPage);
+            }
+        }
+
+        for (uint8_t gun_index = 0; gun_index < pSysConfig->TotalConnectorCount; gun_index++) {
+            pDcChargingInfo =  (struct ChargingInfoData *)GetDcChargingInfoData(gun_index);
+
+            checkEvBoardAlarmState(pDcChargingInfo->Type);
+        }
+
+        //write(wtdFd, "a", 1);
+        //WriteWatchDogState("a");
+
+        usleep(whileLoopTime);
+    }
+
+    return FAIL;
+}

+ 29 - 9
EVSE/Projects/DD360ComBox/Apps/main.h → EVSE/Projects/DD360ComBox/Apps/CSU/main.h

@@ -28,7 +28,7 @@
 #define DEFAULT_AC_INDEX                        2
 #define PSU_MIN_CUR                             100
 
-#define DB_FILE                                 "/Storage/ChargeLog/localCgargingRecord.db"
+//#define DB_FILE                                 "/Storage/ChargeLog/localCgargingRecord.db"
 
 #define uSEC_VAL                                1000000
 #define SELFTEST_TIMEOUT                        60//45
@@ -43,9 +43,9 @@
 #define GUN_COMP_WAIT_TIMEOUT                   10
 #define GUN_PRECHARGING_TIMEOUT                 60
 
-#define log_info(format, args...) StoreLogMsg_1("[%s:%d][%s][Info] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
-#define log_warn(format, args...) StoreLogMsg_1("[%s:%d][%s][Warn] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
-#define log_error(format, args...) StoreLogMsg_1("[%s:%d][%s][Error] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+//#define log_info(format, args...) StoreLogMsg_1("[%s:%d][%s][Info] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+//#define log_warn(format, args...) StoreLogMsg_1("[%s:%d][%s][Warn] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+//#define log_error(format, args...) StoreLogMsg_1("[%s:%d][%s][Error] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
 
 //------------------------------------------------------------------------------
 typedef struct StLedConfig {
@@ -61,18 +61,38 @@ typedef struct StLedConfig {
 } LedConfig;
 
 //------------------------------------------------------------------------------
-bool isDetectPlugin();
-void _DetectPlugInTimeout();
-void StopSystemTimeoutDet();
+bool isDetectPlugin(void);
+void _DetectPlugInTimeout(void);
+void StartSystemTimeoutDet(uint8_t flag);
+void StopSystemTimeoutDet(void);
 
 void StartGunInfoTimeoutDet(uint8_t gunIndex, uint8_t flag);
 void StopGunInfoTimeoutDet(uint8_t gunIndex);
 
-void ClearAuthorizedFlag();
+void AuthorizingStart(void);
+bool IsAuthorizingMode(void);
+bool isAuthorizedComplete(void);
+void ClearAuthorizedFlag(void);
 
 void ChargingAlarmProcess(uint8_t gunIndex);
 void StopChargingProcessByString(uint8_t level);
 
-void AcChargingTerminalProcess();
+void EmcOccureByString(char *code);
+void ReleaseEmsOccureByString(uint8_t index, char *code);
+
+void confirmSelGun(uint8_t selGun);
+void destroySelGun(uint8_t curGun);
+int getConfirmSelectedGun(uint8_t curSel);
+void setSelGunWaitToAuthor(uint8_t curSel);
+
+void ChargingTerminalProcess(uint8_t gunIndex);
+void AcChargingTerminalProcess(void);
+
+void ChangeGunSelectByIndex(uint8_t sel);
+
+void setChargerMode(uint8_t gun_index, uint8_t mode);
+
+void KillAllTask(void);
+void KillTask(void);
 
 #endif /* _MAIN_H_ */

File diff suppressed because it is too large
+ 282 - 256
EVSE/Projects/DD360ComBox/Apps/CSU/mainNew.c


+ 2 - 0
EVSE/Projects/DD360ComBox/Apps/Config.h

@@ -317,6 +317,8 @@ typedef struct StDcCommonInfo {
     uint8_t CheckRelayStatus[6]; //check Relay welding or driving fault
     uint8_t GunRelayWeldingOccur[2];
     uint8_t GunRelayDrivingOccur[2];
+    uint8_t SystemModeChange;
+    uint8_t Reserved[3];
 } DcCommonInfo;
 
 #endif /* CONFIG_H_ */

+ 54 - 53
EVSE/Projects/DD360ComBox/Apps/DataBase/DataBase.c

@@ -9,7 +9,16 @@
 #include "../ShareMemory/shmMem.h"
 
 //------------------------------------------------------------------------------
-int DB_Open(sqlite3 *db)
+#define DB_FILE                                 "/Storage/ChargeLog/localCgargingRecord.db"
+
+//------------------------------------------------------------------------------
+static sqlite3 *localDb;
+
+//------------------------------------------------------------------------------
+//===============================================
+// SQLite3 related routine
+//===============================================
+int DB_Open(void)
 {
     int result = PASS;
     char *errMsg = NULL;
@@ -49,21 +58,21 @@ int DB_Open(sqlite3 *db)
                             "`idx` INTEGER PRIMARY KEY AUTOINCREMENT, "
                             "`rebootDatetime` TEXT NOT NULL, unique(rebootDatetime) on conflict replace);";
 
-    if (sqlite3_open(DB_FILE, &db)) {
+    if (sqlite3_open(DB_FILE, &localDb)) {
         result = FAIL;
-        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(db));
-        sqlite3_close(db);
+        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(localDb));
+        sqlite3_close(localDb);
     } else {
         log_info( "Local charging record database open successfully.\r\n");
 
-        if (sqlite3_exec(db, createRecordSql, 0, 0, &errMsg) != SQLITE_OK) {
+        if (sqlite3_exec(localDb, createRecordSql, 0, 0, &errMsg) != SQLITE_OK) {
             result = FAIL;
             log_info( "Create local charging record table error message: %s\n", errMsg);
         } else {
             log_info( "Opened local charging record table successfully\n");
         }
 
-        if (sqlite3_exec(db, createCfgSql, 0, 0, &errMsg) != SQLITE_OK) {
+        if (sqlite3_exec(localDb, createCfgSql, 0, 0, &errMsg) != SQLITE_OK) {
             result = FAIL;
             log_info( "Create local config table error message: %s\n", errMsg);
         } else {
@@ -71,14 +80,14 @@ int DB_Open(sqlite3 *db)
         }
 
         //DS60-120
-        if (sqlite3_exec(db, createrecordSql, 0, 0, &errMsg) != SQLITE_OK) {
+        if (sqlite3_exec(localDb, createrecordSql, 0, 0, &errMsg) != SQLITE_OK) {
             result = FAIL;
             log_info( "Create local record table error message: %s\n", errMsg);
         } else {
             log_info( "Opened local record table successfully\n");
         }
 
-        if (sqlite3_exec(db, createrebootSql, 0, 0, &errMsg) != SQLITE_OK) {
+        if (sqlite3_exec(localDb, createrebootSql, 0, 0, &errMsg) != SQLITE_OK) {
             result = FAIL;
             log_info( "Create reboot record table error message: %s\n", errMsg);
         } else {
@@ -86,49 +95,41 @@ int DB_Open(sqlite3 *db)
         }
         //-----
 
-        sqlite3_close(db);
+        sqlite3_close(localDb);
     }
 
     return result;
 }
 
-int DB_Insert_Record(sqlite3 *db, int gun_index)
+int DB_Insert_Record(int gun_index)
 {
     int result = PASS;
     char *errMsg = NULL;
     char insertSql[1024];
+    struct ChargingInfoData *pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun_index);
+    struct OCPP16Data *ShmOCPP16Data = (struct OCPP16Data *)GetShmOCPP16Data();
 
     sprintf(insertSql, "insert into charging_record(reservationId, transactionId, startMethod, userId, dateTimeStart, dateTimeStop, socStart, socStop, chargeEnergy, stopReason) "
             "values('%d', '%d', '%d', '%s', '%s', '%s', '%d', '%d', '%f', '%s');",
-            chargingInfo[gun_index]->ReservationId, //DS60-120 add
+            pDcChargingInfo->ReservationId, //DS60-120 add
             ShmOCPP16Data->StartTransaction[gun_index].ResponseTransactionId,
-            chargingInfo[gun_index]->StartMethod,
-            chargingInfo[gun_index]->StartUserId,
-            chargingInfo[gun_index]->StartDateTime,
-            chargingInfo[gun_index]->StopDateTime,
-            chargingInfo[gun_index]->EvBatteryStartSoc,
-            chargingInfo[gun_index]->EvBatterySoc,
-            chargingInfo[gun_index]->PresentChargedEnergy,
-            //DS60-120 remove
-            //ShmSysConfigAndInfo->SysInfo.AcChargingData[gun_index].ReservationId,
-            //ShmOCPP16Data->StartTransaction[gun_index].ResponseTransactionId,
-            //ShmSysConfigAndInfo->SysInfo.AcChargingData[gun_index].StartMethod,
-            //ShmSysConfigAndInfo->SysInfo.AcChargingData[gun_index].StartUserId,
-            //ShmSysConfigAndInfo->SysInfo.AcChargingData[gun_index].StartDateTime,
-            //ShmSysConfigAndInfo->SysInfo.AcChargingData[gun_index].StopDateTime,
-            //ShmSysConfigAndInfo->SysInfo.AcChargingData[gun_index].EvBatterySoc,
-            //ShmSysConfigAndInfo->SysInfo.AcChargingData[gun_index].EvBatterySoc,
-            //ShmSysConfigAndInfo->SysInfo.AcChargingData[gun_index].PresentChargedEnergy,
+            pDcChargingInfo->StartMethod,
+            pDcChargingInfo->StartUserId,
+            pDcChargingInfo->StartDateTime,
+            pDcChargingInfo->StopDateTime,
+            pDcChargingInfo->EvBatteryStartSoc,
+            pDcChargingInfo->EvBatterySoc,
+            pDcChargingInfo->PresentChargedEnergy,
             ShmOCPP16Data->StopTransaction[gun_index].StopReason);
 
     //if (sqlite3_open("/Storage/ChargeLog/localCgargingRecord.db", &db)) {
-    if (sqlite3_open(DB_FILE, &db)) { //DS60-120 add
+    if (sqlite3_open(DB_FILE, &localDb)) { //DS60-120 add
         result = FAIL;
-        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(db));
-        sqlite3_close(db);
+        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(localDb));
+        sqlite3_close(localDb);
     } else {
         log_info( "Local charging record database open successfully.\r\n");
-        if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
+        if (sqlite3_exec(localDb, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
             result = FAIL;
             log_info( "Insert local charging record error message: %s\n", errMsg);
         } else {
@@ -137,50 +138,50 @@ int DB_Insert_Record(sqlite3 *db, int gun_index)
 
         //DS60-120 add
         sprintf(insertSql, "delete from charging_record where idx < (select idx from charging_record order by idx desc limit 1)-2000;");
-        if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
+        if (sqlite3_exec(localDb, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
             result = FAIL;
             log_info( "delete local charging error message: %s\n", errMsg);
         } else {
             log_info( "delete local charging record successfully\n");
         }
 
-        sqlite3_close(db);
+        sqlite3_close(localDb);
     }
 
     return result;
 }
 
-int DB_Update_Operactive(sqlite3 *db, uint8_t gun_index, uint8_t IsAvailable)
+int DB_Update_Operactive(uint8_t gun_index, uint8_t IsAvailable)
 {
     uint8_t result = false;
     char *errMsg = NULL;
     char sqlStr[1024];
     srand(time(NULL));
 
-    if (sqlite3_open(DB_FILE, &db)) {
+    if (sqlite3_open(DB_FILE, &localDb)) {
         result = FAIL;
-        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(db));
-        sqlite3_close(db);
+        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(localDb));
+        sqlite3_close(localDb);
     } else {
         log_info( "Local charging record database open successfully (%d).\r\n", IsAvailable);
 
         //sprintf(sqlStr, "insert or replace into config (IsAvailable, connector, val) values('IsAvailable', %d, %d);", gun_index, IsAvailable);
         sprintf(sqlStr, "insert or replace into config (item, connector, val) values('IsAvailable', %d, %d);", gun_index, IsAvailable); //DS60-120 add
         log_info("sqlStr= %s\r\n", sqlStr);
-        if (sqlite3_exec(db, sqlStr, 0, 0, &errMsg) != SQLITE_OK) {
+        if (sqlite3_exec(localDb, sqlStr, 0, 0, &errMsg) != SQLITE_OK) {
             result = FAIL;
             log_info( "update config error message: %s\n", errMsg);
         } else {
             log_info("update connector-%d config item isOperactive to %d\r\n", gun_index, IsAvailable);
         }
 
-        sqlite3_close(db);
+        sqlite3_close(localDb);
     }
 
     return result;
 }
 
-int DB_Get_Operactive(sqlite3 *db, uint8_t gun_index)
+int DB_Get_Operactive(uint8_t gun_index)
 {
     uint8_t result = true;
     char *errMsg = NULL;
@@ -192,13 +193,13 @@ int DB_Get_Operactive(sqlite3 *db, uint8_t gun_index)
     sprintf(sqlStr, "select * from config where item='IsAvailable' and connector=%d;", gun_index); //DS60-120 add
     //DEBUG_INFO("sqlStr= %s\r\n", sqlStr);
 
-    if (sqlite3_open(DB_FILE, &db)) {
+    if (sqlite3_open(DB_FILE, &localDb)) {
         result = FAIL;
-        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(db));
-        sqlite3_close(db);
+        log_info( "Can't open database: %s\r\n", sqlite3_errmsg(localDb));
+        sqlite3_close(localDb);
     } else {
         log_info( "Local config query database open successfully.\r\n");
-        sqlite3_get_table(db, sqlStr, &rs, &rows, &cols, &errMsg);
+        sqlite3_get_table(localDb, sqlStr, &rs, &rows, &cols, &errMsg);
         if (rows > 0) {
             for (int idxRow = 1; idxRow <= rows; idxRow++) {
                 if (strcmp(rs[(idxRow * cols) + 3], "0") == 0) {
@@ -211,13 +212,13 @@ int DB_Get_Operactive(sqlite3 *db, uint8_t gun_index)
         }
 
         sqlite3_free_table(rs);
-        sqlite3_close(db);
+        sqlite3_close(localDb);
     }
 
     return result;
 }
 
-int DB_Reboot_Record(sqlite3 *db)
+int DB_Reboot_Record(void)
 {
     int result = PASS;
     char *errMsg = NULL;
@@ -225,13 +226,13 @@ int DB_Reboot_Record(sqlite3 *db)
 
     sprintf(insertSql, "insert into reboot_record(rebootDatetime) values(CURRENT_TIMESTAMP);");
 
-    if (sqlite3_open(DB_FILE, &db)) {
+    if (sqlite3_open(DB_FILE, &localDb)) {
         result = FAIL;
-        log_info( "Can't open database: %s\n", sqlite3_errmsg(db));
-        sqlite3_close(db);
+        log_info( "Can't open database: %s\n", sqlite3_errmsg(localDb));
+        sqlite3_close(localDb);
     } else {
         log_info( "Local charging record database open successfully.\n");
-        if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
+        if (sqlite3_exec(localDb, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
             result = FAIL;
             log_info( "Insert reboot record error message: %s\n", errMsg);
         } else {
@@ -239,14 +240,14 @@ int DB_Reboot_Record(sqlite3 *db)
         }
 
         sprintf(insertSql, "delete from reboot_record where idx < (select idx from charging_record order by idx desc limit 1)-2000;");
-        if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
+        if (sqlite3_exec(localDb, insertSql, 0, 0, &errMsg) != SQLITE_OK) {
             result = FAIL;
             log_info( "delete reboot record error message: %s\n", errMsg);
         } else {
             log_info( "delete reboot record successfully\n");
         }
 
-        sqlite3_close(db);
+        sqlite3_close(localDb);
     }
 
     return result;

+ 15 - 10
EVSE/Projects/DD360ComBox/Apps/Makefile

@@ -16,6 +16,7 @@ INC_FLAGS += -I $(TOP)/Define
 INC_FLAGS += -I $(TOP)/Log
 INC_FLAGS += -I $(TOP)/ShareMemory
 INC_FLAGS += -I $(TOP)/CSU
+INC_FLAGS += -I $(TOP)/DataBase
 INC_FLAGS += -I $(TOP)/ModuleInternalComm
 INC_FLAGS += -I $(TOP)/ModuleEvComm
 INC_FLAGS += -I $(TOP)/ModulePrimary
@@ -27,6 +28,7 @@ DefineLib = $(TOP)/Define
 LogLib = $(TOP)/Log
 ShmMemLib = $(TOP)/ShareMemory
 CSULib = $(TOP)/CSU
+DataBaseLib = $(TOP)/DataBase
 InternalCommLib = $(TOP)/ModuleInternalComm
 EvCommLib = $(TOP)/ModuleEvComm
 PrimaryLib = $(TOP)/ModulePrimary
@@ -62,10 +64,13 @@ COMMON_OBJ_FILES = common.o \
 					$(DefineLib)/define.o \
 					$(ShmMemLib)/shmMem.o \
 					$(LogLib)/log.o \
-					$(SelectGunLib)/SelectGun.o
-#main
-MAIN_OBJ_FILES = $(COMMON_OBJ_FILES) $(SQLite3_H) $(ModuleUpgrade_H) $(RFID_H) $(Lib_Module_RatedCurrent) \
-					main.o $(CSULib)/Primary.o
+					$(SelectGunLib)/SelectGun.o \
+
+
+MAIN_OBJ_FILES = $(COMMON_OBJ_FILES) $(DataBaseLib)/DataBase.o \
+					$(CSULib)/main.o  $(CSULib)/Primary.o $(CSULib)/WatchDog.o $(CSULib)/ZipFile.o \
+					$(CSULib)/RFID.o $(CSULib)/SelfTest.o $(CSULib)/UpgradeFW.o \
+					$(CSULib)/Ethernet.o
 MAIN_SRC_FILES = $(patsubst %.o, %.c, $(MAIN_OBJ_FILES))
 %.o: %.c
 	$(CC) $(CFLAGS) -c $<
@@ -95,8 +100,8 @@ apps: MainTask DoCommTask EvCommTask \
 				FactoryConfigApp OtherTools CleanExec
 
 MainTask:
-	#$(CC) $(DEFINE) $(MAIN_SRC_FILES) $(CFLAGS) $(TFLAGS) $(INC_FLAGS) ${Lib_Module_RFID} \
-	#	 ${Lib_Module_Upgrade} ${Lib_SQLite3} $(Lib_Module_RatedCurrent) -o main
+	#$(CC) $(DEFINE) $(MAIN_SRC_FILES) $(CFLAGS) $(TFLAGS) $(INC_FLAGS) $(SQLite3_H) $(ModuleUpgrade_H) $(RateCurrent_H) \
+	#	$(RFID_H) $(Lib_Module_RFID) $(Lib_Module_Upgrade) $(Lib_SQLite3) $(Lib_Module_RateCurrent) -o main
 	$(CC) $(DEFINE) $(SQLite3_H) $(ModuleUpgrade_H) $(RFID_H) $(RatedCurrent_H) $(CFLAGS) -c -o main.o main.c
 	$(CC) $(DEFINE) $(SQLite3_H) $(ModuleUpgrade_H) $(RFID_H) $(RatedCurrent_H) $(CFLAGS) -c -o timeout.o timeout.c
 	$(CC) $(DEFINE) $(CFLAGS) -c -o common.o common.c
@@ -108,10 +113,10 @@ DoCommTask:
 	$(CC) -o Module_DoComm DoComm.o define.o
 
 EvCommTask:
-	$(CC) $(DEFINE) $(EVCOMM_SRC_FILES) $(CFLAGS) $(TFLAGS) $(INC_FLAGS) $(Lib_Module_RatedCurrent) -o Module_EvComm
-	#$(CC) $(DEFINE) $(CFLAGS) $(RatedCurrent_H) -c -o Ev_Comm.o $(EvCommLib)/Ev_Comm.c
-	#$(CC) $(DEFINE) $(CFLAGS) $(RatedCurrent_H) -c -o Module_EvComm.o $(EvCommLib)/Module_EvComm.c
-	#$(CC) -o Module_EvComm Ev_Comm.o Module_EvComm.o $(Lib_Module_RatedCurrent)
+	#$(CC) $(DEFINE) $(EVCOMM_SRC_FILES) $(CFLAGS) $(TFLAGS) $(INC_FLAGS) $(Lib_Module_RatedCurrent) -o Module_EvComm
+	$(CC) $(DEFINE) $(CFLAGS) $(RatedCurrent_H) -c -o Ev_Comm.o $(EvCommLib)/Ev_Comm.c
+	$(CC) $(DEFINE) $(CFLAGS) $(RatedCurrent_H) -c -o Module_EvComm.o $(EvCommLib)/Module_EvComm.c
+	$(CC) -o Module_EvComm Ev_Comm.o Module_EvComm.o $(Lib_Module_RatedCurrent)
 
 EventLoggingTask:
 	$(CC) $(DEFINE) $(CFLAGS) -c -o define.o $(DefineLib)/define.c

+ 2 - 2
EVSE/Projects/DD360ComBox/Apps/ModuleEvComm/Module_EvComm.c

@@ -2228,7 +2228,7 @@ static float ReadAdcVolt(uint8_t AdcChannel)
     //AIN3=pilot voltage
     int fd = -1;
     uint8_t str[64] = {0};
-    uint8_t AdcValue[4] = {0};
+    uint8_t AdcValue[8] = {'\0'};
 
     if (AdcChannel > 7) {
         return -1;
@@ -2240,7 +2240,7 @@ static float ReadAdcVolt(uint8_t AdcChannel)
 
     close(fd);
 
-    return (1.8 * atoi((int)AdcValue)) / 4095;
+    return (1.8 * atoi((char *)&AdcValue[0])) / 4095;
 }
 
 static void getChillerTemperature(ChillerTemp *chillerTemp)

+ 31 - 29
EVSE/Projects/DD360ComBox/Apps/ModuleEvComm/Module_EvRxComm.c

@@ -96,22 +96,22 @@ static float ReadAdcVolt(uint8_t AdcChannel)
     //AIN2=CCS_Proximity/2
     //AIN3=pilot voltage
     int fd = -1;
-    uint8_t str[64];
-    uint8_t AdcValue[4];
+    uint8_t str[64] = {0};
+    uint8_t AdcValue[8] = {'\0'};
+    //uint32_t AdcValue = 0;
 
     if (AdcChannel > 7) {
         return -1;
     }
 
-    memset(str, 0, sizeof(str));
-    memset(AdcValue, 0, sizeof(AdcValue));
     sprintf((char *)str, "/sys/bus/iio/devices/iio\:device0/in_voltage%d_raw", AdcChannel);
     fd = open((char *)str, O_RDONLY);
     read(fd, AdcValue, 4);
 
     close(fd);
 
-    return (1.8 * atoi((int)AdcValue)) / 4095;
+    return (1.8 * atoi((char *)&AdcValue[0])) / 4095;
+    //return (1.8 * atoi((char *)&AdcValue)) / 4095;
 }
 
 static void getChillerTemperature(ChillerTemp *chillerTemp)
@@ -124,14 +124,14 @@ static void getChillerTemperature(ChillerTemp *chillerTemp)
         adcVoltage = 0.0;
         adcVoltage =  ReadAdcVolt(i);
         if ((adcVoltage <= 0.9) && (adcVoltage >= 0.8)) { //0 ~ -40
-            chillerTemp->Temp[i] = ((adcVoltage - 0.908) * 500) + 60;
+            pChillerTemp->Temp[i] = ((adcVoltage - 0.908) * 500) + 60;
             //log_info("1 adcVoltage = %f", (adcVoltage - 0.9) * 500);
         } else if ((adcVoltage <= 1.07) && (adcVoltage > 0.9)) {
-            chillerTemp->Temp[i] = ((adcVoltage - 0.91) * 705.88) + 60;
+            pChillerTemp->Temp[i] = ((adcVoltage - 0.91) * 705.88) + 60;
             //log_info("2 adcVoltage = %f", (adcVoltage - 0.9) * 500);
-        } /*else {
-            chillerTemp->Temp[i] = 195;
-        }*/
+        } else {
+            pChillerTemp->Temp[i] = 195;
+        }
 
         //CcsConnectorTemp1 = ReadAdcVolt(i);
         //if ((CcsConnectorTemp1 <= 0.9) && (CcsConnectorTemp1 >= 0.8)) { //0 ~ -40
@@ -182,7 +182,6 @@ static void AddrAssignment(uint8_t *data)
     //}
 }
 
-
 void CANReceiver(int fd)
 {
     pid_t canRecPid;
@@ -211,7 +210,7 @@ void CANReceiver(int fd)
         ShmCHAdeMOData = (struct CHAdeMOData *)GetShmCHAdeMOData();
         ShmGBTData = (struct GBTData *)GetShmGBTData();
         ShmCcsData = (struct CcsData *)GetShmCcsData();
-        ShmDcCommonData = (DcCommonInfo *)GetShmDcCommonInfo();
+        ShmDcCommonData = (DcCommonInfo *)GetShmDcCommonData();
 
         while (isContinue) {
             memset(&frame, 0, sizeof(struct can_frame));
@@ -493,23 +492,26 @@ void CANReceiver(int fd)
                     //         pDcChargingInfo->ConnectorTemp);
                 }
 #endif //0
-                //log_info("EvboardStatus = %x \n",
-                //         ShmCHAdeMOData->evse[gunTypeIndex].EvboardStatus);
-                //log_info("ConnectorPlug locked = %x \n",
-                //         frame.data[0]);
-
-                //if (frame.data[1] >= GUN_OTP_VALUE ||
-                //        frame.data[2] >= GUN_OTP_VALUE ||
-                //        chiilerTemp.Temp[0] >= GUN_OTP_VALUE ||
-                //        chiilerTemp.Temp[1] >= GUN_OTP_VALUE) {
-                //    log_info("Conn %d Temp 0= %d, Temp 1 = %d, chillerTemp1 = %d, chillerTemp2 = %d\r\n",
-                //             targetGun,
-                //             frame.data[1],
-                //             frame.data[2],
-                //             chiilerTemp.Temp[0],
-                //             chiilerTemp.Temp[1]);
-                //}
-                //log_info("PilotVoltage = %x \n", (-120 + frame.data[3]) / 10);
+                if (ShmDcCommonData->SystemModeChange == YES) {
+                    ShmDcCommonData->SystemModeChange = NO;
+                    //log_info("EvboardStatus = %x \n",
+                    //         ShmCHAdeMOData->evse[gunTypeIndex].EvboardStatus);
+                    //log_info("ConnectorPlug locked = %x \n",
+                    //         frame.data[0]);
+
+                    //if (frame.data[1] >= GUN_OTP_VALUE ||
+                    //        frame.data[2] >= GUN_OTP_VALUE ||
+                    //        chiilerTemp.Temp[0] >= GUN_OTP_VALUE ||
+                    //        chiilerTemp.Temp[1] >= GUN_OTP_VALUE) {
+                    log_info("Conn %d Temp 0= %d, Temp 1 = %d, chillerTemp1 = %d, chillerTemp2 = %d\r\n",
+                             targetGun,
+                             frame.data[1],
+                             frame.data[2],
+                             chiilerTemp.Temp[0],
+                             chiilerTemp.Temp[1]);
+                    //}
+                    //log_info("PilotVoltage = %x \n", (-120 + frame.data[3]) / 10);
+                }
                 break;
 
             case ACK_EVSE_ISOLATION_STATUS:

+ 2 - 2
EVSE/Projects/DD360ComBox/Apps/ModuleEvComm/Module_EvTxComm.c

@@ -484,7 +484,7 @@ static void checkConnectorOVPState(uint8_t gunIndex)
     struct ChargingInfoData *pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex);
 
     // 避免槍溫偵測誤判
-    static uint8_t gunTempAllowCount[2] = {0, 0};
+    static uint8_t gunTempAllowCount[2] = {0};
     bool isOTP = false;
 
     switch (pDcChargingInfo->Type) {
@@ -593,7 +593,7 @@ int main(int argc, char *argv[])
     pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
     pAlarmCode = (struct AlarmCodeData *)GetShmAlarmCodeData();
     pFaultCode = (struct FaultCodeData *)GetShmFaultCodeData();
-    ShmDcCommonData = (DcCommonInfo *)GetShmDcCommonInfo();
+    ShmDcCommonData = (DcCommonInfo *)GetShmDcCommonData();
     ShmCHAdeMOData = (struct CHAdeMOData *)GetShmCHAdeMOData();
     ShmGBTData = (struct GBTData *)GetShmGBTData();
     ShmCcsData = (struct CcsData *)GetShmCcsData();

+ 2 - 1
EVSE/Projects/DD360ComBox/Apps/ModuleInternalComm/RelayBoard.c

@@ -1131,7 +1131,7 @@ void RelayBoardTask(int uartFD)
         pAlarmCode = (struct AlarmCodeData *)GetShmAlarmCodeData();
         ShmRelayModuleData = (struct RelayModuleData *)GetShmRelayModuleData();
         ShmPsuData = (struct PsuData *)GetShmPsuData();
-        ShmDcCommonData = (DcCommonInfo *)GetShmDcCommonInfo();
+        ShmDcCommonData = (DcCommonInfo *)GetShmDcCommonData();
         ShmPrimaryMcuData = (struct PrimaryMcuData *)GetShmPrimaryMcuData();
 
         Uart5Fd = uartFD;
@@ -1284,6 +1284,7 @@ void RelayBoardTask(int uartFD)
                     //regRelay.relay_event.bits.Gun1_Parallel_N = outputRelay.relay_event.bits.Gun1_Parallel_N;
 
                     //MatchRelayStatus();
+
                     //log_info("Match Relay, AC = %x, g1_p = %x, g1_n = %x, g2_p = %x, g2_n = %x, pre = %x, bri_p = %x, bri_n = %x \n",
                     //         regRelay.relay_event.bits.AC_Contactor,
                     //         regRelay.relay_event.bits.Gun1_P,

+ 22 - 12
EVSE/Projects/DD360ComBox/Apps/ShareMemory/shmMem.c

@@ -40,7 +40,7 @@ static struct LedModuleData *ShmLedModuleData = NULL;
 static struct OCPP16Data *ShmOCPP16Data = NULL;
 
 static SelectGunInfo *ShmSelectGunInfo = NULL;
-static DcCommonInfo *ShmDcCommonInfo = NULL;
+static DcCommonInfo *ShmDcCommonData = NULL;
 
 static struct ChargingInfoData *DcChargingData[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY] = {NULL};
 static struct ChargingInfoData *AcChargingData[AC_QUANTITY] = {NULL};
@@ -51,7 +51,7 @@ static GunIndexInfo gGunIndexInfo = {0};
 //struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
 //struct WARNING_CODE_INFO *pSysWarning = (struct WARNING_CODE_INFO *)GetShmSysWarningInfo();
 
-//struct AlarmCodeData *pAlarmCode =(struct AlarmCodeData *)GetShmAlarmCodeData();
+//struct AlarmCodeData *pAlarmCode = (struct AlarmCodeData *)GetShmAlarmCodeData();
 //struct InfoCodeData *pInfoCode = (struct InfoCodeData *)GetShmInfoCodeData();
 //struct FaultCodeData *pFaultCode = (struct FaultCodeData *)GetShmFaultCodeData();
 
@@ -68,7 +68,10 @@ static GunIndexInfo gGunIndexInfo = {0};
 //struct OCPP16Data *ShmOCPP16Data = (struct OCPP16Data *)GetShmOCPP16Data();
 
 //SelectGunInfo *ShmSelectGunInfo = (SelectGunInfo *)GetShmSelectGunInfo();
-//DcCommonInfo *ShmDcCommonInfo = (DcCommonInfo *)GetShmDcCommonInfo();
+//DcCommonInfo *ShmDcCommonData = (DcCommonInfo *)GetShmDcCommonData();
+
+//struct ChargingInfoData *pDcChargingInfo = NULL;
+//struct ChargingInfoData *pAcChargingInfo = NULL;
 
 //------------------------------------------------------------------------------
 void *GetGunIndexInfo(void)
@@ -306,17 +309,17 @@ void *GetShmSelectGunInfo(void)
     return ShmSelectGunInfo;
 }
 
-void *GetShmDcCommonInfo(void)
+void *GetShmDcCommonData(void)
 {
-    if (ShmDcCommonInfo == NULL) {
+    if (ShmDcCommonData == NULL) {
         return NULL;
     }
 
-    return ShmDcCommonInfo;
+    return ShmDcCommonData;
 }
 
 //------------------------------------------------------------------------------
-/*static void initialGunIndexToUnUse(void)
+static void initialGunIndexToUnUse(void)
 {
     uint8_t index = 0;
     struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
@@ -337,7 +340,6 @@ void *GetShmDcCommonInfo(void)
         pSysInfo->AcChargingData[index].Index = NO_DEFINE;
     }
 }
-*/
 
 #if 0
 static void getFirmwareVersion(void)
@@ -424,7 +426,7 @@ static void getFirmwareVersion(void)
 }
 #endif //0
 
-void InitialShareMemoryParameter(void)
+void InitialShareMemoryInfo(void)
 {
     FILE *fp = NULL;
     char cmd[512] = {0};
@@ -532,7 +534,15 @@ void InitialShareMemoryParameter(void)
     pAlarmCode->AlarmEvents.bits.ModelNameNoneMatchStestFail = NO;
     pAlarmCode->AlarmEvents.bits.PsuNoResource = NO;
     pAlarmCode->AlarmEvents.bits.FailToCreateShareMemory = NO;
-    //initialGunIndexToUnUse();//DS60-120 add
+
+    initialGunIndexToUnUse();//DS60-120 add
+
+    //ShmDcCommonData->CcsVersion = _CCS_VERSION_CHECK_TAG_V015S0;
+    //ShmDcCommonData->psuKeepCommunication = NO;
+    //ShmDcCommonData->acContactSwitch = NO;
+    ShmDcCommonData->ConnectErrList[0].GunErrMessage = 0;
+    ShmDcCommonData->ConnectErrList[1].GunErrMessage = 0;
+    //ShmDcCommonData->LcmFwVersion = 0;
 }
 
 int InitSelectGunShmMem(void)
@@ -558,7 +568,7 @@ int InitCommonShmMem(void)
 
     if ((MeterSMId = shmget(ShmCommonKey, sizeof(DcCommonInfo), IPC_CREAT | 0777)) < 0) {
         return FAIL;
-    } else if ((ShmDcCommonInfo = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
+    } else if ((ShmDcCommonData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
         return FAIL;
     }
 
@@ -750,7 +760,7 @@ void ClearAllShmMemParameter(void)
     //memset(ShmOCPP16Data,0,sizeof(struct OCPP16Data));
 
     //memset(ShmCsuMeterInfo, 0, sizeof(struct MeterInformation));
-    memset(ShmDcCommonInfo, 0, sizeof(DcCommonInfo));
+    memset(ShmDcCommonData, 0, sizeof(DcCommonInfo));
 
 #if defined DD360 || defined DD360Audi || defined DD360ComBox
     memset(ShmSelectGunInfo, 0, sizeof(SelectGunInfo));

+ 1 - 4
EVSE/Projects/DD360ComBox/Apps/ShareMemory/shmMem.h

@@ -28,7 +28,7 @@ bool MappingGunChargingInfo(char *whichTask);
 
 int CreateAllCsuShareMemory(void);
 void ClearAllShmMemParameter(void);
-void InitialShareMemoryParameter(void);
+void InitialShareMemoryInfo(void);
 
 void SetDcChargingInfoData(uint8_t index, struct ChargingInfoData *chargingInfoIndex);
 void *GetDcChargingInfoData(uint8_t index);
@@ -66,8 +66,5 @@ void MappingChargingInfoData(void);
 
 void *GetShmSelectGunInfo(void);
 
-void *GetShmDcCommonInfo(void);
-
-
 int InitSelectGunShmMem(void);
 #endif /* _CSU_SHARE_MEMORY_H_ */

+ 60 - 3
EVSE/Projects/DD360ComBox/Apps/main.c

@@ -27,12 +27,12 @@
 #include <ctype.h>
 #include <ifaddrs.h>
 #include <math.h>
-#include "./Define/define.h"
+#include "../../define.h"
 #include <stdbool.h>
 #include <dirent.h>
 
 #include "Config.h"
-#include "main.h"
+//#include "main.h"
 #include "common.h"
 #include "timeout.h"
 
@@ -40,6 +40,62 @@
 #include "./SelectGun/SelectGun.h"
 #endif //defined DD360Audi
 
+//------------------------------------------------------------------------------
+#define MODELNAME_FAIL                          0
+#define BUFFER_SIZE                             128
+#define BTN_RELEASE                             0
+#define BTN_PRESS                               1
+#define MAX_BUF                                 64
+#define MtdBlockSize                            0x600000
+#define SYSFS_GPIO_DIR                          "/sys/class/gpio"
+#define UPGRADE_FAN                             0x02
+#if defined DD360 ||defined DD360Audi || defined DD360ComBox
+#define UPGRADE_RB                              0x09 //0x09 for DD360 dispenser
+#else
+#define UPGRADE_RB                              0x03 //other module use
+#endif //defined DD360 || defined DD360Audi
+#define UPGRADE_PRI                             0x04
+#define UPGRADE_AC                              0x05
+#define UPGRADE_LED                             0x06
+#define SYSTEM_MIN_VOL                          80 //150
+#define MIN_OUTPUT_CUR                          0
+#define AC_OUTPUT_VOL                           220
+
+#define DEFAULT_AC_INDEX                        2
+#define PSU_MIN_CUR                             100
+
+#define DB_FILE                                 "/Storage/ChargeLog/localCgargingRecord.db"
+
+#define uSEC_VAL                                1000000
+#define SELFTEST_TIMEOUT                        60//45
+#define AUTHORIZE_TIMEOUT                       15//30
+#define AUTHORIZE_COMP_TIMEOUT                  3
+#define AUTHORIZE_FAIL_TIMEOUT                  3
+#define AUTHORIZE_STOP_TIMEOUT                  30
+#define RETURN_TO_CHARGING_PAGE                 30
+#define GUN_PREPARE_TIMEOUT                     30
+#define GUN_EV_WAIT_TIMEOUT                     120
+#define GUN_EVSE_WAIT_TIMEOUT                   60
+#define GUN_COMP_WAIT_TIMEOUT                   10
+#define GUN_PRECHARGING_TIMEOUT                 60
+
+#define log_info(format, args...) StoreLogMsg_1("[%s:%d][%s][Info] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+#define log_warn(format, args...) StoreLogMsg_1("[%s:%d][%s][Warn] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+#define log_error(format, args...) StoreLogMsg_1("[%s:%d][%s][Error] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+
+//------------------------------------------------------------------------------
+typedef struct StLedConfig {
+    //OutputDrvValue[0]
+    uint8_t LeftButtonLed: 1;                   //bit 0,    H: ON,      L:OFF
+    uint8_t RightButtonLed: 1;                  //bit 1,    H: ON,      L:OFF
+    uint8_t GreenLED: 1;                        //bit 2,    H: ON,      L:OFF
+    uint8_t YellowLED: 1;                       //bit 3,    H: ON,      L:OFF
+    uint8_t RedLED: 1;                          //bit 4,    H: ON,      L:OFF
+    uint8_t SystemLed4: 1;                      //bit 5,    H: ON,      L:OFF
+    uint8_t AcContactor: 1;                     //bit 6,    H: ON,      L:OFF
+    uint8_t Reserved: 1;                        //bit 7 reserved
+} LedConfig;
+
 //------------------------------------------------------------------------------
 char *valid_Internet[2] = {"8.8.8.8", "180.76.76.76"};
 uint8_t mask_table[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
@@ -306,7 +362,8 @@ static void checkGunOTPState(uint8_t _index)
     case _Type_CCS_2:
         // CCS 不管甚麼輸出都會有槍溫偵測!!~
         if (chargingInfo[_index]->ConnectorTemp != UNDEFINED_TEMP) {
-            ResetChargerAlarmCode(_index, "011019");
+            ResetChargerAlarmCode(_index, "011019"); //清除溫度檢測異常status code
+
             if (chargingInfo[_index]->ConnectorTemp >= GUN_OTP_VALUE) {
                 RecordAlarmCode(_index, "012230");
             } else if (chargingInfo[_index]->ConnectorTemp != 0 &&

Some files were not shown because too many files changed in this diff