Explorar el Código

[Bug fixed][DM30][DW30][OCPP]: The behavior of OCPP remote control and data transfer is not correct.

2020.06.08 / TC Hsu

Actions: Merge OCPP relate modify from alston, which is based on Noodoe's OCPP test items. Include remote soft/hard reset, remote start/stop charging, authorize behavior based on remote and local RFID, connectors available/unavailable state change in status notification message.

Image version    : N/A
Image checksum   : N/A

Hardware PWB P/N : N/A
Hardware Version : N/A

Files:

	modified:   EVSE/Projects/DM30/Apps/Makefile
	modified:   EVSE/Projects/DM30/Apps/main.c
	modified:   EVSE/Projects/DM30/Apps/timeout.h
	modified:   EVSE/Projects/DW30/Apps/Makefile
	modified:   EVSE/Projects/DW30/Apps/main.c
	modified:   EVSE/Projects/DW30/Apps/timeout.h
TC_Hsu hace 4 años
padre
commit
8094dbdfa3

+ 3 - 2
EVSE/Projects/DM30/Apps/Makefile

@@ -3,6 +3,7 @@ export PATH=/bin:/sbin:/usr/bin:$(SDK_PATH_TARGET)/usr/bin:$PATH
 
 #define library variable
 Internal485ProtocolLib = -L ../../../Modularization/Internal485Protocol -lInternal485Protocol
+Lib_SQLite3 = "-L../../../Modularization/ocppfiles" -lsqlite3
 
 all: CreateOutputFolder BuildFactorys BuildApps CopyExecuteFiles Clean
 
@@ -11,9 +12,9 @@ BuildFactorys: FactoryConfigBin
 BuildApps: MainTask EvCommTask EventLoggingTask InternalCommTask LcmControlTask PrimaryCommTask PsuCommTask ReadCmdlineTask FactoryConfigApp
 
 MainTask:
-	$(CC) -D $(Project) -D DEBUG_OPTION=$(Project_Debug_Option) -include../../../Modularization/Module_RFID.h -include../../../Modularization/Module_Upgrade.h -O0 -g3 -Wall -c -fmessage-length=0 -o main.o main.c
+	$(CC) -D $(Project) -D DEBUG_OPTION=$(Project_Debug_Option) -include../../../Modularization/ocppfiles/sqlite3.h -include../../../Modularization/Module_RFID.h -include../../../Modularization/Module_Upgrade.h -O0 -g3 -Wall -c -fmessage-length=0 -o main.o main.c
 	$(CC) -D $(Project) -D DEBUG_OPTION=$(Project_Debug_Option) -O0 -g3 -Wall -c -fmessage-length=0 -o timeout.o timeout.c
-	$(CC) -o main main.o timeout.o ../../../Modularization/libModule_RFID.a ../../../Modularization/libModule_Upgrade.a
+	$(CC) -o main main.o timeout.o ../../../Modularization/libModule_RFID.a ../../../Modularization/libModule_Upgrade.a ${Lib_SQLite3}
 
 EvCommTask:
 	$(CC) -D $(Project) -D DEBUG_OPTION=$(Project_Debug_Option) -includeConfig.h -O0 -g3 -Wall -c -fmessage-length=0 -o Ev_Comm.o Ev_Comm.c

+ 479 - 9
EVSE/Projects/DM30/Apps/main.c

@@ -57,10 +57,13 @@
 #define NO_DEFINE           255
 #define DEFAULT_AC_INDEX    2
 
+#define DB_FILE             "/Storage/ChargeLog/localCgargingRecord.db"
+
 char    *valid_Internet[2] = {"8.8.8.8", "180.76.76.76"};
 unsigned char mask_table[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
 int whileLoopTime = 10000; // 10 ms
 int wtdFd = -1;
+byte _authorizeIndex = NO_DEFINE;
 
 bool IsAuthorizingMode();
 void ClearAuthorizedFlag();
@@ -87,6 +90,11 @@ void RecordWarningCode(byte gunIndex, char *code);
 void ReleaseWarningCodeByString(byte gunIndex, char *code);
 void ReleaseAlarmCode(byte gunIndex);
 
+int DB_Open(sqlite3 *db);
+int DB_Insert_Record(sqlite3 *db, int gun_index);
+int DB_Update_Operactive(sqlite3 *db, uint8_t gun_index, uint8_t IsAvailable);
+int DB_Get_Operactive(sqlite3 *db, uint8_t gun_index);
+
 #define DEBUG_INFO_MSG(format, args...) StoreLogMsg_1("[%s:%d][%s][Info] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
 #define DEBUG_WARN_MSG(format, args...) StoreLogMsg_1("[%s:%d][%s][Warn] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
 #define DEBUG_ERROR_MSG(format, args...) StoreLogMsg_1("[%s:%d][%s][Error] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
@@ -127,6 +135,194 @@ int rfidFd = -1;
 char* rfidPortName = "/dev/ttyS2";
 char* fwVersion = "D5.14.00.0000.00";
 
+sqlite3 *localDb;
+bool isDb_ready;
+
+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);";
+
+    if(sqlite3_open(DB_FILE, &db))
+    {
+        result = FAIL;
+        PRINTF_FUNC( "Can't open database: %s\r\n", sqlite3_errmsg(db));
+        sqlite3_close(db);
+    }
+    else
+    {
+        PRINTF_FUNC( "Local charging record database open successfully.\r\n");
+
+        if (sqlite3_exec(db, createRecordSql, 0, 0, &errMsg) != SQLITE_OK)
+        {
+            result = FAIL;
+            PRINTF_FUNC( "Create local charging record table error message: %s\n", errMsg);
+        }
+        else
+        {
+            PRINTF_FUNC( "Opened local charging record table successfully\n");
+        }
+
+        if (sqlite3_exec(db, createCfgSql, 0, 0, &errMsg) != SQLITE_OK)
+        {
+            result = FAIL;
+            PRINTF_FUNC( "Create local config table error message: %s\n", errMsg);
+        }
+        else
+        {
+            PRINTF_FUNC( "Opened local config 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];
+
+    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');",
+            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,
+            ShmOCPP16Data->StopTransaction[gun_index].StopReason);
+
+    if(sqlite3_open("/Storage/ChargeLog/localCgargingRecord.db", &db))
+    {
+        result = FAIL;
+        PRINTF_FUNC( "Can't open database: %s\r\n", sqlite3_errmsg(db));
+        sqlite3_close(db);
+    }
+    else
+    {
+        PRINTF_FUNC( "Local charging record database open successfully.\r\n");
+        if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK)
+        {
+            result = FAIL;
+            PRINTF_FUNC( "Insert local charging record error message: %s\n", errMsg);
+        }
+        else
+        {
+            PRINTF_FUNC( "Insert 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;
+        PRINTF_FUNC( "Can't open database: %s\r\n", sqlite3_errmsg(db));
+        sqlite3_close(db);
+    }
+    else
+    {
+        PRINTF_FUNC( "Local charging record database open successfully.\r\n");
+
+        sprintf(sqlStr, "insert or replace into config (IsAvailable, connector, val) values('IsAvailable', %d, %d);", gun_index, IsAvailable);
+
+        PRINTF_FUNC("sqlStr= %s\r\n", sqlStr);
+
+        if (sqlite3_exec(db, sqlStr, 0, 0, &errMsg) != SQLITE_OK)
+        {
+            result = FAIL;
+            PRINTF_FUNC( "update config error message: %s\n", errMsg);
+        }
+        else
+        {
+            PRINTF_FUNC("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);
+    //DEBUG_INFO("sqlStr= %s\r\n", sqlStr);
+
+    if(sqlite3_open(DB_FILE, &db))
+    {
+        result = FAIL;
+        PRINTF_FUNC( "Can't open database: %s\r\n", sqlite3_errmsg(db));
+        sqlite3_close(db);
+    }
+    else
+    {
+        PRINTF_FUNC( "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;
+                }
+                PRINTF_FUNC("Query connector-%d isOperactive: %s\r\n", gun_index, rs[(idxRow*cols)+3]);
+            }
+        }
+        else
+        {
+            PRINTF_FUNC("Query connector-%d fail, set default value to operactive.\r\n", gun_index);
+        }
+
+        sqlite3_free_table(rs);
+        sqlite3_close(db);
+    }
+
+    return result;
+}
+
 //================================================
 // initial can-bus
 //================================================
@@ -1152,6 +1348,7 @@ void InitialShareMemoryInfo()
     ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_NONE;
     ShmSysConfigAndInfo->SysInfo.MainChargingMode = _MAIN_CHARGING_MODE_MAX;
     ShmSysConfigAndInfo->SysInfo.ReAssignedFlag = _REASSIGNED_NONE;
+    ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc = NO_DEFINE;
 
     ShmFanModuleData->TestFanSpeed = 0;
 
@@ -1252,7 +1449,7 @@ bool InitialSystemDefaultConfig()
 //  sleep(3);
 //  system("/sbin/ifconfig eth0 192.168.1.10 netmask 255.255.255.0 down");
 //  sleep(1);
-//  system("/sbin/ifconfig eth0 192.168.1.10 netmask 255.255.255.0 up");
+//  system("/sbin/ifconfig eth1 192.168.0.10 netmask 255.255.255.0 up");
 
     return result;
 }
@@ -2593,11 +2790,28 @@ void UserScanFunction()
                         chargingInfo[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->StartUserId, ShmSysConfigAndInfo->SysConfig.UserId);
                 memcpy(value, (unsigned char *)chargingInfo[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->StartUserId,
                         ARRAY_SIZE(chargingInfo[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->StartUserId));
+
+                // 同一張卡直接停掉
                 if (strcmp((char *)ShmSysConfigAndInfo->SysConfig.UserId, value) == EQUAL)
                 {
                     ChargingTerminalProcess(ShmSysConfigAndInfo->SysInfo.CurGunSelected);
+                    strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                }
+                else
+                {
+                    // 進驗證
+                    if (_acgunIndex > 0 && ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc == DEFAULT_AC_INDEX)
+                    {
+                        _authorizeIndex = ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc;
+                    }
+                    else
+                    {
+                        _authorizeIndex = ShmSysConfigAndInfo->SysInfo.CurGunSelected;
+                    }
+
+                    StartSystemTimeoutDet(Timeout_AuthorizingForStop);
+                    AuthorizingStart();
                 }
-                strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
             }
             else if (idleReq)
             {
@@ -2626,6 +2840,60 @@ void UserScanFunction()
             }
         }
     }
+    else
+    {
+        // 透過後臺停止充電的判斷
+        if (isAuthorizedComplete() || ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING)
+        {
+            // 判斷後台回覆狀態
+            if(canStartCharging() || ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING)
+            {
+                if (_authorizeIndex != NO_DEFINE)
+                {
+                    // 先找 AC
+                    if (_authorizeIndex == DEFAULT_AC_INDEX)
+                    {
+                        if (strcmp((char *)ac_chargingInfo[0]->StartUserId, (char *)ShmSysConfigAndInfo->SysConfig.UserId) == EQUAL)
+                        {
+                            AcChargingTerminalProcess();
+                        }
+                    }
+                    else
+                    {
+                        if (ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST &&
+                            strcmp((char *)chargingInfo[_authorizeIndex]->StartUserId, "") != EQUAL)
+                        {
+                            ChargingTerminalProcess(_authorizeIndex);
+                        }
+                    }
+
+                    strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                    _authorizeIndex = NO_DEFINE;
+                }
+            }
+            else
+                strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+
+            ClearAuthorizedFlag();
+        }
+        else if (ShmSysConfigAndInfo->SysConfig.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)
+                    {
+                        ChargingTerminalProcess(_authorizeIndex);
+                        strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                        ClearAuthorizedFlag();
+                        break;
+                    }
+                }
+            }
+        }
+    }
 }
 
 unsigned char isModeChange(unsigned char gun_index)
@@ -2669,6 +2937,7 @@ void ScannerCardProcess()
             {
                 // LCM => Authorize fail
                 ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_AUTHORIZ_FAIL;
+                strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
             }
             ClearAuthorizedFlag();
         }
@@ -2726,6 +2995,7 @@ bool AddGunInfoByConnector(byte typeValue, byte slots)
 
                 // AC 固定 index
                 ac_chargingInfo[_acgunIndex]->Index = 1;
+                ac_chargingInfo[_acgunIndex]->ReservationId = -1;
                 ac_chargingInfo[_acgunIndex]->SystemStatus = S_BOOTING;
                 ac_chargingInfo[_acgunIndex]->Type = _Type_AC;
                 ac_chargingInfo[_acgunIndex]->IsAvailable = YES;
@@ -2746,6 +3016,7 @@ bool AddGunInfoByConnector(byte typeValue, byte slots)
                 chargingInfo[_gunIndex] = &ShmSysConfigAndInfo->SysInfo.ChademoChargingData[_chademoIndex];
 
                 chargingInfo[_gunIndex]->Index = _gunIndex;
+                chargingInfo[_gunIndex]->ReservationId = -1;
                 chargingInfo[_gunIndex]->slotsIndex = slots;
                 chargingInfo[_gunIndex]->SystemStatus = S_BOOTING;
                 chargingInfo[_gunIndex]->Type = _Type_Chademo;
@@ -2766,6 +3037,7 @@ bool AddGunInfoByConnector(byte typeValue, byte slots)
                 chargingInfo[_gunIndex] = &ShmSysConfigAndInfo->SysInfo.CcsChargingData[_ccsIndex];
 
                 chargingInfo[_gunIndex]->Index =    _gunIndex;
+                chargingInfo[_gunIndex]->ReservationId = -1;
                 chargingInfo[_gunIndex]->slotsIndex = slots;
                 chargingInfo[_gunIndex]->SystemStatus = S_BOOTING;
                 chargingInfo[_gunIndex]->Type = _Type_CCS_2;
@@ -2787,6 +3059,7 @@ bool AddGunInfoByConnector(byte typeValue, byte slots)
                 chargingInfo[_gunIndex] = &ShmSysConfigAndInfo->SysInfo.GbChargingData[_gb_Index];
 
                 chargingInfo[_gunIndex]->Index =    _gunIndex;
+                chargingInfo[_gunIndex]->ReservationId = -1;
                 chargingInfo[_gunIndex]->slotsIndex = slots;
                 chargingInfo[_gunIndex]->SystemStatus = S_BOOTING;
                 chargingInfo[_gunIndex]->Type = _Type_GB;
@@ -2992,7 +3265,7 @@ void KillTask()
     system("killall Module_LcmControl");
     system("killall Module_InternalComm");
     system("killall Module_PsuComm");
-    system("killall OcppBackend &");
+    //system("killall OcppBackend &");
     system("killall Module_4g &");
     system("killall Module_Wifi &");
 }
@@ -3283,6 +3556,29 @@ void StopGunInfoTimeoutDet(unsigned char gunIndex)
     }
 }
 
+void CheckConnectionTimeout()
+{
+    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;
@@ -3290,8 +3586,17 @@ void CreateTimeoutFork()
     timeoutPid = fork();
     if (timeoutPid > 0)
     {
+        gettimeofday(&_cmdSubPriority_time, NULL);
+        CheckConnectionTimeout();
+
         while(true)
         {
+            if ((GetTimeoutValue(_cmdSubPriority_time) / 1000) > 5000)
+            {
+                CheckConnectionTimeout();
+                gettimeofday(&_cmdSubPriority_time, NULL);
+            }
+
             //printf("Timeout ***********SystemTimeoutFlag = %d, ********\n", ShmSysConfigAndInfo->SysInfo.SystemTimeoutFlag);
             // 系統
             switch(ShmSysConfigAndInfo->SysInfo.SystemTimeoutFlag)
@@ -3325,7 +3630,7 @@ void CreateTimeoutFork()
                     }
                     break;
                 case Timeout_WaitPlug:
-                    if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) >= 40000000)
+                    if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) >= _connectionTimeout * 1000000)
                     {
                         _DetectPlugInTimeout();
                         StopSystemTimeoutDet();
@@ -3340,6 +3645,16 @@ void CreateTimeoutFork()
                     }
                 }
                     break;
+                case Timeout_AuthorizingForStop:
+                {
+                    if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) >= 30000000)
+                    {
+                        strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                        ClearAuthorizedFlag();
+                        StopSystemTimeoutDet();
+                    }
+                }
+                    break;
             }
             // 各槍
             for (byte gun_index = 0; gun_index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; gun_index++)
@@ -3480,21 +3795,21 @@ void CheckFwUpdateFunction()
         DEBUG_INFO_MSG("Backend : update start. \n");
         strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "");
         strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "Installing");
+        ShmOCPP16Data->SpMsg.bits.FirmwareStatusNotificationReq = YES;
         KillTask();
 
         if (CheckUpdateProcess() == PASS)
         {
             DEBUG_INFO_MSG("Backend : update complete. \n");
-            strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "");
             strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "Installed");
         }
         else
         {
             DEBUG_INFO_MSG("Backend : update fail. \n");
-            strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "");
             strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "InstallationFailed");
         }
 
+        strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "Installed");
         ShmOCPP16Data->SpMsg.bits.FirmwareStatusNotificationReq = YES;
         sleep(5);
         system("reboot -f");
@@ -3548,21 +3863,46 @@ void CheckOcppStatus()
 
     if (ShmOCPP16Data->MsMsg.bits.ResetReq == YES)
     {
+        bool canReset = true;
+        if (ShmSysConfigAndInfo->SysWarningInfo.Level != 2)
+        {
+            for (byte _index = 0; _index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _index++)
+            {
+                if (chargingInfo[_index]->SystemStatus != S_IDLE &&
+                    chargingInfo[_index]->SystemStatus != S_RESERVATION &&
+                    chargingInfo[_index]->SystemStatus != S_MAINTAIN)
+                {
+                    canReset = false;
+                    if (chargingInfo[_index]->SystemStatus >= S_REASSIGN && chargingInfo[_index]->SystemStatus < S_TERMINATING)
+                    {
+                        ChargingTerminalProcess(_index);
+                    }
+                }
+            }
+        }
+
+        if (canReset)
+        {
         ShmOCPP16Data->MsMsg.bits.ResetReq = NO;
+            sprintf((char*)ShmOCPP16Data->Reset.ResponseStatus, "Accepted");
         if(strcmp((char *)ShmOCPP16Data->Reset.Type, "Hard") == EQUAL)
         {
             DEBUG_ERROR_MSG("****** Hard Reboot ****** \n");
+                ShmOCPP16Data->MsMsg.bits.ResetConf = YES;
             sleep(3);
             system("reboot -f");
         }
         else if (strcmp((char *)ShmOCPP16Data->Reset.Type, "Soft") == EQUAL)
         {
             DEBUG_ERROR_MSG("****** Soft Reboot ****** \n");
+                ShmOCPP16Data->MsMsg.bits.ResetConf = YES;
             sleep(3);
+                system("killall OcppBackend &");
             KillTask();
             system("/usr/bin/run_evse_restart.sh");
         }
     }
+    }
 }
 
 void OcppStartTransation(byte gunIndex)
@@ -3591,7 +3931,10 @@ bool OcppRemoteStop(byte gunIndex)
 {
     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;
 }
@@ -3629,6 +3972,7 @@ void ChkOcppStatus(byte gunIndex)
             chargingInfo[gunIndex]->ReservationId = ShmOCPP16Data->ReserveNow[gunIndex].ReservationId;
             chargingInfo[gunIndex]->SystemStatus = S_RESERVATION;
         }
+        ShmOCPP16Data->CsMsg.bits[gunIndex].ReserveNowConf = YES;
     }
 
     if (chargingInfo[gunIndex]->SystemStatus == S_RESERVATION &&
@@ -3642,17 +3986,53 @@ void ChkOcppStatus(byte gunIndex)
             chargingInfo[gunIndex]->ReservationId = 0;
             chargingInfo[gunIndex]->SystemStatus = S_IDLE;
         }
+        ShmOCPP16Data->CsMsg.bits[gunIndex].CancelReservationConf = YES;
     }
 
     if (ShmOCPP16Data->CsMsg.bits[gunIndex].ChangeAvailabilityReq == YES)
     {
-        PRINTF_FUNC("***************ChkOcppStatus : OcppChangeAvailability******************** \n");
-        DEBUG_ERROR_MSG("***************ChkOcppStatus : OcppChangeAvailability******************** \n");
+        PRINTF_FUNC("***************ChkOcppStatus : OcppChangeAvailability to %s********************\n",ShmOCPP16Data->ChangeAvailability[gunIndex].Type);
+
         ShmOCPP16Data->CsMsg.bits[gunIndex].ChangeAvailabilityReq = NO;
         if(strcmp((char *)ShmOCPP16Data->ChangeAvailability[gunIndex].Type, "Operative") == EQUAL)
+        {
+            if (isDb_ready)
+            {
+                DB_Update_Operactive(localDb, gunIndex, YES);
+            }
+
             chargingInfo[gunIndex]->IsAvailable = YES;
+
+            if (chargingInfo[gunIndex]->SystemStatus == S_IDLE ||
+                chargingInfo[gunIndex]->SystemStatus == S_RESERVATION ||
+                chargingInfo[gunIndex]->SystemStatus == S_MAINTAIN)
+            {
+                setChargerMode(gunIndex, MODE_IDLE);
+            }
+        }
         else if (strcmp((char *)ShmOCPP16Data->ChangeAvailability[gunIndex].Type, "Inoperative") == EQUAL)
+        {
+            if (isDb_ready)
+            {
+                DB_Update_Operactive(localDb, gunIndex, NO);
+            }
+
             chargingInfo[gunIndex]->IsAvailable = NO;
+
+            if (chargingInfo[gunIndex]->SystemStatus == S_IDLE ||
+                chargingInfo[gunIndex]->SystemStatus == S_RESERVATION ||
+                chargingInfo[gunIndex]->SystemStatus == S_MAINTAIN)
+            {
+                setChargerMode(gunIndex, MODE_MAINTAIN);
+            }
+        }
+    }
+
+    if (ShmOCPP16Data->CsMsg.bits[gunIndex].UnlockConnectorReq == YES)
+    {
+        ShmOCPP16Data->CsMsg.bits[gunIndex].UnlockConnectorReq = NO;
+        strcpy((char *)ShmOCPP16Data->UnlockConnector[gunIndex].ResponseStatus, "NotSupported");
+        ShmOCPP16Data->CsMsg.bits[gunIndex].UnlockConnectorConf = YES;
     }
 }
 
@@ -3883,6 +4263,45 @@ void ClearAlarmCodeWhenAcOff()
     }
 }
 
+//==========================================
+// Check task processing
+//==========================================
+void CheckTask()
+{
+    if(ShmSysConfigAndInfo->SysConfig.ModelName[10] == 'T')
+    {
+        if(system("pidof -s Module_4g > /dev/null") != 0)
+        {
+            DEBUG_ERROR_MSG("Module_4g not running, restart it.\r\n");
+            system("/root/Module_4g &");
+        }
+    }
+    else if(ShmSysConfigAndInfo->SysConfig.ModelName[10] == 'W')
+    {
+        if(system("pidof -s Module_Wifi > /dev/null") != 0)
+        {
+            DEBUG_ERROR_MSG("Module_Wifi not running, restart it.\r\n");
+            system("/root/Module_Wifi &");
+        }
+    }
+
+    if(strcmp((char *)ShmSysConfigAndInfo->SysConfig.OcppServerURL, "") != EQUAL &&
+            strcmp((char *)ShmSysConfigAndInfo->SysConfig.ChargeBoxId, "") != EQUAL)
+    {
+        if(system("pidof -s OcppBackend > /dev/null") != 0)
+        {
+            DEBUG_ERROR_MSG("OcppBackend not running, restart it.\r\n");
+            system("/root/OcppBackend &");
+        }
+    }
+
+    if(system("pidof -s Module_ProduceUtils > /dev/null") != 0)
+    {
+        DEBUG_ERROR_MSG("Module_ProduceUtils not running, restart it.\r\n");
+        system ("/root/Module_ProduceUtils &");
+    }
+}
+
 int main(void)
 {
     if(CreateShareMemory() == 0)
@@ -3909,6 +4328,7 @@ int main(void)
         DEBUG_ERROR_MSG("InitialSystemDefaultConfig NG \n");
         StopProcessingLoop();
     }
+
     PRINTF_FUNC("CheckConnectorTypeStatus. \n");
     CheckGunTypeFromHw();
     PRINTF_FUNC("CheckIsAlternatvieByModelName. \n");
@@ -3962,6 +4382,20 @@ int main(void)
         }
     }
 
+// Local DB
+    if(DB_Open(localDb) != PASS)
+    {
+        PRINTF_FUNC("DB_Open fail. \n");
+        isDb_ready = false;
+    }
+    else
+    {
+        isDb_ready = true;
+
+        for(int _index=0; _index< ShmSysConfigAndInfo->SysConfig.TotalConnectorCount;_index++)
+            chargingInfo[_index]->IsAvailable = DB_Get_Operactive(localDb, _index);
+    }
+
     ChangeLcmByIndex(_LCM_IDLE);
     sleep(1);
     //***** 須新增的偵測 *****//
@@ -3972,6 +4406,7 @@ int main(void)
     //CreateWatchdog();
     // Main loop
     PRINTF_FUNC("Main Loop. \n");
+    gettimeofday(&_cmdMainPriority_time, NULL);
     for (;;)
     {
         CheckOcppStatus();
@@ -3996,6 +4431,12 @@ int main(void)
             ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_WAIT_FOR_PLUG;
         }
 
+        if ((GetTimeoutValue(_cmdMainPriority_time) / 1000) > 5000)
+        {
+            CheckTask();
+            gettimeofday(&_cmdMainPriority_time, NULL);
+        }
+
         for (byte gun_index = 0; gun_index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; gun_index++)
         {
             CheckGpioInStatus();
@@ -4007,6 +4448,7 @@ int main(void)
             {
                 case S_IDLE:
                 case S_RESERVATION:
+                case S_MAINTAIN:
                 {
                     if (chargingInfo[gun_index]->SystemStatus == S_IDLE &&
                         isModeChange(gun_index))
@@ -4014,6 +4456,7 @@ int main(void)
                         PRINTF_FUNC("S_IDLE================================== %x \n", gun_index);
                         chargingInfo[gun_index]->RemainChargingDuration = 0;
                         chargingInfo[gun_index]->PresentChargedEnergy = 0;
+                        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "");
                     }
                     else if (chargingInfo[gun_index]->SystemStatus == S_RESERVATION &&
                              isModeChange(gun_index))
@@ -4022,6 +4465,11 @@ int main(void)
                         ShmOCPP16Data->CsMsg.bits[gun_index].ReserveNowConf = YES;
                     }
 
+                    if (chargingInfo[gun_index]->IsAvailable == NO)
+                    {
+                        setChargerMode(gun_index, MODE_MAINTAIN);
+                    }
+
                     if (ShmSysConfigAndInfo->SysWarningInfo.Level == 2)
                     {
                         if (gun_index == ShmSysConfigAndInfo->SysInfo.CurGunSelected)
@@ -4088,6 +4536,7 @@ int main(void)
                                         ChangeGunSelectByIndex(ShmSysConfigAndInfo->SysInfo.OrderCharging);
                                         AddPlugInTimes(ShmSysConfigAndInfo->SysInfo.OrderCharging);
                                         setChargerMode(ShmSysConfigAndInfo->SysInfo.OrderCharging, MODE_REASSIGN_CHECK);
+                                        strcpy((char *)chargingInfo[(unsigned char)ShmSysConfigAndInfo->SysInfo.OrderCharging]->StartUserId, "");
                                         ClearDetectPluginFlag();
                                         continue;
                                     }
@@ -4225,6 +4674,9 @@ int main(void)
                                     ShmSysConfigAndInfo->SysInfo.ReAssignedFlag = _REASSIGNED_NONE;
                                 }
                             }
+
+                            if (ShmSysConfigAndInfo->SysInfo.CurGunSelected == gun_index)
+                                ShmSysConfigAndInfo->SysInfo.ConnectorPage = _LCM_PRE_CHARGE;
                             continue;
                         }
                     }
@@ -4250,7 +4702,10 @@ int main(void)
                     if (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag == _REASSIGNED_NONE ||
                         ShmSysConfigAndInfo->SysInfo.MainChargingMode == _MAIN_CHARGING_MODE_AVER)
                     {
+                        if (ShmSysConfigAndInfo->SysInfo.CanAverageCharging)
                         setChargerMode(gun_index, MODE_PRECHARGE);
+                        else
+                            setChargerMode(gun_index, MODE_IDLE);
                     }
                     else if (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag == _REASSIGNED_RELAY_M_TO_A &&
                         ShmSysConfigAndInfo->SysInfo.BridgeRelayStatus == NO)
@@ -4274,7 +4729,8 @@ int main(void)
                         StartGunInfoTimeoutDet(gun_index, Timeout_Preparing);
                     }
 
-                    if (ShmPsuData->SystemPresentPsuQuantity > 0 && ShmPsuData->SystemAvailablePower > 10)
+                    if (ShmPsuData->SystemPresentPsuQuantity > 0 && ShmPsuData->SystemAvailablePower > 10 &&
+                        GetTimeoutValue(chargingInfo[gun_index]->TimeoutTimer) >= 5000000)
                     {
                         setChargerMode(gun_index, MODE_PREPARE_FOR_EV);
                     }
@@ -4520,15 +4976,19 @@ int main(void)
                     if (isModeChange(gun_index))
                     {
                         PRINTF_FUNC ("terminating......................... %x \n", gun_index);
+                        if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "Remote") != EQUAL)
+                            strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "EVDisconnected");
                         StopGunInfoTimeoutDet(gun_index);
                     }
 
+                    bool toComplete = false;
                     if (chargingInfo[gun_index]->Type == _Type_Chademo)
                     {
                         // 非車端的停止 : 需等待小板送出停止指令,讓車端解除槍
                         if (isEvStopCharging_chademo(gun_index) == YES ||
                             isPrechargeStatus_chademo(gun_index) <= 0)
                         {
+                            toComplete = true;
                             setChargerMode(gun_index, MODE_COMPLETE);
                         }
                     }
@@ -4538,6 +4998,7 @@ int main(void)
                         if (isEvStopCharging_gb(gun_index) == YES ||
                             isPrechargeStatus_gb(gun_index) <= 0)
                         {
+                            toComplete = true;
                             setChargerMode(gun_index, MODE_COMPLETE);
                         }
                     }
@@ -4548,9 +5009,18 @@ int main(void)
                             (isPrechargeStatus_ccs(gun_index) >= 53 || isPrechargeStatus_ccs(gun_index) == 0 ||
                              isPrechargeStatus_ccs(gun_index) == 13 || isPrechargeStatus_ccs(gun_index) == 14))
                         {
+                            toComplete = true;
                             setChargerMode(gun_index, MODE_COMPLETE);
                         }
                     }
+
+                    if (!toComplete)
+                    {
+                        if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "Remote") != EQUAL)
+                            strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "Local");
+                    }
+
+
                     if (ShmSysConfigAndInfo->SysInfo.CurGunSelected == gun_index)
                         ShmSysConfigAndInfo->SysInfo.ConnectorPage = _LCM_COMPLETE;
                 }

+ 10 - 1
EVSE/Projects/DM30/Apps/timeout.h

@@ -32,6 +32,8 @@
 #include <ctype.h>
 #include <ifaddrs.h>
 
+#define CONN_PLUG_TIME_OUT          40
+
 enum Timeout_flag
 {
     Timeout_None =                      0,
@@ -46,7 +48,14 @@ enum Timeout_flag
     Timeout_EvseChargingDet =           8,
     Timeout_EvseCompleteDet =           9,
     Timeout_ForCcsPrechargeDet =        10,
-    Timeout_ReturnToChargingGunDet =    11
+    Timeout_ReturnToChargingGunDet =    11,
+    Timeout_AuthorizingForStop =        12
 };
 
+// for timeout fork
+struct timeval _cmdSubPriority_time;
+unsigned short _connectionTimeout;
+
+// for main
+struct timeval _cmdMainPriority_time;
 #endif /* TIMEOUT_H_ */

+ 3 - 2
EVSE/Projects/DW30/Apps/Makefile

@@ -3,6 +3,7 @@ export PATH=/bin:/sbin:/usr/bin:$(SDK_PATH_TARGET)/usr/bin:$PATH
 
 #define library variable
 Internal485ProtocolLib = -L ../../../Modularization/Internal485Protocol -lInternal485Protocol
+Lib_SQLite3 = "-L../../../Modularization/ocppfiles" -lsqlite3
 
 all: CreateOutputFolder BuildFactorys BuildApps CopyExecuteFiles Clean
 
@@ -11,9 +12,9 @@ BuildFactorys: FactoryConfigBin
 BuildApps: MainTask EvCommTask EventLoggingTask InternalCommTask LcmControlTask PrimaryCommTask PsuCommTask ReadCmdlineTask FactoryConfigApp
 
 MainTask:
-	$(CC) -D $(Project) -D DEBUG_OPTION=$(Project_Debug_Option) -include../../../Modularization/Module_RFID.h -include../../../Modularization/Module_Upgrade.h -O0 -g3 -Wall -c -fmessage-length=0 -o main.o main.c
+	$(CC) -D $(Project) -D DEBUG_OPTION=$(Project_Debug_Option) -include../../../Modularization/ocppfiles/sqlite3.h -include../../../Modularization/Module_RFID.h -include../../../Modularization/Module_Upgrade.h -O0 -g3 -Wall -c -fmessage-length=0 -o main.o main.c
 	$(CC) -D $(Project) -D DEBUG_OPTION=$(Project_Debug_Option) -O0 -g3 -Wall -c -fmessage-length=0 -o timeout.o timeout.c
-	$(CC) -o main main.o timeout.o ../../../Modularization/libModule_RFID.a ../../../Modularization/libModule_Upgrade.a
+	$(CC) -o main main.o timeout.o ../../../Modularization/libModule_RFID.a ../../../Modularization/libModule_Upgrade.a ${Lib_SQLite3}
 
 EvCommTask:
 	$(CC) -D $(Project) -D DEBUG_OPTION=$(Project_Debug_Option) -includeConfig.h -O0 -g3 -Wall -c -fmessage-length=0 -o Ev_Comm.o Ev_Comm.c

+ 479 - 9
EVSE/Projects/DW30/Apps/main.c

@@ -57,10 +57,13 @@
 #define NO_DEFINE           255
 #define DEFAULT_AC_INDEX    2
 
+#define DB_FILE             "/Storage/ChargeLog/localCgargingRecord.db"
+
 char    *valid_Internet[2] = {"8.8.8.8", "180.76.76.76"};
 unsigned char mask_table[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
 int whileLoopTime = 10000; // 10 ms
 int wtdFd = -1;
+byte _authorizeIndex = NO_DEFINE;
 
 bool IsAuthorizingMode();
 void ClearAuthorizedFlag();
@@ -87,6 +90,11 @@ void RecordWarningCode(byte gunIndex, char *code);
 void ReleaseWarningCodeByString(byte gunIndex, char *code);
 void ReleaseAlarmCode(byte gunIndex);
 
+int DB_Open(sqlite3 *db);
+int DB_Insert_Record(sqlite3 *db, int gun_index);
+int DB_Update_Operactive(sqlite3 *db, uint8_t gun_index, uint8_t IsAvailable);
+int DB_Get_Operactive(sqlite3 *db, uint8_t gun_index);
+
 #define DEBUG_INFO_MSG(format, args...) StoreLogMsg_1("[%s:%d][%s][Info] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
 #define DEBUG_WARN_MSG(format, args...) StoreLogMsg_1("[%s:%d][%s][Warn] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
 #define DEBUG_ERROR_MSG(format, args...) StoreLogMsg_1("[%s:%d][%s][Error] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
@@ -127,6 +135,194 @@ int rfidFd = -1;
 char* rfidPortName = "/dev/ttyS2";
 char* fwVersion = "D5.14.00.0000.00";
 
+sqlite3 *localDb;
+bool isDb_ready;
+
+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);";
+
+    if(sqlite3_open(DB_FILE, &db))
+    {
+        result = FAIL;
+        PRINTF_FUNC( "Can't open database: %s\r\n", sqlite3_errmsg(db));
+        sqlite3_close(db);
+    }
+    else
+    {
+        PRINTF_FUNC( "Local charging record database open successfully.\r\n");
+
+        if (sqlite3_exec(db, createRecordSql, 0, 0, &errMsg) != SQLITE_OK)
+        {
+            result = FAIL;
+            PRINTF_FUNC( "Create local charging record table error message: %s\n", errMsg);
+        }
+        else
+        {
+            PRINTF_FUNC( "Opened local charging record table successfully\n");
+        }
+
+        if (sqlite3_exec(db, createCfgSql, 0, 0, &errMsg) != SQLITE_OK)
+        {
+            result = FAIL;
+            PRINTF_FUNC( "Create local config table error message: %s\n", errMsg);
+        }
+        else
+        {
+            PRINTF_FUNC( "Opened local config 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];
+
+    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');",
+            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,
+            ShmOCPP16Data->StopTransaction[gun_index].StopReason);
+
+    if(sqlite3_open("/Storage/ChargeLog/localCgargingRecord.db", &db))
+    {
+        result = FAIL;
+        PRINTF_FUNC( "Can't open database: %s\r\n", sqlite3_errmsg(db));
+        sqlite3_close(db);
+    }
+    else
+    {
+        PRINTF_FUNC( "Local charging record database open successfully.\r\n");
+        if (sqlite3_exec(db, insertSql, 0, 0, &errMsg) != SQLITE_OK)
+        {
+            result = FAIL;
+            PRINTF_FUNC( "Insert local charging record error message: %s\n", errMsg);
+        }
+        else
+        {
+            PRINTF_FUNC( "Insert 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;
+        PRINTF_FUNC( "Can't open database: %s\r\n", sqlite3_errmsg(db));
+        sqlite3_close(db);
+    }
+    else
+    {
+        PRINTF_FUNC( "Local charging record database open successfully.\r\n");
+
+        sprintf(sqlStr, "insert or replace into config (IsAvailable, connector, val) values('IsAvailable', %d, %d);", gun_index, IsAvailable);
+
+        PRINTF_FUNC("sqlStr= %s\r\n", sqlStr);
+
+        if (sqlite3_exec(db, sqlStr, 0, 0, &errMsg) != SQLITE_OK)
+        {
+            result = FAIL;
+            PRINTF_FUNC( "update config error message: %s\n", errMsg);
+        }
+        else
+        {
+            PRINTF_FUNC("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);
+    //DEBUG_INFO("sqlStr= %s\r\n", sqlStr);
+
+    if(sqlite3_open(DB_FILE, &db))
+    {
+        result = FAIL;
+        PRINTF_FUNC( "Can't open database: %s\r\n", sqlite3_errmsg(db));
+        sqlite3_close(db);
+    }
+    else
+    {
+        PRINTF_FUNC( "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;
+                }
+                PRINTF_FUNC("Query connector-%d isOperactive: %s\r\n", gun_index, rs[(idxRow*cols)+3]);
+            }
+        }
+        else
+        {
+            PRINTF_FUNC("Query connector-%d fail, set default value to operactive.\r\n", gun_index);
+        }
+
+        sqlite3_free_table(rs);
+        sqlite3_close(db);
+    }
+
+    return result;
+}
+
 //================================================
 // initial can-bus
 //================================================
@@ -1152,6 +1348,7 @@ void InitialShareMemoryInfo()
     ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_NONE;
     ShmSysConfigAndInfo->SysInfo.MainChargingMode = _MAIN_CHARGING_MODE_MAX;
     ShmSysConfigAndInfo->SysInfo.ReAssignedFlag = _REASSIGNED_NONE;
+    ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc = NO_DEFINE;
 
     ShmFanModuleData->TestFanSpeed = 0;
 
@@ -1252,7 +1449,7 @@ bool InitialSystemDefaultConfig()
 //  sleep(3);
 //  system("/sbin/ifconfig eth0 192.168.1.10 netmask 255.255.255.0 down");
 //  sleep(1);
-//  system("/sbin/ifconfig eth0 192.168.1.10 netmask 255.255.255.0 up");
+//  system("/sbin/ifconfig eth1 192.168.0.10 netmask 255.255.255.0 up");
 
     return result;
 }
@@ -2593,11 +2790,28 @@ void UserScanFunction()
                         chargingInfo[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->StartUserId, ShmSysConfigAndInfo->SysConfig.UserId);
                 memcpy(value, (unsigned char *)chargingInfo[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->StartUserId,
                         ARRAY_SIZE(chargingInfo[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->StartUserId));
+
+                // 同一張卡直接停掉
                 if (strcmp((char *)ShmSysConfigAndInfo->SysConfig.UserId, value) == EQUAL)
                 {
                     ChargingTerminalProcess(ShmSysConfigAndInfo->SysInfo.CurGunSelected);
+                    strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                }
+                else
+                {
+                    // 進驗證
+                    if (_acgunIndex > 0 && ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc == DEFAULT_AC_INDEX)
+                    {
+                        _authorizeIndex = ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc;
+                    }
+                    else
+                    {
+                        _authorizeIndex = ShmSysConfigAndInfo->SysInfo.CurGunSelected;
+                    }
+
+                    StartSystemTimeoutDet(Timeout_AuthorizingForStop);
+                    AuthorizingStart();
                 }
-                strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
             }
             else if (idleReq)
             {
@@ -2626,6 +2840,60 @@ void UserScanFunction()
             }
         }
     }
+    else
+    {
+        // 透過後臺停止充電的判斷
+        if (isAuthorizedComplete() || ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING)
+        {
+            // 判斷後台回覆狀態
+            if(canStartCharging() || ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING)
+            {
+                if (_authorizeIndex != NO_DEFINE)
+                {
+                    // 先找 AC
+                    if (_authorizeIndex == DEFAULT_AC_INDEX)
+                    {
+                        if (strcmp((char *)ac_chargingInfo[0]->StartUserId, (char *)ShmSysConfigAndInfo->SysConfig.UserId) == EQUAL)
+                        {
+                            AcChargingTerminalProcess();
+                        }
+                    }
+                    else
+                    {
+                        if (ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST &&
+                            strcmp((char *)chargingInfo[_authorizeIndex]->StartUserId, "") != EQUAL)
+                        {
+                            ChargingTerminalProcess(_authorizeIndex);
+                        }
+                    }
+
+                    strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                    _authorizeIndex = NO_DEFINE;
+                }
+            }
+            else
+                strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+
+            ClearAuthorizedFlag();
+        }
+        else if (ShmSysConfigAndInfo->SysConfig.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)
+                    {
+                        ChargingTerminalProcess(_authorizeIndex);
+                        strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                        ClearAuthorizedFlag();
+                        break;
+                    }
+                }
+            }
+        }
+    }
 }
 
 unsigned char isModeChange(unsigned char gun_index)
@@ -2669,6 +2937,7 @@ void ScannerCardProcess()
             {
                 // LCM => Authorize fail
                 ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_AUTHORIZ_FAIL;
+                strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
             }
             ClearAuthorizedFlag();
         }
@@ -2726,6 +2995,7 @@ bool AddGunInfoByConnector(byte typeValue, byte slots)
 
                 // AC 固定 index
                 ac_chargingInfo[_acgunIndex]->Index = 1;
+                ac_chargingInfo[_acgunIndex]->ReservationId = -1;
                 ac_chargingInfo[_acgunIndex]->SystemStatus = S_BOOTING;
                 ac_chargingInfo[_acgunIndex]->Type = _Type_AC;
                 ac_chargingInfo[_acgunIndex]->IsAvailable = YES;
@@ -2746,6 +3016,7 @@ bool AddGunInfoByConnector(byte typeValue, byte slots)
                 chargingInfo[_gunIndex] = &ShmSysConfigAndInfo->SysInfo.ChademoChargingData[_chademoIndex];
 
                 chargingInfo[_gunIndex]->Index = _gunIndex;
+                chargingInfo[_gunIndex]->ReservationId = -1;
                 chargingInfo[_gunIndex]->slotsIndex = slots;
                 chargingInfo[_gunIndex]->SystemStatus = S_BOOTING;
                 chargingInfo[_gunIndex]->Type = _Type_Chademo;
@@ -2766,6 +3037,7 @@ bool AddGunInfoByConnector(byte typeValue, byte slots)
                 chargingInfo[_gunIndex] = &ShmSysConfigAndInfo->SysInfo.CcsChargingData[_ccsIndex];
 
                 chargingInfo[_gunIndex]->Index =    _gunIndex;
+                chargingInfo[_gunIndex]->ReservationId = -1;
                 chargingInfo[_gunIndex]->slotsIndex = slots;
                 chargingInfo[_gunIndex]->SystemStatus = S_BOOTING;
                 chargingInfo[_gunIndex]->Type = _Type_CCS_2;
@@ -2787,6 +3059,7 @@ bool AddGunInfoByConnector(byte typeValue, byte slots)
                 chargingInfo[_gunIndex] = &ShmSysConfigAndInfo->SysInfo.GbChargingData[_gb_Index];
 
                 chargingInfo[_gunIndex]->Index =    _gunIndex;
+                chargingInfo[_gunIndex]->ReservationId = -1;
                 chargingInfo[_gunIndex]->slotsIndex = slots;
                 chargingInfo[_gunIndex]->SystemStatus = S_BOOTING;
                 chargingInfo[_gunIndex]->Type = _Type_GB;
@@ -2992,7 +3265,7 @@ void KillTask()
     system("killall Module_LcmControl");
     system("killall Module_InternalComm");
     system("killall Module_PsuComm");
-    system("killall OcppBackend &");
+    //system("killall OcppBackend &");
     system("killall Module_4g &");
     system("killall Module_Wifi &");
 }
@@ -3283,6 +3556,29 @@ void StopGunInfoTimeoutDet(unsigned char gunIndex)
     }
 }
 
+void CheckConnectionTimeout()
+{
+    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;
@@ -3290,8 +3586,17 @@ void CreateTimeoutFork()
     timeoutPid = fork();
     if (timeoutPid > 0)
     {
+        gettimeofday(&_cmdSubPriority_time, NULL);
+        CheckConnectionTimeout();
+
         while(true)
         {
+            if ((GetTimeoutValue(_cmdSubPriority_time) / 1000) > 5000)
+            {
+                CheckConnectionTimeout();
+                gettimeofday(&_cmdSubPriority_time, NULL);
+            }
+
             //printf("Timeout ***********SystemTimeoutFlag = %d, ********\n", ShmSysConfigAndInfo->SysInfo.SystemTimeoutFlag);
             // 系統
             switch(ShmSysConfigAndInfo->SysInfo.SystemTimeoutFlag)
@@ -3325,7 +3630,7 @@ void CreateTimeoutFork()
                     }
                     break;
                 case Timeout_WaitPlug:
-                    if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) >= 40000000)
+                    if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) >= _connectionTimeout * 1000000)
                     {
                         _DetectPlugInTimeout();
                         StopSystemTimeoutDet();
@@ -3340,6 +3645,16 @@ void CreateTimeoutFork()
                     }
                 }
                     break;
+                case Timeout_AuthorizingForStop:
+                {
+                    if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) >= 30000000)
+                    {
+                        strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                        ClearAuthorizedFlag();
+                        StopSystemTimeoutDet();
+                    }
+                }
+                    break;
             }
             // 各槍
             for (byte gun_index = 0; gun_index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; gun_index++)
@@ -3480,21 +3795,21 @@ void CheckFwUpdateFunction()
         DEBUG_INFO_MSG("Backend : update start. \n");
         strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "");
         strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "Installing");
+        ShmOCPP16Data->SpMsg.bits.FirmwareStatusNotificationReq = YES;
         KillTask();
 
         if (CheckUpdateProcess() == PASS)
         {
             DEBUG_INFO_MSG("Backend : update complete. \n");
-            strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "");
             strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "Installed");
         }
         else
         {
             DEBUG_INFO_MSG("Backend : update fail. \n");
-            strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "");
             strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "InstallationFailed");
         }
 
+        strcpy((char *)ShmOCPP16Data->FirmwareStatusNotification.Status, "Installed");
         ShmOCPP16Data->SpMsg.bits.FirmwareStatusNotificationReq = YES;
         sleep(5);
         system("reboot -f");
@@ -3548,21 +3863,46 @@ void CheckOcppStatus()
 
     if (ShmOCPP16Data->MsMsg.bits.ResetReq == YES)
     {
+        bool canReset = true;
+        if (ShmSysConfigAndInfo->SysWarningInfo.Level != 2)
+        {
+            for (byte _index = 0; _index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _index++)
+            {
+                if (chargingInfo[_index]->SystemStatus != S_IDLE &&
+                    chargingInfo[_index]->SystemStatus != S_RESERVATION &&
+                    chargingInfo[_index]->SystemStatus != S_MAINTAIN)
+                {
+                    canReset = false;
+                    if (chargingInfo[_index]->SystemStatus >= S_REASSIGN && chargingInfo[_index]->SystemStatus < S_TERMINATING)
+                    {
+                        ChargingTerminalProcess(_index);
+                    }
+                }
+            }
+        }
+
+        if (canReset)
+        {
         ShmOCPP16Data->MsMsg.bits.ResetReq = NO;
+            sprintf((char*)ShmOCPP16Data->Reset.ResponseStatus, "Accepted");
         if(strcmp((char *)ShmOCPP16Data->Reset.Type, "Hard") == EQUAL)
         {
             DEBUG_ERROR_MSG("****** Hard Reboot ****** \n");
+                ShmOCPP16Data->MsMsg.bits.ResetConf = YES;
             sleep(3);
             system("reboot -f");
         }
         else if (strcmp((char *)ShmOCPP16Data->Reset.Type, "Soft") == EQUAL)
         {
             DEBUG_ERROR_MSG("****** Soft Reboot ****** \n");
+                ShmOCPP16Data->MsMsg.bits.ResetConf = YES;
             sleep(3);
+                system("killall OcppBackend &");
             KillTask();
             system("/usr/bin/run_evse_restart.sh");
         }
     }
+    }
 }
 
 void OcppStartTransation(byte gunIndex)
@@ -3591,7 +3931,10 @@ bool OcppRemoteStop(byte gunIndex)
 {
     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;
 }
@@ -3629,6 +3972,7 @@ void ChkOcppStatus(byte gunIndex)
             chargingInfo[gunIndex]->ReservationId = ShmOCPP16Data->ReserveNow[gunIndex].ReservationId;
             chargingInfo[gunIndex]->SystemStatus = S_RESERVATION;
         }
+        ShmOCPP16Data->CsMsg.bits[gunIndex].ReserveNowConf = YES;
     }
 
     if (chargingInfo[gunIndex]->SystemStatus == S_RESERVATION &&
@@ -3642,17 +3986,53 @@ void ChkOcppStatus(byte gunIndex)
             chargingInfo[gunIndex]->ReservationId = 0;
             chargingInfo[gunIndex]->SystemStatus = S_IDLE;
         }
+        ShmOCPP16Data->CsMsg.bits[gunIndex].CancelReservationConf = YES;
     }
 
     if (ShmOCPP16Data->CsMsg.bits[gunIndex].ChangeAvailabilityReq == YES)
     {
-        PRINTF_FUNC("***************ChkOcppStatus : OcppChangeAvailability******************** \n");
-        DEBUG_ERROR_MSG("***************ChkOcppStatus : OcppChangeAvailability******************** \n");
+        PRINTF_FUNC("***************ChkOcppStatus : OcppChangeAvailability to %s********************\n",ShmOCPP16Data->ChangeAvailability[gunIndex].Type);
+
         ShmOCPP16Data->CsMsg.bits[gunIndex].ChangeAvailabilityReq = NO;
         if(strcmp((char *)ShmOCPP16Data->ChangeAvailability[gunIndex].Type, "Operative") == EQUAL)
+        {
+            if (isDb_ready)
+            {
+                DB_Update_Operactive(localDb, gunIndex, YES);
+            }
+
             chargingInfo[gunIndex]->IsAvailable = YES;
+
+            if (chargingInfo[gunIndex]->SystemStatus == S_IDLE ||
+                chargingInfo[gunIndex]->SystemStatus == S_RESERVATION ||
+                chargingInfo[gunIndex]->SystemStatus == S_MAINTAIN)
+            {
+                setChargerMode(gunIndex, MODE_IDLE);
+            }
+        }
         else if (strcmp((char *)ShmOCPP16Data->ChangeAvailability[gunIndex].Type, "Inoperative") == EQUAL)
+        {
+            if (isDb_ready)
+            {
+                DB_Update_Operactive(localDb, gunIndex, NO);
+            }
+
             chargingInfo[gunIndex]->IsAvailable = NO;
+
+            if (chargingInfo[gunIndex]->SystemStatus == S_IDLE ||
+                chargingInfo[gunIndex]->SystemStatus == S_RESERVATION ||
+                chargingInfo[gunIndex]->SystemStatus == S_MAINTAIN)
+            {
+                setChargerMode(gunIndex, MODE_MAINTAIN);
+            }
+        }
+    }
+
+    if (ShmOCPP16Data->CsMsg.bits[gunIndex].UnlockConnectorReq == YES)
+    {
+        ShmOCPP16Data->CsMsg.bits[gunIndex].UnlockConnectorReq = NO;
+        strcpy((char *)ShmOCPP16Data->UnlockConnector[gunIndex].ResponseStatus, "NotSupported");
+        ShmOCPP16Data->CsMsg.bits[gunIndex].UnlockConnectorConf = YES;
     }
 }
 
@@ -3883,6 +4263,45 @@ void ClearAlarmCodeWhenAcOff()
     }
 }
 
+//==========================================
+// Check task processing
+//==========================================
+void CheckTask()
+{
+    if(ShmSysConfigAndInfo->SysConfig.ModelName[10] == 'T')
+    {
+        if(system("pidof -s Module_4g > /dev/null") != 0)
+        {
+            DEBUG_ERROR_MSG("Module_4g not running, restart it.\r\n");
+            system("/root/Module_4g &");
+        }
+    }
+    else if(ShmSysConfigAndInfo->SysConfig.ModelName[10] == 'W')
+    {
+        if(system("pidof -s Module_Wifi > /dev/null") != 0)
+        {
+            DEBUG_ERROR_MSG("Module_Wifi not running, restart it.\r\n");
+            system("/root/Module_Wifi &");
+        }
+    }
+
+    if(strcmp((char *)ShmSysConfigAndInfo->SysConfig.OcppServerURL, "") != EQUAL &&
+            strcmp((char *)ShmSysConfigAndInfo->SysConfig.ChargeBoxId, "") != EQUAL)
+    {
+        if(system("pidof -s OcppBackend > /dev/null") != 0)
+        {
+            DEBUG_ERROR_MSG("OcppBackend not running, restart it.\r\n");
+            system("/root/OcppBackend &");
+        }
+    }
+
+    if(system("pidof -s Module_ProduceUtils > /dev/null") != 0)
+    {
+        DEBUG_ERROR_MSG("Module_ProduceUtils not running, restart it.\r\n");
+        system ("/root/Module_ProduceUtils &");
+    }
+}
+
 int main(void)
 {
     if(CreateShareMemory() == 0)
@@ -3909,6 +4328,7 @@ int main(void)
         DEBUG_ERROR_MSG("InitialSystemDefaultConfig NG \n");
         StopProcessingLoop();
     }
+
     PRINTF_FUNC("CheckConnectorTypeStatus. \n");
     CheckGunTypeFromHw();
     PRINTF_FUNC("CheckIsAlternatvieByModelName. \n");
@@ -3962,6 +4382,20 @@ int main(void)
         }
     }
 
+// Local DB
+    if(DB_Open(localDb) != PASS)
+    {
+        PRINTF_FUNC("DB_Open fail. \n");
+        isDb_ready = false;
+    }
+    else
+    {
+        isDb_ready = true;
+
+        for(int _index=0; _index< ShmSysConfigAndInfo->SysConfig.TotalConnectorCount;_index++)
+            chargingInfo[_index]->IsAvailable = DB_Get_Operactive(localDb, _index);
+    }
+
     ChangeLcmByIndex(_LCM_IDLE);
     sleep(1);
     //***** 須新增的偵測 *****//
@@ -3972,6 +4406,7 @@ int main(void)
     //CreateWatchdog();
     // Main loop
     PRINTF_FUNC("Main Loop. \n");
+    gettimeofday(&_cmdMainPriority_time, NULL);
     for (;;)
     {
         CheckOcppStatus();
@@ -3996,6 +4431,12 @@ int main(void)
             ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_WAIT_FOR_PLUG;
         }
 
+        if ((GetTimeoutValue(_cmdMainPriority_time) / 1000) > 5000)
+        {
+            CheckTask();
+            gettimeofday(&_cmdMainPriority_time, NULL);
+        }
+
         for (byte gun_index = 0; gun_index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; gun_index++)
         {
             CheckGpioInStatus();
@@ -4007,6 +4448,7 @@ int main(void)
             {
                 case S_IDLE:
                 case S_RESERVATION:
+                case S_MAINTAIN:
                 {
                     if (chargingInfo[gun_index]->SystemStatus == S_IDLE &&
                         isModeChange(gun_index))
@@ -4014,6 +4456,7 @@ int main(void)
                         PRINTF_FUNC("S_IDLE================================== %x \n", gun_index);
                         chargingInfo[gun_index]->RemainChargingDuration = 0;
                         chargingInfo[gun_index]->PresentChargedEnergy = 0;
+                        strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "");
                     }
                     else if (chargingInfo[gun_index]->SystemStatus == S_RESERVATION &&
                              isModeChange(gun_index))
@@ -4022,6 +4465,11 @@ int main(void)
                         ShmOCPP16Data->CsMsg.bits[gun_index].ReserveNowConf = YES;
                     }
 
+                    if (chargingInfo[gun_index]->IsAvailable == NO)
+                    {
+                        setChargerMode(gun_index, MODE_MAINTAIN);
+                    }
+
                     if (ShmSysConfigAndInfo->SysWarningInfo.Level == 2)
                     {
                         if (gun_index == ShmSysConfigAndInfo->SysInfo.CurGunSelected)
@@ -4088,6 +4536,7 @@ int main(void)
                                         ChangeGunSelectByIndex(ShmSysConfigAndInfo->SysInfo.OrderCharging);
                                         AddPlugInTimes(ShmSysConfigAndInfo->SysInfo.OrderCharging);
                                         setChargerMode(ShmSysConfigAndInfo->SysInfo.OrderCharging, MODE_REASSIGN_CHECK);
+                                        strcpy((char *)chargingInfo[(unsigned char)ShmSysConfigAndInfo->SysInfo.OrderCharging]->StartUserId, "");
                                         ClearDetectPluginFlag();
                                         continue;
                                     }
@@ -4225,6 +4674,9 @@ int main(void)
                                     ShmSysConfigAndInfo->SysInfo.ReAssignedFlag = _REASSIGNED_NONE;
                                 }
                             }
+
+                            if (ShmSysConfigAndInfo->SysInfo.CurGunSelected == gun_index)
+                                ShmSysConfigAndInfo->SysInfo.ConnectorPage = _LCM_PRE_CHARGE;
                             continue;
                         }
                     }
@@ -4250,7 +4702,10 @@ int main(void)
                     if (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag == _REASSIGNED_NONE ||
                         ShmSysConfigAndInfo->SysInfo.MainChargingMode == _MAIN_CHARGING_MODE_AVER)
                     {
+                        if (ShmSysConfigAndInfo->SysInfo.CanAverageCharging)
                         setChargerMode(gun_index, MODE_PRECHARGE);
+                        else
+                            setChargerMode(gun_index, MODE_IDLE);
                     }
                     else if (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag == _REASSIGNED_RELAY_M_TO_A &&
                         ShmSysConfigAndInfo->SysInfo.BridgeRelayStatus == NO)
@@ -4274,7 +4729,8 @@ int main(void)
                         StartGunInfoTimeoutDet(gun_index, Timeout_Preparing);
                     }
 
-                    if (ShmPsuData->SystemPresentPsuQuantity > 0 && ShmPsuData->SystemAvailablePower > 10)
+                    if (ShmPsuData->SystemPresentPsuQuantity > 0 && ShmPsuData->SystemAvailablePower > 10 &&
+                        GetTimeoutValue(chargingInfo[gun_index]->TimeoutTimer) >= 5000000)
                     {
                         setChargerMode(gun_index, MODE_PREPARE_FOR_EV);
                     }
@@ -4520,15 +4976,19 @@ int main(void)
                     if (isModeChange(gun_index))
                     {
                         PRINTF_FUNC ("terminating......................... %x \n", gun_index);
+                        if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "Remote") != EQUAL)
+                            strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "EVDisconnected");
                         StopGunInfoTimeoutDet(gun_index);
                     }
 
+                    bool toComplete = false;
                     if (chargingInfo[gun_index]->Type == _Type_Chademo)
                     {
                         // 非車端的停止 : 需等待小板送出停止指令,讓車端解除槍
                         if (isEvStopCharging_chademo(gun_index) == YES ||
                             isPrechargeStatus_chademo(gun_index) <= 0)
                         {
+                            toComplete = true;
                             setChargerMode(gun_index, MODE_COMPLETE);
                         }
                     }
@@ -4538,6 +4998,7 @@ int main(void)
                         if (isEvStopCharging_gb(gun_index) == YES ||
                             isPrechargeStatus_gb(gun_index) <= 0)
                         {
+                            toComplete = true;
                             setChargerMode(gun_index, MODE_COMPLETE);
                         }
                     }
@@ -4548,9 +5009,18 @@ int main(void)
                             (isPrechargeStatus_ccs(gun_index) >= 53 || isPrechargeStatus_ccs(gun_index) == 0 ||
                              isPrechargeStatus_ccs(gun_index) == 13 || isPrechargeStatus_ccs(gun_index) == 14))
                         {
+                            toComplete = true;
                             setChargerMode(gun_index, MODE_COMPLETE);
                         }
                     }
+
+                    if (!toComplete)
+                    {
+                        if (strcmp((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "Remote") != EQUAL)
+                            strcpy((char *)ShmOCPP16Data->StopTransaction[gun_index].StopReason, "Local");
+                    }
+
+
                     if (ShmSysConfigAndInfo->SysInfo.CurGunSelected == gun_index)
                         ShmSysConfigAndInfo->SysInfo.ConnectorPage = _LCM_COMPLETE;
                 }

+ 10 - 1
EVSE/Projects/DW30/Apps/timeout.h

@@ -32,6 +32,8 @@
 #include <ctype.h>
 #include <ifaddrs.h>
 
+#define CONN_PLUG_TIME_OUT          40
+
 enum Timeout_flag
 {
     Timeout_None =                      0,
@@ -46,7 +48,14 @@ enum Timeout_flag
     Timeout_EvseChargingDet =           8,
     Timeout_EvseCompleteDet =           9,
     Timeout_ForCcsPrechargeDet =        10,
-    Timeout_ReturnToChargingGunDet =    11
+    Timeout_ReturnToChargingGunDet =    11,
+    Timeout_AuthorizingForStop =        12
 };
 
+// for timeout fork
+struct timeval _cmdSubPriority_time;
+unsigned short _connectionTimeout;
+
+// for main
+struct timeval _cmdMainPriority_time;
 #endif /* TIMEOUT_H_ */