Răsfoiți Sursa

2021-12-27 / Wendell

Actions
1. [add] support ocpp 2.0
2. [add] charging data, status code, reboot, power consumption, network status database record
3. [add] DC input uvp function
4. [add] bypass psu self-test when dc input occur
5. [add] reservation function
6. [add] default MaintainServerURL value
7. [add] stop charging flag
8. [mod] authorization logic
9. [mod] trigger StartTransaction timing
10.[mod] recover time of psu fault
11.[fix] qr code display issue

Files
1. As follow commit history

Image version : V1.07.XX.XXXX.XX
Wendell 3 ani în urmă
părinte
comite
faabba7131

+ 60 - 0
EVSE/Projects/DO360/Apps/Common.c

@@ -64,6 +64,58 @@ int StorePsuLogMsg(const char *fmt, ...)
     return rc;
 }
 
+int StoreEventLogMsg(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);
+
+    sprintf(Buf,"echo \"%04d-%02d-%02d %02d:%02d:%02d:%03d - %s\" >> /Storage/EventLog/[%04d.%02d]EventLog",
+        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;
+}
+
+int StoreAuthLogMsg(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);
+
+    sprintf(Buf,"echo \'%04d-%02d-%02d %02d:%02d:%02d:%03d - %s\' >> /Storage/SystemLog/[%04d.%02d]AuthLog",
+        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;
+}
+
 void GetClockTime(struct timespec *_now_time)
 {
     clock_gettime(CLOCK_MONOTONIC, _now_time);
@@ -128,3 +180,11 @@ int StatusCodeCompose(char *oriCode, char *newCode)
     return strlen(oriCode);
 }
 
+void getNowDatetime(unsigned char *data)
+{
+    time_t t = time(NULL);
+    struct tm tm = *localtime(&t);
+
+    sprintf((char*)data, "%04d-%02d-%02dT%02d:%02d:%02dZ", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
+}
+

+ 8 - 0
EVSE/Projects/DO360/Apps/Common.h

@@ -28,12 +28,20 @@
 #define LOG_ERROR(format, args...) StoreSysLogMsg("[%s:%4d][%s][Erro] "format, (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__), __LINE__, __FUNCTION__, ##args)
 #define LOG_DBG(format, args...) StoreSysLogMsg("[%s:%4d][%s][Debg] "format, (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__), __LINE__, __FUNCTION__, ##args)
 #define PSU_LOG(format, args...) StorePsuLogMsg("[%s:%4d][%s][Info] "format, (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__), __LINE__, __FUNCTION__, ##args)
+#define LOG_EVENT(format, args...) StoreEventLogMsg("[%s:%4d][%s][Info] "format, (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__), __LINE__, __FUNCTION__, ##args)
+#define AUTH_INFO(format, args...) StoreAuthLogMsg("[%s:%4d][%s][Info] "format, (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__), __LINE__, __FUNCTION__, ##args)
+
+#define DB_FILE                     "/Storage/ChargeLog/localCgargingRecord.db"
+#define NETWORK_DB_FILE             "/Storage/EventLog/Eventlog.db"
 
 int StoreSysLogMsg(const char *fmt, ...);
 int StorePsuLogMsg(const char *fmt, ...);
+int StoreEventLogMsg(const char *fmt, ...);
+int StoreAuthLogMsg(const char *fmt, ...);
 void GetClockTime(struct timespec *_now_time);
 unsigned long GetTimeoutValue(struct timespec _start_time);
 unsigned long GetSecTimeoutValue(struct timespec _start_time);
 int StatusCodeCompose(char *oriCode, char *newCode);
+void getNowDatetime(unsigned char *data);
 
 #endif /* COMMON_H_ */

+ 50 - 3
EVSE/Projects/DO360/Apps/Config.h

@@ -61,6 +61,9 @@ typedef unsigned char               byte;
 #define SLAVE_ETH1_IP               "192.168.0.10"
 #define SLAVE_ETH1_SUBMASK          "255.255.255.0"
 
+#define AUTHORIZE_COMPLETED_TIME    3
+#define STARTTRANSATION_IMMEDIATELY
+
 // **********  Audi ********** //
 // Model Name: DOYC182000D2AD
 // Model Name: DDYC182V0UE2AD
@@ -79,6 +82,11 @@ typedef unsigned char               byte;
 
 // *********** TCC *********** //
 // Model Name: DBYE182000D1PH
+// Model Name: DBYC182000D1TC
+// Model Name: DDYC182V0EE1TC
+
+#define STR_LITTLE_ENDIAN           "Little Endian"
+#define STR_BIG_ENDIAN              "Big Endian"
 
 enum _SYSTEM_STATUS
 {
@@ -275,6 +283,10 @@ enum _ETHERNET_USAGE
 #define STR_CONN_CONNECTED          "Connected"
 #define STR_CONN_DISCONNECTED       "Disconnected"
 
+#define STR_DARKEST                 "Darkest"
+#define STR_MEDIUM                  "Medium"
+#define STR_BRIGHTEST               "Brightest"
+
 enum _CONN_STATUS
 {
     _Connnection_Disable = 0,
@@ -309,6 +321,10 @@ enum _E4YOU_INDICATION_STATUS
     _E4YOU_LED_Alarm            = 4,
 };
 
+#define STR_QR_DEFAULT              "Default"
+#define STR_QR_CUSTOMIZED           "Customized"
+#define STR_QR_CHARGEBOXID          "ChargeBoxId"
+
 enum _QR_MODE
 {
     _QR_MODE_Default            = 0,
@@ -316,6 +332,15 @@ enum _QR_MODE
     _QR_MODE_ChargeBoxId        = 2,                // for audi
 };
 
+enum _CUSTOMER_CODE
+{
+    _CUSTOMER_CODE_Phihong      = 0,
+    _CUSTOMER_CODE_Audi         = 1,
+    _CUSTOMER_CODE_E4U          = 2,
+    _CUSTOMER_CODE_UCar         = 3,
+    _CUSTOMER_CODE_TCC          = 4,
+};
+
 #define STR_CABINET_ROLE_NONE       "Single"
 #define STR_CABINET_ROLE_MASTER     "Master"
 #define STR_CABINET_ROLE_SLAVE      "Slave"
@@ -345,7 +370,8 @@ typedef union
         unsigned int DKLedIndication:1;             // 0: no led indication,        1: enable DK Model led indication
         unsigned int BackendEnable:1;               // 0: backend disable,          1: backend enable
         unsigned int Wifi4gResetEnable:1;           // 0: wifi/4g reset io disable, 1: wifi/4g reset io enable
-        unsigned int res:19;
+        unsigned int PsuInit:1;                     // 0: no effect,                1: psu is initialized
+        unsigned int res:18;
     }bits;
 }SystemControl;
 
@@ -481,10 +507,29 @@ typedef union
         unsigned int NeedSelfTest:1;                // 0: no effect,                1: need execute self test
         unsigned int Paused:1;                      // 0: no effect,                1: psu paused
         unsigned int FailureResume:1;               // 0: no error,                 1: psu failure, need resume
-        unsigned int res:28;
+        unsigned int CommunicationLost:1;           // 0: no error,                 1: psu communication lost
+        unsigned int res:27;
     }bits;
 }PsuControl;
 
+typedef struct
+{
+    int TxCnt;
+    int RxCnt;
+    int LostCnt;
+    int CommCnt;
+}DevideCommInfo;
+
+typedef struct
+{
+    DevideCommInfo PrimaryComm;
+    DevideCommInfo Relay1Comm;
+    DevideCommInfo Relay2Comm;
+    DevideCommInfo FanComm;
+    DevideCommInfo LedComm;
+    DevideCommInfo PsuComm;
+}CommInfoData;
+
 typedef struct
 {
     unsigned char   MaxDispenser;
@@ -492,8 +537,9 @@ typedef struct
     unsigned char   CabinetSwitch;
     unsigned char   CabinetRole;
     unsigned char   SelfTestStep;
-    unsigned char   res;
+    unsigned char   CustomerCode;
     unsigned short  ChargerRatingPower;             // unit: 0.1kw, charger rating power, parsing from model name
+    CommInfoData    CommInfo;
     SystemControl   SysCtrl;
     TestControl     TestCtrl;
     DebugControl    DebugCtrl;
@@ -504,6 +550,7 @@ typedef struct
     PsuControl      PsuCtrl;
     ForceCharging   FCharging[MAX_GROUP_QUANTITY];
     unsigned char   GunAvailable[MAX_GROUP_QUANTITY];
+    unsigned char   PsuInitQuantity[MAX_GROUP_QUANTITY];
 }SysControl;
 // ************************************************************************************************* //
 typedef struct

+ 11 - 1
EVSE/Projects/DO360/Apps/FactoryConfig.c

@@ -166,7 +166,7 @@ int main(int argc,char *argv[])
 
         //strcpy((char*)SysConfig.ModelName, "");
         //strcpy((char*)SysConfig.SerialNumber, "");
-        strcpy((char *)SysConfig.ModelName, "DOYC182000D2AD");
+        strcpy((char *)SysConfig.ModelName, "DOYC362000D2PH");
         strcpy((char *)SysConfig.SerialNumber, "NeedSetupSN");
         sleep(5);
     }
@@ -247,6 +247,16 @@ int main(int argc,char *argv[])
 	SysConfig.OfflineMaxChargeDuration = 0;
 	strcpy((char *) SysConfig.OcppServerURL, "");
 	strcpy((char *) SysConfig.ChargeBoxId, "");
+
+	if(SysConfig.ModelName[12] == 'P' && SysConfig.ModelName[13] == 'H')
+	{
+	    strcpy((char *) SysConfig.MaintainServerURL, "wss://ocpp.phihong.com.tw:2013/");
+	}
+	else
+	{
+	    strcpy((char *) SysConfig.MaintainServerURL, "");
+	}
+
 	SysConfig.LedInfo.Intensity = 2;
 
 	// clean power cabinet wiring info

+ 10 - 3
EVSE/Projects/DO360/Apps/Makefile

@@ -13,7 +13,7 @@ Lib_SQLite3 = "-L../../../Modularization/ocppfiles" -lsqlite3
 all: CopyFile apps Clean
 #apps: Module_CSU Module_EvComm Module_EventLogging Module_InternalComm Module_LcmControl Module_PrimaryComm Module_PsuComm 
 # ReadCmdline kill.sh
-apps: Common MainTask CabinetParallel SelfTestTask LedIndication EvCommTask EventLoggingTask InternalCommTask LcmControlTask PrimaryCommTask InfyGroup_PsuCommObj PsuCommTask ReadCmdlineTask UnsafetyOutputTool FactoryConfigApp OtherTools
+apps: Common MainTask CabinetParallel SelfTestTask AuthorizeTask LedIndication EvCommTask EventLoggingTask InternalCommTask LcmControlTask PrimaryCommTask InfyGroup_PsuCommObj PsuCommTask ReadCmdlineTask UnsafetyOutputTool FactoryConfigApp OtherTools
 
 Common:
 	rm -f Common.o
@@ -38,6 +38,12 @@ SelfTestTask:
 	$(CC) -o Module_ChargerSelfTest Module_ChargerSelfTest.o Common.o -lrt
 	cp -f Module_ChargerSelfTest ../Images/root	
 
+AuthorizeTask:
+	rm -f Module_Authorize;
+	$(CC) -D $(Project) -includeConfig.h -O0 -g3 -Wall -c -fmessage-length=0 -o Module_Authorize.o Module_Authorize.c
+	$(CC) -o Module_Authorize Module_Authorize.o Common.o -lrt
+	cp -f Module_Authorize ../Images/root	
+
 LedIndication:
 	rm -f Module_LedIndication;
 	$(CC) -D $(Project) -includeConfig.h -O0 -g3 -Wall -c -fmessage-length=0 -o Module_LedIndication.o Module_LedIndication.c
@@ -53,8 +59,8 @@ EvCommTask:
 	
 EventLoggingTask:
 	rm -f Module_EventLogging;
-	$(CC) -D $(Project) -includeConfig.h -O0 -g3 -Wall -c -fmessage-length=0 -o Module_EventLogging.o Module_EventLogging.c
-	$(CC) -o Module_EventLogging Module_EventLogging.o Common.o -lrt
+	$(CC) -D $(Project) -include../../../Modularization/ocppfiles/sqlite3.h -includeConfig.h -O0 -g3 -Wall -c -fmessage-length=0 -o Module_EventLogging.o Module_EventLogging.c
+	$(CC) -o Module_EventLogging Module_EventLogging.o Common.o ${Lib_SQLite3} -lrt
 	cp -f Module_EventLogging ../Images/root	
 	
 InternalCommTask:
@@ -132,6 +138,7 @@ CleanExecute:
 	rm -f Module_EvComm
 	rm -f Module_CabinetParallel
 	rm -f Module_ChargerSelfTest
+	rm -f Module_Authorize
 	rm -f Module_LedIndication
 	rm -f Module_EventLogging
 	rm -f Module_InternalComm

+ 741 - 0
EVSE/Projects/DO360/Apps/Module_Authorize.c

@@ -0,0 +1,741 @@
+/*
+ * Module_Authorize.c
+ *
+ *  Created on: 2021年11月16日
+ *      Author: 7978
+ */
+
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/shm.h>
+#include <sys/mman.h>
+#include <linux/can.h>
+#include <linux/can/raw.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 <time.h>
+#include <ctype.h>
+#include <ifaddrs.h>
+#include <signal.h>
+#include <net/if_arp.h>
+#include "../../define.h"
+#include "Module_Authorize.h"
+#include "Module_EvComm.h"
+#include "Config.h"
+#include "Common.h"
+
+
+#define AUTHORIZE_INTERVAL              100000          // unit: 1us
+#define AUTHORIZE_WAIT_OCPP_TIMEOUT     30              // unit: 1s
+#define SYS_AUTHORIZE_COMP_TIMEOUT      1               // unit: 1s
+#define AUTH_TIME_OFFSET_TIME           3               // unit: 1s
+#define AUTO_START_CHARGING             "AutoStartCharging"
+
+struct SysConfigAndInfo             *ShmSysConfigAndInfo;
+ChargerInfoData                     *ShmChargerInfo;
+struct ChargingInfoData             *chargingInfo[GENERAL_GUN_QUANTITY];
+struct OCPP16Data                   *ShmOCPP16Data;
+struct OCPP20Data                   *ShmOCPP20Data;
+
+struct timespec                     _SysAuth_Time;
+struct timespec                     _GunAuth_Time[GENERAL_GUN_QUANTITY];
+struct timespec                     _DispenserAuth_Time[GENERAL_GUN_QUANTITY];
+
+unsigned char _preSysAuthStatus = 0;
+unsigned char _preGunAuthStatus[GENERAL_GUN_QUANTITY];
+unsigned char _preDispenserAuthStatus[GENERAL_GUN_QUANTITY];
+
+//==========================================
+// Init all share memory
+//==========================================
+int InitShareMemory(void)
+{
+    int result = PASS;
+    int MeterSMId;
+
+    //creat ShmSysConfigAndInfo
+    if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo), 0777)) < 0)
+    {
+        #ifdef SystemLogMessage
+        LOG_ERROR("shmget ShmSysConfigAndInfo NG");
+        #endif
+        result = FAIL;
+    }
+    else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+    {
+        #ifdef SystemLogMessage
+        LOG_ERROR("shmat ShmSysConfigAndInfo NG");
+        #endif
+        result = FAIL;
+     }
+    else
+    {
+
+    }
+
+    if ((MeterSMId = shmget(SM_ChargerInfoKey, sizeof(ChargerInfoData), 0777)) < 0)
+    {
+        #ifdef SystemLogMessage
+        LOG_ERROR("shmat ChargerInfoData NG");
+        #endif
+        result = FAIL;
+    }
+    else if ((ShmChargerInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+    {
+        #ifdef SystemLogMessage
+        LOG_ERROR("shmat ChargerInfoData NG");
+        #endif
+        result = FAIL;
+    }
+
+    if ((MeterSMId = shmget(ShmOcppModuleKey, sizeof(struct OCPP16Data), 0777)) < 0)
+    {
+        #ifdef SystemLogMessage
+        LOG_ERROR("shmat ShmOCPP16Data NG");
+        #endif
+        result = FAIL;
+    }
+    else if ((ShmOCPP16Data = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+    {
+        LOG_ERROR("shmat ShmOCPP16Data NG");
+        result = FAIL;
+    }
+
+    if ((MeterSMId = shmget(ShmOcpp20ModuleKey, sizeof(struct OCPP20Data), 0777)) < 0)
+    {
+        LOG_ERROR("[main]CreatShareMemory:shmget OCPP20Data NG\n");
+        result = FAIL;
+    }
+    else if ((ShmOCPP20Data = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+    {
+        LOG_ERROR("[main]CreatShareMemory:shmat OCPP20Data NG\n");
+        result = FAIL;
+    }
+
+    return result;
+}
+
+void InitialConnector(void)
+{
+    for(int i = 0; i < CONNECTOR_QUANTITY; i++)
+    {
+        chargingInfo[i] = &ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].GeneralChargingData;
+    }
+}
+
+//===============================================
+// Ocpp Remote Start
+//===============================================
+bool Is_Ocpp_RemoteStartReq(int gun_index)
+{
+    if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16)
+    {
+        return ShmOCPP16Data->CsMsg.bits[gun_index].RemoteStartTransactionReq == YES ? true : false;
+    }
+    if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20)
+    {
+        return ShmOCPP20Data->CsMsg.bits[gun_index].RequestStartTransactionReq == YES ? true : false;
+    }
+    return false;
+}
+
+void Clean_Ocpp_RemoteStartReq(int gun_index)
+{
+    if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16)
+    {
+        ShmOCPP16Data->CsMsg.bits[gun_index].RemoteStartTransactionReq = false;
+        return;
+    }
+    if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20)
+    {
+        ShmOCPP20Data->CsMsg.bits[gun_index].RequestStartTransactionReq = false;
+        return;
+    }
+}
+
+void Get_Ocpp_RemoteStartIdTag(int gun_index, char *idTag)
+{
+    if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16)
+    {
+        strcpy(idTag, (char *)&ShmOCPP16Data->RemoteStartTransaction[gun_index].IdTag[0]);
+        return;
+    }
+    if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20)
+    {
+        strcpy(idTag, (char *)&ShmOCPP20Data->RequestStartTransaction[gun_index].idToken.idToken[0]);
+        return;
+    }
+    strcpy(idTag, "");
+}
+
+//===============================================
+// Ocpp AuthorizeRemoteTxRequests
+//===============================================
+bool Is_Ocpp_AuthorizeRemoteTxRequests(void)
+{
+    if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16)
+    {
+        return strstr((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[AuthorizeRemoteTxRequests].ItemData, "TRUE") > 0 ? true : false;
+    }
+    if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20)
+    {
+        return strstr((char *)ShmOCPP20Data->ControllerComponentVariable[AuthCtrlr_AuthorizeRemoteStart].variableAttribute[0].value, "TRUE") > 0 ? true : false;
+    }
+    return false;
+}
+
+//===============================================
+// Ocpp AuthorizeReq
+//===============================================
+void Set_Ocpp_AuthorizeReq(void)
+{
+    if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16)
+    {
+        ShmOCPP16Data->SpMsg.bits.AuthorizeConf = false;
+        ShmOCPP16Data->SpMsg.bits.AuthorizeReq = true;
+        return;
+    }
+    if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20)
+    {
+        ShmOCPP20Data->SpMsg.bits.AuthorizeConf = false;
+        ShmOCPP20Data->SpMsg.bits.AuthorizeReq = true;
+        return;
+    }
+}
+
+bool Is_Ocpp_AuthorizeConf(void)
+{
+    if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16)
+    {
+        return ShmOCPP16Data->SpMsg.bits.AuthorizeConf == YES ? true : false;
+    }
+    if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20)
+    {
+        return ShmOCPP20Data->SpMsg.bits.AuthorizeConf == YES ? true : false;
+    }
+    return false;
+}
+
+bool Is_Ocpp_Authorize_Status(char *status)
+{
+    if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16)
+    {
+        return strcmp((char *)ShmOCPP16Data->Authorize.ResponseIdTagInfo.Status, status) == EQUAL ? true : false;
+    }
+    if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20)
+    {
+        return strcmp((char *)ShmOCPP20Data->Authorize.Response_idTokenInfo.status, status) == EQUAL ? true : false;
+    }
+    return false;
+}
+
+//===============================================
+// Ocpp Reserve Now
+//===============================================
+void Get_Ocpp_ReserveNowIdTag(int gun_index, char *idTag)
+{
+    if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16)
+    {
+        strcpy(idTag, (char *)ShmOCPP16Data->ReserveNow[gun_index].IdTag);
+        return;
+    }
+    if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20)
+    {
+        strcpy(idTag, (char *)ShmOCPP20Data->ReserveNow[gun_index].idToken.idToken);
+        return;
+    }
+    strcpy(idTag, "");
+    return;
+}
+
+bool Is_Ocpp_ReserveNowIdTag(uint8_t gun_index, char *authIdTag)
+{
+    char ReserveIdTag[32];
+
+    Get_Ocpp_ReserveNowIdTag(gun_index, ReserveIdTag);
+
+    return strcmp(ReserveIdTag, authIdTag) == EQUAL ? true : false;
+}
+
+void SetAuthorize(AuthorizingInfoData *AuthInfo, unsigned char type)
+{
+    memcpy(ShmSysConfigAndInfo->SysConfig.UserId, AuthInfo->AuthId, 32);
+
+    AuthInfo->AuthStatus = _AuthorizeStatus_Busy;
+    AuthInfo->AuthType = type;
+
+    ShmSysConfigAndInfo->SysInfo.AuthorizedTarget = AuthInfo->AuthTarget;
+    ShmSysConfigAndInfo->SysInfo.AuthorizedType = type;
+}
+
+bool IsRemoteStartRequest(int *connector)
+{
+    AuthorizingInfoData *AuthInfo;
+
+    // remote start check
+    for(int index = 0; index < GENERAL_GUN_QUANTITY; index++)
+    {
+        if(Is_Ocpp_RemoteStartReq(index))
+        {
+            AuthInfo = &ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].AuthInfo;
+            AuthInfo->AuthTarget = index + 1;
+            Get_Ocpp_RemoteStartIdTag(index, (char *)AuthInfo->AuthId);
+
+            SetAuthorize(AuthInfo, _AuthType_RemoteStart);
+            Clean_Ocpp_RemoteStartReq(index);
+            AuthInfo->AuthRequest = NO;
+            *connector = index;
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool IsAuthorizingRequest(int *connector)
+{
+    AuthorizingInfoData *AuthInfo;
+
+    // connector authorize check
+    for(int index = 0; index < GENERAL_GUN_QUANTITY; index++)
+    {
+        AuthInfo = &ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].AuthInfo;
+        if(AuthInfo->AuthStatus == _AuthorizeStatus_Idle && AuthInfo->AuthRequest == YES)
+        {
+            if(strlen((char *)AuthInfo->AuthId) > 0)
+            {
+                SetAuthorize(AuthInfo, _AuthType_RFID);
+                AuthInfo->AuthRequest = NO;
+                *connector = index;
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+bool IsDispenserAuthorizingRequest(int *dispenser)
+{
+    AuthorizingInfoData *AuthInfo;
+
+    // AUTO_GUN_SELECTION authorize check
+    for(int index = 0; index < GENERAL_GUN_QUANTITY; index++)
+    {
+        AuthInfo = &ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].AuthInfo;
+        if(AuthInfo->AuthStatus == _AuthorizeStatus_Idle && AuthInfo->AuthRequest == YES)
+        {
+            if(strlen((char *)AuthInfo->AuthId) > 0)
+            {
+                SetAuthorize(AuthInfo, _AuthType_RFID);
+                AuthInfo->AuthRequest = NO;
+                *dispenser = index;
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+unsigned char Chk_OfflinePolicy(char *idTag)
+{
+    if(ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_NO_CHARGING)
+    {
+        AUTH_INFO("*********** Offline Policy [No Charging] ***********");
+        return _AuthResult_Invalid;
+    }
+    else if(ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING)
+    {
+        // set authorize pass when offline policy is free charge
+        AUTH_INFO("*********** Offline Policy [Free Charging] ***********");
+        return _AuthResult_Valid;
+    }
+    else if(ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_LOCAL_LIST)
+    {
+        BOOL find = false;
+
+        // check white list
+        for(int i = 0; i < 10; i++)
+        {
+            if(strcmp((char *)ShmSysConfigAndInfo->SysConfig.LocalWhiteCard[i], "") != EQUAL)
+            {
+                if(strcmp((char *)ShmSysConfigAndInfo->SysConfig.LocalWhiteCard[i], idTag) == EQUAL)
+                {
+                    find = true;
+                    AUTH_INFO("***********  [White Card OK] ***********");
+                    break;
+                }
+            }
+        }
+
+        if(find == false)
+        {
+            if((ShmChargerInfo->AuthInfo.AuthMode.bits.AutoStartEnable || ShmSysConfigAndInfo->SysConfig.AuthorisationMode == AUTH_MODE_DISABLE) &&
+                strcmp((char *)ShmSysConfigAndInfo->SysConfig.UserId, AUTO_START_CHARGING) == EQUAL)
+            {
+                find = true;
+                AUTH_INFO("******** [Auto Start Charging] ********");
+            }
+        }
+
+        AUTH_INFO("*********** Local Authorization %s ***********", find ? "OK" : "NG");
+
+        if(find)
+        {
+            return _AuthResult_Valid;
+        }
+        else
+        {
+            return _AuthResult_Invalid;
+        }
+    }
+    else
+    {
+        AUTH_INFO("*********** [Invalid Policy]   ***********");
+
+        return _AuthResult_Invalid;
+    }
+
+    return _AuthResult_Invalid;
+}
+
+void SysAuthInitial(void)
+{
+    memset(ShmSysConfigAndInfo->SysConfig.UserId, 0x00, 32);
+
+    ShmSysConfigAndInfo->SysInfo.AuthorizedDispenser = 0;
+    ShmSysConfigAndInfo->SysInfo.AuthorizedTarget = 0;
+    ShmSysConfigAndInfo->SysInfo.AuthorizedType = _AuthResult_None;
+    ShmSysConfigAndInfo->SysInfo.AuthorizedStatus = _AuthorizeStatus_Idle;
+}
+
+void AuthTimeoutProcess(void)
+{
+    int timeout = 0;
+
+    for(int index = 0; index < GENERAL_GUN_QUANTITY; index++)
+    {
+        if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].AuthInfo.AuthStatus == _AuthorizeStatus_End)
+        {
+            if(_preGunAuthStatus[index] != ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].AuthInfo.AuthStatus)
+            {
+                GetClockTime(&_GunAuth_Time[index]);
+            }
+
+            timeout = ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].AuthInfo.AuthStatus == _AuthResult_Valid ?
+                ShmSysConfigAndInfo->SysInfo.DispenserInfo.ConnectorTimeout : AUTHORIZE_COMPLETED_TIME;
+            timeout += AUTH_TIME_OFFSET_TIME;
+
+            if(GetTimeoutValue(_GunAuth_Time[index]) / uSEC_VAL >= timeout)
+            {
+                AUTH_INFO("*********** Gun %d Authorizing Initial ***********", index + 1);
+                memset(&ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].AuthInfo, 0x00, sizeof(AuthorizingInfoData));
+            }
+        }
+        _preGunAuthStatus[index] = ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].AuthInfo.AuthStatus;
+    }
+    for(int index = 0; index < GENERAL_GUN_QUANTITY; index++)
+    {
+        if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].AuthInfo.AuthStatus == _AuthorizeStatus_End)
+        {
+            if(_preDispenserAuthStatus[index] != ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].AuthInfo.AuthStatus)
+            {
+                GetClockTime(&_DispenserAuth_Time[index]);
+            }
+
+            timeout = ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].AuthInfo.AuthResult == _AuthResult_Valid ?
+                ShmSysConfigAndInfo->SysInfo.DispenserInfo.ConnectorTimeout : AUTHORIZE_COMPLETED_TIME;
+            timeout += AUTH_TIME_OFFSET_TIME;
+
+            if(GetTimeoutValue(_DispenserAuth_Time[index]) / uSEC_VAL >= timeout)
+            {
+                AUTH_INFO("*********** Dispenser %d Authorizing Initial ***********", index + 1);
+                memset(&ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].AuthInfo, 0x00, sizeof(AuthorizingInfoData));
+            }
+        }
+        _preDispenserAuthStatus[index] = ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].AuthInfo.AuthStatus;
+    }
+}
+
+int main(void)
+{
+    int _dispenser = 0, _connector = 0;
+    unsigned char _authResult = _AuthResult_None;
+
+    bool _autoSelection = false;
+    bool _needOcppAuthorize = false;
+    bool _keepRun = false;
+
+    if(InitShareMemory() == FAIL)
+    {
+        #ifdef SystemLogMessage
+        LOG_ERROR("InitShareMemory NG");
+        #endif
+
+        sleep(5);
+        return 0;
+    }
+
+    InitialConnector();
+
+    while(1)
+    {
+        _keepRun = false;
+        AuthTimeoutProcess();
+
+        switch(ShmSysConfigAndInfo->SysInfo.AuthorizedStatus)
+        {
+            case _AuthorizeStatus_Idle:
+                if(_preSysAuthStatus != ShmSysConfigAndInfo->SysInfo.AuthorizedStatus)
+                {
+                    AUTH_INFO("[SysAuthStatus Idle]");
+                    _preSysAuthStatus = ShmSysConfigAndInfo->SysInfo.AuthorizedStatus;
+                    _authResult = _AuthResult_None;
+                    _autoSelection = false;
+                }
+
+                if(IsRemoteStartRequest(&_connector))
+                {
+                    ShmSysConfigAndInfo->SysInfo.AuthorizedStatus = _AuthorizeStatus_Wait;
+                    _keepRun = true;
+                    AUTH_INFO("Gun %d Remote Start Authorize", _connector + 1);
+                    break;
+                }
+                if(IsAuthorizingRequest(&_connector))
+                {
+                    ShmSysConfigAndInfo->SysInfo.AuthorizedStatus = _AuthorizeStatus_Wait;
+                    _keepRun = true;
+                    AUTH_INFO("Gun %d RFID Authorize", _connector + 1);
+                    break;
+                }
+                if(IsDispenserAuthorizingRequest(&_dispenser))
+                {
+                    _autoSelection = true;
+                    ShmSysConfigAndInfo->SysInfo.AuthorizedStatus = _AuthorizeStatus_Wait;
+                    _keepRun = true;
+                    AUTH_INFO("Dispenser %d AutoSelection Authorize", index + 1);
+                    break;
+                }
+                break;
+
+            case _AuthorizeStatus_Wait:
+                if(_preSysAuthStatus != ShmSysConfigAndInfo->SysInfo.AuthorizedStatus)
+                {
+                    AUTH_INFO("[SysAuthStatus Wait]");
+                    _preSysAuthStatus = ShmSysConfigAndInfo->SysInfo.AuthorizedStatus;
+                }
+                _needOcppAuthorize = false;
+
+                if(ShmSysConfigAndInfo->SysInfo.AuthorizedType == _AuthType_RemoteStart)
+                {
+                    if(Is_Ocpp_AuthorizeRemoteTxRequests())
+                    {
+                        _needOcppAuthorize = true;
+                    }
+                    else
+                    {
+                        AUTH_INFO("*********** Gun %d Remote Start Authorizing Bypass ***********",
+                            ShmSysConfigAndInfo->SysInfo.AuthorizedTarget);
+                        _authResult = _AuthResult_Valid;
+                        ShmSysConfigAndInfo->SysInfo.AuthorizedStatus = _AuthorizeStatus_Done;
+                        _keepRun = true;
+                        break;
+                    }
+                }
+                else if(ShmSysConfigAndInfo->SysInfo.AuthorizedType == _AuthType_RFID)
+                {
+                    if(ShmSysConfigAndInfo->SysInfo.OcppConnStatus &&
+                        ShmSysConfigAndInfo->SysConfig.AuthorisationMode == AUTH_MODE_ENABLE &&
+                        !ShmChargerInfo->AuthInfo.AuthMode.bits.AutoStartEnable)
+                    {
+                        _needOcppAuthorize = true;
+                    }
+                    else
+                    {
+                        _authResult = Chk_OfflinePolicy((char *)ShmSysConfigAndInfo->SysConfig.UserId);
+                        ShmSysConfigAndInfo->SysInfo.AuthorizedStatus = _AuthorizeStatus_Done;
+                        _keepRun = true;
+                        break;
+                    }
+                }
+
+                if(_needOcppAuthorize)
+                {
+                    Set_Ocpp_AuthorizeReq();
+                    AUTH_INFO("*********** Set OPCC AuthorizeReq ***********");
+                    ShmSysConfigAndInfo->SysInfo.AuthorizedStatus = _AuthorizeStatus_Busy;
+                }
+                break;
+
+            case _AuthorizeStatus_Busy:
+                if(_preSysAuthStatus != ShmSysConfigAndInfo->SysInfo.AuthorizedStatus)
+                {
+                    AUTH_INFO("[SysAuthStatus Busy]");
+                    _preSysAuthStatus = ShmSysConfigAndInfo->SysInfo.AuthorizedStatus;
+                    GetClockTime(&_SysAuth_Time);
+                }
+
+                if(GetTimeoutValue(_SysAuth_Time) / uSEC_VAL >= AUTHORIZE_WAIT_OCPP_TIMEOUT)
+                {
+                    AUTH_INFO("*********** Ocpp Authorizing Timeout ***********");
+                    _authResult = _AuthResult_Invalid;
+                    ShmSysConfigAndInfo->SysInfo.AuthorizedStatus = _AuthorizeStatus_Done;
+                    _keepRun = true;
+                    break;
+                }
+                else
+                {
+                    if(ShmSysConfigAndInfo->SysInfo.OcppConnStatus)
+                    {
+                        if(Is_Ocpp_AuthorizeConf())
+                        {
+                            BOOL accept = false;
+                            if(Is_Ocpp_Authorize_Status("Accepted"))
+                            {
+                                accept = true;
+                            }
+
+                            AUTH_INFO("*********** OCPP Authorize %s ***********", accept ? "OK" : "NG");
+                            _authResult = accept ? _AuthResult_Valid : _AuthResult_Invalid;
+                            ShmSysConfigAndInfo->SysInfo.AuthorizedStatus = _AuthorizeStatus_Done;
+                            _keepRun = true;
+                            break;
+                        }
+                    }
+                    else
+                    {
+                        AUTH_INFO("*********** OCPP Authorize Disconnected ***********");
+                        _authResult = Chk_OfflinePolicy((char *)ShmSysConfigAndInfo->SysConfig.UserId);
+                        ShmSysConfigAndInfo->SysInfo.AuthorizedStatus = _AuthorizeStatus_Done;
+                        _keepRun = true;
+                        break;
+                    }
+                }
+                break;
+
+            case _AuthorizeStatus_Done:
+                if(_preSysAuthStatus != ShmSysConfigAndInfo->SysInfo.AuthorizedStatus)
+                {
+                    AUTH_INFO("[SysAuthStatus Done]");
+                    _preSysAuthStatus = ShmSysConfigAndInfo->SysInfo.AuthorizedStatus;
+                    GetClockTime(&_SysAuth_Time);
+                }
+
+                if(_autoSelection)
+                {
+                    AUTH_INFO("*********** Dispense %d RFID Authorize %s ***********", _dispenser + 1, _authResult == _AuthResult_Valid ? "OK" : "NG");
+                    if(_authResult == _AuthResult_Valid)
+                    {
+                        if(strcmp((char *)ShmSysConfigAndInfo->SysConfig.UserId, AUTO_START_CHARGING) == EQUAL)
+                        {
+                            sprintf((char*)ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[_dispenser].AuthInfo.AuthId, "%s",
+                                ShmSysConfigAndInfo->SysConfig.SerialNumber);
+                        }
+                    }
+                    ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[_dispenser].AuthInfo.AuthResult = _authResult;
+                    ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[_dispenser].AuthInfo.AuthStatus = _AuthorizeStatus_End;
+                }
+                else
+                {
+                    unsigned char connector = 0;
+
+                    connector = ShmSysConfigAndInfo->SysInfo.AuthorizedTarget - 1;
+                    if(chargingInfo[connector]->SystemStatus == S_IDLE && _authResult == _AuthResult_Valid)
+                    {
+                        if(strcmp((char *)ShmSysConfigAndInfo->SysConfig.UserId, AUTO_START_CHARGING) == EQUAL)
+                        {
+                            sprintf((char*)ShmSysConfigAndInfo->SysConfig.UserId, "%s%s",
+                                ShmSysConfigAndInfo->SysConfig.ModelName, ShmSysConfigAndInfo->SysConfig.SerialNumber);
+                        }
+                        memcpy(chargingInfo[connector]->StartUserId, ShmSysConfigAndInfo->SysConfig.UserId, 32);
+
+                        if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[connector].AuthInfo.AuthType == _AuthType_RFID)
+                        {
+                            AUTH_INFO("*********** Gun %d RFID Authorize %s ***********", connector + 1, _authResult == _AuthResult_Valid ? "OK" : "NG");
+                        }
+                        if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[connector].AuthInfo.AuthType == _AuthType_RemoteStart)
+                        {
+                            AUTH_INFO("*********** Gun %d RemoteAuthorize %s ***********", connector + 1, _authResult == _AuthResult_Valid ? "OK" : "NG");
+                            ShmSysConfigAndInfo->SysInfo.ConnectorInfo[connector].Parameter.bits.RemoteStartRequest = true;
+                        }
+                    }
+                    else if(chargingInfo[connector]->SystemStatus == S_RESERVATION && _authResult == _AuthResult_Valid)
+                    {
+                        _authResult = Is_Ocpp_ReserveNowIdTag(connector, (char *)ShmSysConfigAndInfo->SysInfo.ConnectorInfo[connector].AuthInfo.AuthId) ? _AuthResult_Valid : _AuthResult_Invalid;
+
+                        if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[connector].AuthInfo.AuthType == _AuthType_RFID)
+                        {
+                            AUTH_INFO("*********** Gun %d RFID Reserve Authorize %s ***********", connector + 1, _authResult == _AuthResult_Valid ? "OK" : "NG");
+                        }
+                        if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[connector].AuthInfo.AuthType == _AuthType_RemoteStart)
+                        {
+                            AUTH_INFO("*********** Gun %d Reserve RemoteAuthorize %s ***********", connector + 1, _authResult == _AuthResult_Valid ? "OK" : "NG");
+                            ShmSysConfigAndInfo->SysInfo.ConnectorInfo[connector].Parameter.bits.RemoteStartRequest = true;
+                        }
+                    }
+                    else
+                    {
+                        AUTH_INFO("*********** Gun %d Authorize OK But Status Fail (%d) ***********", connector + 1, chargingInfo[connector]->SystemStatus);
+                        _authResult = _AuthResult_Invalid;
+                    }
+                    ShmSysConfigAndInfo->SysInfo.ConnectorInfo[connector].AuthInfo.AuthResult = _authResult;
+                    ShmSysConfigAndInfo->SysInfo.ConnectorInfo[connector].AuthInfo.AuthStatus = _AuthorizeStatus_End;
+                }
+
+                ShmSysConfigAndInfo->SysInfo.AuthorizedStatus = _AuthorizeStatus_End;
+                break;
+
+            case _AuthorizeStatus_End:
+                if(_preSysAuthStatus != ShmSysConfigAndInfo->SysInfo.AuthorizedStatus)
+                {
+                    AUTH_INFO("[SysAuthStatus End]");
+                    _preSysAuthStatus = ShmSysConfigAndInfo->SysInfo.AuthorizedStatus;
+                    GetClockTime(&_SysAuth_Time);
+                }
+
+                if(GetTimeoutValue(_SysAuth_Time) / uSEC_VAL >= SYS_AUTHORIZE_COMP_TIMEOUT)
+                {
+                    AUTH_INFO("*********** PowerCabinet Authorize Completed ***********");
+                    SysAuthInitial();
+                }
+                break;
+
+            default:
+                if(_preSysAuthStatus != ShmSysConfigAndInfo->SysInfo.AuthorizedStatus)
+                {
+                    AUTH_INFO("[SysAuthStatus Unknown]");
+                    _preSysAuthStatus = ShmSysConfigAndInfo->SysInfo.AuthorizedStatus;
+                }
+
+                ShmSysConfigAndInfo->SysInfo.AuthorizedStatus = _AuthorizeStatus_End;
+                break;
+        }
+
+        if(!_keepRun)
+        {
+            usleep(AUTHORIZE_INTERVAL);
+        }
+    }
+
+    return 0;
+}

+ 13 - 0
EVSE/Projects/DO360/Apps/Module_Authorize.h

@@ -0,0 +1,13 @@
+/*
+ * Module_Authorize.h
+ *
+ *  Created on: 2021年11月16日
+ *      Author: 7978
+ */
+
+#ifndef MODULE_AUTHORIZE_H_
+#define MODULE_AUTHORIZE_H_
+
+
+
+#endif /* MODULE_AUTHORIZE_H_ */

+ 9 - 2
EVSE/Projects/DO360/Apps/Module_ChargerSelfTest.c

@@ -425,7 +425,15 @@ int main(void)
                             }
                             else
                             {
-                                SetSelfTestSate(_STEST_PSU_DETECT);
+                                if(!ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DcInputUVP)
+                                {
+                                    SetSelfTestSate(_STEST_PSU_DETECT);
+                                }
+                                else
+                                {
+                                    LOG_INFO("DC Input UVP, Bypass PSU Self-Test");
+                                    SetSelfTestSate(_STEST_COMPLETE);
+                                }
                             }
                         }
                         else
@@ -464,7 +472,6 @@ int main(void)
                 {
                     ShmChargerInfo->Control.PsuCtrl.bits.SelfTestOK = NO;
                     ShmChargerInfo->Control.PsuCtrl.bits.NeedSelfTest = YES;
-                    ShmChargerInfo->Control.PsuCtrl.bits.Paused = NO;
                     ShmChargerInfo->Control.RelayCtrl.bits.AcContactor = ON;
 
                     GetClockTime(&_TestStep_time);

+ 254 - 25
EVSE/Projects/DO360/Apps/Module_EvComm.c

@@ -1136,6 +1136,10 @@ void ChargingCapabilityResponse(int socket, struct PACKET_STRUCTURE *packet)
 	ConnectorCapability[packet->Header.id - 1].TotalCost = cost;
 	ConnectorCapability[packet->Header.id - 1].AccountBalance = account;
 
+    ShmSysConfigAndInfo->SysInfo.ConnectorInfo[packet->Header.id - 1].CapabilityVoltage = voltage;
+    ShmSysConfigAndInfo->SysInfo.ConnectorInfo[packet->Header.id - 1].CapabilityCurrent = current;
+    ShmSysConfigAndInfo->SysInfo.ConnectorInfo[packet->Header.id - 1].CapabilityPower = power;
+
 	sendBuffer.Header.se = packet->Header.se;
 	sendBuffer.Header.id = packet->Header.id;
 	sendBuffer.Header.op = _Header_Response;
@@ -1299,10 +1303,12 @@ void AddMiscCommand(struct PACKET_STRUCTURE *packet, struct MISC_COMMAND *misc)
 // LOG_INFO("Cabinet >> Dispenser %d SoftReset    [%d]", dispenserIndex + 1, misc.Value);
 // LOG_INFO("Cabinet >> Dispenser %d AuthMode     [%s]", dispenserIndex + 1, misc.Value ? "Disable" : "Enable");
 // LOG_INFO("Cabinet >> Dispenser %d EVCCID       [%s]", dispenserIndex + 1, misc.Value ? "Enable" : "Disable");
-
+// LOG_INFO("Cabinet >> Dispenser %d LEDIntensity [%s]", dispenserIndex + 1, strIntensity[misc.Value]);
+// LOG_INFO("Cabinet >> Dispenser %d LEDIntensity [%d]", dispenserIndex + 1, misc.Value);
 void MiscCmdRes(int socket, struct PACKET_STRUCTURE *packet, unsigned char dispenserIndex, unsigned char result)
 {
     char *strConnection[] = {STR_CONN_DISABLE, STR_CONN_CONNECTED, STR_CONN_DISCONNECTED};
+    char *strIntensity[] = {STR_DARKEST, STR_MEDIUM, STR_BRIGHTEST};
     struct PACKET_STRUCTURE sendBuffer;
 
     memset(&sendBuffer, 0x00, sizeof(sendBuffer));
@@ -1561,6 +1567,23 @@ void MiscCmdRes(int socket, struct PACKET_STRUCTURE *packet, unsigned char dispe
                 LOG_INFO("Cabinet >> Dispenser %d EVCCID       [%s]", dispenserIndex + 1, misc.Value ? "Enable" : "Disable");
                 AddMiscCommand(&sendBuffer, &misc);
             }
+
+            if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].Setting.bits.LEDIntensityRequest)
+            {
+                ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].Setting.bits.LEDIntensityRequest = false;
+                misc.Command = _MiscCmd_LEDIntensity;
+                misc.Value = ShmSysConfigAndInfo->SysConfig.LedInfo.Intensity;
+
+                if(misc.Value <= _LED_INTENSITY_BRIGHTEST)
+                {
+                    LOG_INFO("Cabinet >> Dispenser %d LEDIntensity [%s]", dispenserIndex + 1, strIntensity[misc.Value]);
+                }
+                else
+                {
+                    LOG_INFO("Cabinet >> Dispenser %d LEDIntensity [%d]", dispenserIndex + 1, misc.Value);
+                }
+                AddMiscCommand(&sendBuffer, &misc);
+            }
         }
     }
 
@@ -1638,6 +1661,11 @@ int GetChargerSystemId(char *id)
 
     strcpy((char *)id, "");
 
+    if(ShmChargerInfo->Control.CustomerCode != _CUSTOMER_CODE_Audi)
+    {
+        ShmChargerInfo->AuthInfo.QRCodeMode = ShmSysConfigAndInfo->SysConfig.QRCodeMadeMode;
+    }
+
     switch(ShmChargerInfo->AuthInfo.QRCodeMode)
     {
         case _QR_MODE_Customized:
@@ -1727,6 +1755,115 @@ void GroundFaultDetectionResponse(int socket, struct PACKET_STRUCTURE *packet, u
     SendPacket(socket, &sendBuffer);
 }
 
+void CabinetCSUVersionResponse(int socket, struct PACKET_STRUCTURE *packet, unsigned char result)
+{
+    struct PACKET_STRUCTURE sendBuffer;
+    char version[64];
+
+    memset(&sendBuffer, 0x00, sizeof(sendBuffer));
+    sendBuffer.Header.se = packet->Header.se;
+    sendBuffer.Header.id = packet->Header.id;
+    sendBuffer.Header.op = _Header_Response;
+    sendBuffer.Header.len = 194;
+    sendBuffer.Payload.reg = _Reg_Get_Cabinet_CSU_Version;
+    sendBuffer.Payload.data[0] = result;
+
+    memset(version, 0x00, sizeof(version));
+    strcpy(version, (char *)&ShmSysConfigAndInfo->SysConfig.ModelName[0]);
+    memcpy(&sendBuffer.Payload.data[1], version, 32);
+
+    memset(version, 0x00, sizeof(version));
+    strcpy(version, (char *)&ShmSysConfigAndInfo->SysInfo.CsuBootLoadFwRev[0]);
+    memcpy(&sendBuffer.Payload.data[33], version, 32);
+
+    memset(version, 0x00, sizeof(version));
+    strcpy(version, (char *)&ShmSysConfigAndInfo->SysInfo.CsuKernelFwRev[0]);
+    memcpy(&sendBuffer.Payload.data[65], version, 32);
+
+    memset(version, 0x00, sizeof(version));
+    strcpy(version, (char *)&ShmSysConfigAndInfo->SysInfo.CsuRootFsFwRev[0]);
+    memcpy(&sendBuffer.Payload.data[97], version, 32);
+
+    memset(version, 0x00, sizeof(version));
+    strcpy(version, (char *)&ShmSysConfigAndInfo->SysInfo.CsuPrimFwRev[0]);
+    memcpy(&sendBuffer.Payload.data[129], version, 32);
+
+    memset(version, 0x00, sizeof(version));
+    strcpy(version, (char *)&ShmSysConfigAndInfo->SysConfig.Eth0Interface.EthIpAddress[0]);
+    memcpy(&sendBuffer.Payload.data[161], version, 32);
+
+    SendPacket(socket, &sendBuffer);
+}
+
+void CabinetOtherVersionResponse(int socket, struct PACKET_STRUCTURE *packet, unsigned char result)
+{
+    struct PACKET_STRUCTURE sendBuffer;
+    char version[64];
+
+    memset(&sendBuffer, 0x00, sizeof(sendBuffer));
+    sendBuffer.Header.se = packet->Header.se;
+    sendBuffer.Header.id = packet->Header.id;
+    sendBuffer.Header.op = _Header_Response;
+    sendBuffer.Header.len = 98;
+    sendBuffer.Payload.reg = _Reg_Get_Cabinet_Other_Version;
+    sendBuffer.Payload.data[0] = result;
+
+    memset(version, 0x00, sizeof(version));
+    strcpy(version, (char *)&ShmSysConfigAndInfo->SysInfo.RelayModuleFwRev[0]);
+    memcpy(&sendBuffer.Payload.data[1], version, 32);
+
+    memset(version, 0x00, sizeof(version));
+    strcpy(version, (char *)&ShmSysConfigAndInfo->SysInfo.Relay2ModuleFwRev[0]);
+    memcpy(&sendBuffer.Payload.data[33], version, 32);
+
+    memset(version, 0x00, sizeof(version));
+    strcpy(version, (char *)&ShmSysConfigAndInfo->SysInfo.FanModuleFwRev[0]);
+    memcpy(&sendBuffer.Payload.data[65], version, 32);
+
+    SendPacket(socket, &sendBuffer);
+}
+
+void PsuQuantityResponse(int socket, struct PACKET_STRUCTURE *packet, unsigned char result)
+{
+    struct PACKET_STRUCTURE sendBuffer;
+
+    memset(&sendBuffer, 0x00, sizeof(sendBuffer));
+    sendBuffer.Header.se = packet->Header.se;
+    sendBuffer.Header.id = packet->Header.id;
+    sendBuffer.Header.op = _Header_Response;
+    sendBuffer.Header.len = 3;
+    sendBuffer.Payload.reg = _Reg_Get_Psu_Quantity;
+    sendBuffer.Payload.data[0] = result;
+    sendBuffer.Payload.data[1] = ShmPsuData->SystemPresentPsuQuantity;
+
+    SendPacket(socket, &sendBuffer);
+}
+
+void PsuVersionResponse(int socket, struct PACKET_STRUCTURE *packet, unsigned char result, int psuIndex)
+{
+    struct PACKET_STRUCTURE sendBuffer;
+    char version[64];
+
+    memset(&sendBuffer, 0x00, sizeof(sendBuffer));
+    sendBuffer.Header.se = packet->Header.se;
+    sendBuffer.Header.id = packet->Header.id;
+    sendBuffer.Header.op = _Header_Response;
+    sendBuffer.Header.len = 3;
+    sendBuffer.Payload.reg = _Reg_Get_Psu_Version;
+    sendBuffer.Payload.data[0] = result;
+    sendBuffer.Payload.data[1] = psuIndex;
+
+    memset(version, 0x00, sizeof(version));
+    strcpy(version, (char *)&ShmPsuData->PsuVersion[psuIndex].FwPrimaryVersion[0]);
+    memcpy(&sendBuffer.Payload.data[2], version, 32);
+
+    memset(version, 0x00, sizeof(version));
+    strcpy(version, (char *)&ShmPsuData->PsuVersion[psuIndex].FwSecondVersion[0]);
+    memcpy(&sendBuffer.Payload.data[34], version, 32);
+
+    SendPacket(socket, &sendBuffer);
+}
+
 BOOL FindConnectorID(unsigned char dispenserIndex, unsigned char id)
 {
 	BOOL find = false;
@@ -2256,53 +2393,80 @@ BOOL ConnectorStateHandler(struct PACKET_STRUCTURE *packet, unsigned char dispen
 	return true;
 }
 
+AuthorizingInfoData preGunAuthInfo[GENERAL_GUN_QUANTITY];
+AuthorizingInfoData preDispenserAuthInfo[GENERAL_GUN_QUANTITY];
+
 unsigned char UserIDHandler(struct PACKET_STRUCTURE *packet, unsigned char dispenserIndex)
 {
     BOOL find = FindConnectorID(dispenserIndex, packet->Header.id);
 	DispenserAck_Status authorize = _DAS_Wait;
 	unsigned char CardNumber[32];
-	unsigned char *result;
+	//unsigned char *result;
+	AuthorizingInfoData *AuthInfo;
+	AuthorizingInfoData *preAuthInfo;
 	int length = 0;
 
-	if(find || packet->Header.id == 0xFF)
+	if(find || packet->Header.id == AUTO_GUN_SELECTION)
 	{
 	    length = packet->Header.len - 1;
 	    memset(CardNumber, 0x00, sizeof(CardNumber));
 	    memcpy(CardNumber, packet->Payload.data, length);
 
-	    if(packet->Header.id != 0xFF)
+	    if(packet->Header.id != AUTO_GUN_SELECTION)
 	    {
-	        result = &ShmSysConfigAndInfo->SysInfo.ConnectorInfo[packet->Header.id - 1].AuthorizingResult;
+	        //result = &ShmSysConfigAndInfo->SysInfo.ConnectorInfo[packet->Header.id - 1].AuthorizingResult;
+	        AuthInfo = &ShmSysConfigAndInfo->SysInfo.ConnectorInfo[packet->Header.id - 1].AuthInfo;
+	        preAuthInfo = &preGunAuthInfo[packet->Header.id - 1];
 	    }
 	    else
 	    {
-	        result = &ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].AuthResult;
+	        //result = &ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].AuthResult;
+	        AuthInfo = &ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].AuthInfo;
+	        preAuthInfo = &preDispenserAuthInfo[dispenserIndex];
 	    }
 
-	    if(*result == _AuthResult_Valid)
+	    //if(*result == _AuthResult_Valid)
+        if(AuthInfo->AuthResult == _AuthResult_Valid)
 	    {
-            LOG_INFO("Dispenser %d Target %d user id %s authorizing ok", dispenserIndex + 1, packet->Header.id, CardNumber);
+            if(preAuthInfo->AuthResult != AuthInfo->AuthResult)
+            {
+                LOG_INFO("Dispenser %d Target %d user id %s authorizing ok", dispenserIndex + 1, packet->Header.id, CardNumber);
+            }
             authorize = _DAS_Allowed;
 	    }
-	    else if(*result == _AuthResult_Invalid)
+	    //else if(*result == _AuthResult_Invalid)
+        else if(AuthInfo->AuthResult == _AuthResult_Invalid)
 	    {
-            LOG_INFO("Dispenser %d Target %d user id %s authorizing fail", dispenserIndex + 1, packet->Header.id, CardNumber);
+            if(preAuthInfo->AuthResult != AuthInfo->AuthResult)
+            {
+                LOG_INFO("Dispenser %d Target %d user id %s authorizing fail", dispenserIndex + 1, packet->Header.id, CardNumber);
+            }
             authorize = _DAS_NotAllowed;
 	    }
-	    else if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].AuthStatus == _AuthorizeStatus_Idle &&
-            ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].Setting.bits.AuthorizeRequest == false)
-	    {
-	        memcpy(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].UserId, CardNumber, sizeof(CardNumber));
-	        ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].AuthTarget = packet->Header.id;
-	        ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].Setting.bits.AuthorizeRequest = true;
+        else
+        {
+            if(AuthInfo->AuthStatus == _AuthorizeStatus_Idle && AuthInfo->AuthRequest == NO)
+            {
+                memcpy(AuthInfo->AuthId, CardNumber, sizeof(CardNumber));
+                AuthInfo->AuthTarget = packet->Header.id;
+                AuthInfo->AuthRequest = YES;
 
-	        LOG_INFO("Dispenser %d connector %d user id %s need authorize", dispenserIndex + 1, packet->Header.id, CardNumber);
-	        authorize = _DAS_Wait;
-	    }
-	    else
-	    {
-	        authorize = _DAS_Wait;
-	    }
+                if(AuthInfo->AuthTarget != AUTO_GUN_SELECTION)
+                {
+                    LOG_INFO("Gun %d user id [%s] need authorize", packet->Header.id, CardNumber);
+                }
+                else
+                {
+                    LOG_INFO("Dispenser %d user id [%s] need authorize", dispenserIndex + 1, CardNumber);
+                }
+                authorize = _DAS_Wait;
+            }
+            else
+            {
+                authorize = _DAS_Wait;
+            }
+        }
+        preAuthInfo->AuthResult = AuthInfo->AuthResult;
     }
 	else
 	{
@@ -2690,6 +2854,32 @@ unsigned char GroundFaultDetectionHandler(struct PACKET_STRUCTURE *packet, unsig
     return find;
 }
 
+unsigned char GetCabinetCSUVersionHandler(struct PACKET_STRUCTURE *packet, unsigned char dispenserIndex)
+{
+    return true;
+}
+
+unsigned char GetCabinetOtherVersionHandler(struct PACKET_STRUCTURE *packet, unsigned char dispenserIndex)
+{
+    return true;
+}
+
+unsigned char GetPsuQuantityHandler(struct PACKET_STRUCTURE *packet, unsigned char dispenserIndex)
+{
+    return true;
+}
+
+unsigned char GetPsuVersionHandler(struct PACKET_STRUCTURE *packet, int *psuIndex)
+{
+    *psuIndex = 0;
+
+    if(packet->Payload.data[0] <= ShmPsuData->SystemPresentPsuQuantity && packet->Payload.data[0] > 0)
+    {
+        *psuIndex = packet->Payload.data[0] - 1;
+    }
+    return true;
+}
+
 void DisableConnector(unsigned char dispenserIndex)
 {
 	for(int i = 0; i < ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].ConnectorQuantity; i++)
@@ -2970,6 +3160,47 @@ void DispenserSocketProcess(int socketFd, struct sockaddr_in clientInfo, unsigne
                         }
                         GroundFaultDetectionResponse(socketFd, &receiveBuffer, ackResult);
                     }
+
+                    // Reg: 0x13, Get Cabinet CSU Version
+                    if(receiveBuffer.Header.op == _Header_Read && receiveBuffer.Payload.reg == _Reg_Get_Cabinet_CSU_Version)
+                    {
+                        if(GetCabinetCSUVersionHandler(&receiveBuffer, dispenserIndex))
+                        {
+                            ackResult = _R_OK;
+                        }
+                        CabinetCSUVersionResponse(socketFd, &receiveBuffer, ackResult);
+                    }
+
+                    // Reg: 0x14, Get Cabinet Other Version
+                    if(receiveBuffer.Header.op == _Header_Read && receiveBuffer.Payload.reg == _Reg_Get_Cabinet_Other_Version)
+                    {
+                        if(GetCabinetOtherVersionHandler(&receiveBuffer, dispenserIndex))
+                        {
+                            ackResult = _R_OK;
+                        }
+                        CabinetOtherVersionResponse(socketFd, &receiveBuffer, ackResult);
+                    }
+
+                    // Reg: 0x15, Get Psu Quantity
+                    if(receiveBuffer.Header.op == _Header_Read && receiveBuffer.Payload.reg == _Reg_Get_Psu_Quantity)
+                    {
+                        if(GetPsuQuantityHandler(&receiveBuffer, dispenserIndex))
+                        {
+                            ackResult = _R_OK;
+                        }
+                        PsuQuantityResponse(socketFd, &receiveBuffer, ackResult);
+                    }
+
+                    // Reg: 0x15, Get Psu Version
+                    if(receiveBuffer.Header.op == _Header_Read && receiveBuffer.Payload.reg == _Reg_Get_Psu_Version)
+                    {
+                        int _PsuIndex = 0;
+                        if(GetPsuVersionHandler(&receiveBuffer, &_PsuIndex))
+                        {
+                            ackResult = _R_OK;
+                        }
+                        PsuVersionResponse(socketFd, &receiveBuffer, ackResult, _PsuIndex);
+                    }
 				}
 
 				// clean timeout
@@ -3083,8 +3314,6 @@ void InitDispenserInfo(void)
 	    disconnect = ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].Parameter.bits.Disconnection;
 	    ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].Parameter.Value = 0;
 	    ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].Parameter.bits.Disconnection = disconnect;
-	    ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].AuthorizingType = 0;
-	    ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].AuthorizingResult = 0;
 	    memset(&ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].WarningInfo, 0x00, sizeof(struct WARNING_CODE_INFO));
 
 	    //memset(&LastWarningInfo[i], 0x00, sizeof(struct WARNING_CODE_INFO));

+ 53 - 48
EVSE/Projects/DO360/Apps/Module_EvComm.h

@@ -55,30 +55,34 @@ enum HEADER_OP
 
 enum PAYLOAD_REGISTER
 {
-	_Reg_Dispenser_Model_Name		= 0x01,
-	_Reg_Connector_ID				= 0x02,
-	_Reg_Power_Cabinet_Status		= 0x03,
-	_Reg_Dispenser_Status			= 0x04,
-	_Reg_Charging_Capability		= 0x05,
-	_Reg_Charging_Target			= 0x06,
-	_Reg_Software_Update			= 0x07,
-	_Reg_Plug_In_Status				= 0x08,
-	_Reg_Connector_State			= 0x09,
-	_Reg_User_ID					= 0x0A,
-	_Reg_Charging_Permission		= 0x0B,
-	_Reg_Misc_Control               = 0x0C,
-	_Reg_Report_Csu_Version         = 0x0D,
-	_Reg_Report_Other_Version       = 0x0E,
-	_Reg_Charging_Info              = 0x0F,
-	_Reg_Charger_System_Id          = 0x10,
-	_Reg_WaitPlugIn                 = 0x11,
-	_Reg_GroundFaultDetection       = 0x12,
+    _Reg_Dispenser_Model_Name       = 0x01,
+    _Reg_Connector_ID               = 0x02,
+    _Reg_Power_Cabinet_Status       = 0x03,
+    _Reg_Dispenser_Status           = 0x04,
+    _Reg_Charging_Capability        = 0x05,
+    _Reg_Charging_Target            = 0x06,
+    _Reg_Software_Update            = 0x07,
+    _Reg_Plug_In_Status             = 0x08,
+    _Reg_Connector_State            = 0x09,
+    _Reg_User_ID                    = 0x0A,
+    _Reg_Charging_Permission        = 0x0B,
+    _Reg_Misc_Control               = 0x0C,
+    _Reg_Report_Csu_Version         = 0x0D,
+    _Reg_Report_Other_Version       = 0x0E,
+    _Reg_Charging_Info              = 0x0F,
+    _Reg_Charger_System_Id          = 0x10,
+    _Reg_WaitPlugIn                 = 0x11,
+    _Reg_GroundFaultDetection       = 0x12,
+    _Reg_Get_Cabinet_CSU_Version    = 0x13,
+    _Reg_Get_Cabinet_Other_Version  = 0x14,
+    _Reg_Get_Psu_Quantity           = 0x15,
+    _Reg_Get_Psu_Version            = 0x16,
 };
 
 enum Response_Result
 {
-	_R_OK	= 0x01,
-	_R_NG	= 0x02,
+    _R_OK	= 0x01,
+    _R_NG	= 0x02,
 };
 
 enum Response_Upgrade
@@ -89,17 +93,17 @@ enum Response_Upgrade
 
 enum PlugIn_Status
 {
-	_PIS_UnPlugged	= 0x00,
-	_PIS_PluggedIn	= 0x01,
+    _PIS_UnPlugged	= 0x00,
+    _PIS_PluggedIn	= 0x01,
 };
 
 enum Connector_Remote_Status
 {
-	_CRS_Idle			= 0x00,
-	_CRS_Preparing		= 0x01,
-	_CRS_Charging		= 0x02,
-	_CRS_Terminating	= 0x03,
-	_CRS_Alarm          = 0x04,
+    _CRS_Idle			= 0x00,
+    _CRS_Preparing		= 0x01,
+    _CRS_Charging		= 0x02,
+    _CRS_Terminating	= 0x03,
+    _CRS_Alarm          = 0x04,
 };
 
 typedef enum
@@ -111,51 +115,51 @@ typedef enum
 
 enum Permission_Status
 {
-	_PS_NotPermitted	= 0x00,
-	_PS_Permitted		= 0x01,
+    _PS_NotPermitted	= 0x00,
+    _PS_Permitted		= 0x01,
 };
 
 enum Accept_Status
 {
-	_AS_Reject			= 0x00,
-	_AS_Accept			= 0x01,
+    _AS_Reject			= 0x00,
+    _AS_Accept			= 0x01,
 };
 
 struct HEADER_STRUCTURE
 {
-	unsigned char se;
-	unsigned char id;
-	unsigned char op;
-	unsigned char len;
+    unsigned char se;
+    unsigned char id;
+    unsigned char op;
+    unsigned char len;
 };
 
 struct PAYLOAD_STRUCTURE
 {
-	unsigned char reg;
-	unsigned char data[MAXIMUM_PAYLOAD_LENGTH];
+    unsigned char reg;
+    unsigned char data[MAXIMUM_PAYLOAD_LENGTH];
 };
 
 struct PACKET_STRUCTURE
 {
-	struct HEADER_STRUCTURE  Header;
-	struct PAYLOAD_STRUCTURE Payload;
+    struct HEADER_STRUCTURE  Header;
+    struct PAYLOAD_STRUCTURE Payload;
 }Packet_Structure;
 
 enum DispenserStatus
 {
-	_DS_None					= 0x00,
-	_DS_Identification			= 0x01,
-	_DS_Idle					= 0x02,
-	_DS_Alarm					= 0x03,
-	_DS_Charging				= 0x04,
-	_DS_Timeout					= 0x05,
+    _DS_None					= 0x00,
+    _DS_Identification			= 0x01,
+    _DS_Idle					= 0x02,
+    _DS_Alarm					= 0x03,
+    _DS_Charging				= 0x04,
+    _DS_Timeout					= 0x05,
 };
 
 enum ConnectionStatus
 {
-	_CNS_FREE					= 0x00,
-	_CNS_WaitModelName			= 0x01,
-	_CNS_DispenserMatched		= 0x02,
+    _CNS_FREE					= 0x00,
+    _CNS_WaitModelName			= 0x01,
+    _CNS_DispenserMatched		= 0x02,
 };
 
 struct MISC_COMMAND
@@ -180,6 +184,7 @@ enum MiscCommand
     _MiscCmd_StopButton         = 0x000B,
     _MiscCmd_AuthDisable        = 0x000C,
     _MiscCmd_EVCCIDEnable       = 0x000D,
+    _MiscCmd_LEDIntensity       = 0x000E,
     _MiscCmd_HardwareReboot     = 0x0101,
     _MiscCmd_SoftwareRestart    = 0x0102,
     _MiscCmd_RemoteStart        = 0x0103,

+ 367 - 0
EVSE/Projects/DO360/Apps/Module_EventLogging.c

@@ -12,6 +12,7 @@
 #include 	<linux/wireless.h>
 #include 	<arpa/inet.h>
 #include 	<netinet/in.h>
+#include    <stdbool.h>
 
 #include 	<unistd.h>
 #include 	<stdarg.h>
@@ -29,9 +30,28 @@
 #include	"../../define.h"
 #include    "Common.h"
 
+struct network_previous_status
+{
+    int     rssiWifi;
+    int     rssi4g;
+    uint8_t isInternet:1;
+    uint8_t isOcppConnected:1;
+    uint8_t ethIsInternet:1;
+    uint8_t maln0IsInternet:1;
+    uint8_t ppp0IsInternet:1;
+};
+
 struct SysConfigAndInfo			*ShmSysConfigAndInfo;
 struct StatusCodeData 			*ShmStatusCodeData;
+struct OCPP16Data               *ShmOCPP16Data;
+struct OCPP20Data               *ShmOCPP20Data;
 struct StatusCodeData           StatusCodeDisableMask;
+struct StatusCodeData           StatusUpdateReq;
+struct EventDataType            _BackupEventData[10];
+struct network_previous_status  netPreviousStatus;
+
+sqlite3 *localDb;
+sqlite3 *networkDb;
 
 int DiffTimeb(struct timeb ST, struct timeb ET)
 {
@@ -103,6 +123,28 @@ int InitShareMemory()
     else
     {}
 
+    if ((MeterSMId = shmget(ShmOcppModuleKey, sizeof(struct OCPP16Data), 0777)) < 0)
+    {
+        LOG_ERROR("shmat ShmOCPP16Data NG");
+        result = FAIL;
+    }
+    else if ((ShmOCPP16Data = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+    {
+        LOG_ERROR("shmat ShmOCPP16Data NG");
+        result = FAIL;
+    }
+
+    if ((MeterSMId = shmget(ShmOcpp20ModuleKey, sizeof(struct OCPP20Data), 0777)) < 0)
+    {
+        LOG_ERROR("[main]CreatShareMemory:shmget OCPP20Data NG\n");
+        result = FAIL;
+    }
+    else if ((ShmOCPP20Data = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+    {
+        LOG_ERROR("[main]CreatShareMemory:shmat OCPP20Data NG\n");
+        result = FAIL;
+    }
+
     return result;
 }
 
@@ -151,6 +193,281 @@ void RemoveFaultCodeToBuf(unsigned char *Code)
 	}
 }
 
+//==========================================
+// SQLite routne
+//==========================================
+int DB_Insert_Record(sqlite3 *db, uint8_t *statusCode)
+{
+    int result = PASS;
+    char* errMsg = NULL;
+    char sqlStr[1024];
+
+    sprintf(sqlStr, "insert into event_record(occurDatetime, statusCode) values(CURRENT_TIMESTAMP, '%s');", statusCode);
+
+    // 0 : open successfully, else fail.
+    if(sqlite3_open(DB_FILE, &db))
+    {
+        result = FAIL;
+        LOG_ERROR("Can't open database: %s", sqlite3_errmsg(db));
+        sqlite3_close(db);
+    }
+    else
+    {
+        //LOG_INFO("Local event record database open successfully.");
+        if (sqlite3_exec(db, sqlStr, 0, 0, &errMsg) != SQLITE_OK)
+        {
+            result = FAIL;
+            LOG_ERROR("Insert local event record error message: %s", errMsg);
+        }
+        else
+        {
+            //LOG_INFO("Insert local event record successfully");
+        }
+
+        sprintf(sqlStr, "delete from event_record where idx < (select idx from event_record order by idx desc limit 1)-2000;");
+        if (sqlite3_exec(db, sqlStr, 0, 0, &errMsg) != SQLITE_OK)
+        {
+            result = FAIL;
+            LOG_ERROR("delete local event_record error message: %s", errMsg);
+        }
+        else
+        {
+            //LOG_INFO("delete local event record successfully");
+        }
+
+        sqlite3_close(db);
+    }
+
+    return result;
+}
+
+int DB_Network_Insert_Record(sqlite3 *db)
+{
+    int result = PASS;
+    char* errMsg = NULL;
+    char sqlStr[1024];
+
+    if(ShmSysConfigAndInfo->SysConfig.ModelName[10] == 'D')
+    {
+        sprintf(sqlStr, "insert into network_record(occurDatetime, isInternet, isOcppConnected, isEth0Internet, isMlan0Internet, isPpp0Internet, rssiMlan0, rssiPpp0) values(CURRENT_TIMESTAMP, '%d', '%d', '%d', '%d', '%d', '%d', '%d');",
+                ShmSysConfigAndInfo->SysInfo.InternetConn,
+                ShmSysConfigAndInfo->SysInfo.OcppConnStatus,
+                !ShmStatusCodeData->InfoCode.InfoEvents.bits.InternetDisconnectViaEthernet,
+                !ShmStatusCodeData->InfoCode.InfoEvents.bits.InternetDisconnectViaWiFi,
+                !ShmStatusCodeData->InfoCode.InfoEvents.bits.InternetDisconnectVia4Gi,
+                ShmSysConfigAndInfo->SysConfig.AthInterface.WifiRssi,
+                ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomRssi);
+    }
+    else if(ShmSysConfigAndInfo->SysConfig.ModelName[10] == 'W')
+    {
+        sprintf(sqlStr, "insert into network_record(occurDatetime, isInternet, isOcppConnected, isEth0Internet, isMlan0Internet, isPpp0Internet, rssiMlan0, rssiPpp0) values(CURRENT_TIMESTAMP, '%d', '%d', '%d', '%d', '%d', '%d', '%d');",
+                ShmSysConfigAndInfo->SysInfo.InternetConn,
+                ShmSysConfigAndInfo->SysInfo.OcppConnStatus,
+                !ShmStatusCodeData->InfoCode.InfoEvents.bits.InternetDisconnectViaEthernet,
+                !ShmStatusCodeData->InfoCode.InfoEvents.bits.InternetDisconnectViaWiFi,
+                0,
+                ShmSysConfigAndInfo->SysConfig.AthInterface.WifiRssi,
+                0);
+    }
+    else if(ShmSysConfigAndInfo->SysConfig.ModelName[10] == 'T')
+    {
+        sprintf(sqlStr, "insert into network_record(occurDatetime, isInternet, isOcppConnected, isEth0Internet, isMlan0Internet, isPpp0Internet, rssiMlan0, rssiPpp0) values(CURRENT_TIMESTAMP, '%d', '%d', '%d', '%d', '%d', '%d', '%d');",
+                ShmSysConfigAndInfo->SysInfo.InternetConn,
+                ShmSysConfigAndInfo->SysInfo.OcppConnStatus,
+                !ShmStatusCodeData->InfoCode.InfoEvents.bits.InternetDisconnectViaEthernet,
+                0,
+                !ShmStatusCodeData->InfoCode.InfoEvents.bits.InternetDisconnectVia4Gi,
+                0,
+                ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomRssi);
+    }
+    else
+    {
+        sprintf(sqlStr, "insert into network_record(occurDatetime, isInternet, isOcppConnected, isEth0Internet, isMlan0Internet, isPpp0Internet, rssiMlan0, rssiPpp0) values(CURRENT_TIMESTAMP, '%d', '%d', '%d', '%d', '%d', '%d', '%d');",
+                ShmSysConfigAndInfo->SysInfo.InternetConn,
+                ShmSysConfigAndInfo->SysInfo.OcppConnStatus,
+                !ShmStatusCodeData->InfoCode.InfoEvents.bits.InternetDisconnectViaEthernet,
+                0,
+                0,
+                0,
+                0);
+    }
+
+    if(sqlite3_open(NETWORK_DB_FILE, &db))
+    {
+        result = FAIL;
+        LOG_ERROR("Can't open database: %s", sqlite3_errmsg(db));
+        sqlite3_close(db);
+    }
+    else
+    {
+        if (sqlite3_exec(db, sqlStr, 0, 0, &errMsg) != SQLITE_OK)
+        {
+            result = FAIL;
+            LOG_ERROR("Insert local network status record error message: %s", errMsg);
+        }
+
+        sprintf(sqlStr, "delete from network_record where idx < (select idx from network_record order by idx desc limit 1)-20000;");
+        if (sqlite3_exec(db, sqlStr, 0, 0, &errMsg) != SQLITE_OK)
+        {
+            result = FAIL;
+            LOG_ERROR("delete local network_record error message: %s", errMsg);
+        }
+
+        sqlite3_close(db);
+    }
+
+    return result;
+}
+
+void SetFaultUpdateReq(int ByteIndex, int BitIndex)
+{
+    StatusUpdateReq.FaultCode.FaultEvents.FaultVal[ByteIndex] |= (1 << BitIndex);
+}
+
+void CleanFaultUpdateReq(int ByteIndex, int BitIndex)
+{
+    StatusUpdateReq.FaultCode.FaultEvents.FaultVal[ByteIndex] &= ~(1 << BitIndex);
+}
+
+void SetAlarmUpdateReq(int ByteIndex, int BitIndex)
+{
+    StatusUpdateReq.AlarmCode.AlarmEvents.AlarmVal[ByteIndex] |= (1 << BitIndex);
+}
+
+void CleanAlarmUpdateReq(int ByteIndex, int BitIndex)
+{
+    StatusUpdateReq.AlarmCode.AlarmEvents.AlarmVal[ByteIndex] &= ~(1 << BitIndex);
+}
+
+void SetInfoUpdateReq(int ByteIndex, int BitIndex)
+{
+    StatusUpdateReq.InfoCode.InfoEvents.InfoVal[ByteIndex] |= (1 << BitIndex);
+}
+
+void CleanInfoUpdateReq(int ByteIndex, int BitIndex)
+{
+    StatusUpdateReq.InfoCode.InfoEvents.InfoVal[ByteIndex] &= ~(1 << BitIndex);
+}
+
+void CleanAllUpdateReq(void)
+{
+    memset((char *)&StatusUpdateReq, 0x00, sizeof(struct StatusCodeData));
+}
+
+bool IsStatusCodeUpdateReq(void)
+{
+    for(int i = 0; i < FaultCodeLength; i++)
+    {
+        if(StatusUpdateReq.FaultCode.FaultEvents.FaultVal[i] > 0)
+        {
+            return true;
+        }
+    }
+    for(int i = 0; i < AlarmCodeLength; i++)
+    {
+        if(StatusUpdateReq.AlarmCode.AlarmEvents.AlarmVal[i] > 0)
+        {
+            return true;
+        }
+    }
+    for(int i = 0; i < InfoCodeLength; i++)
+    {
+        if(StatusUpdateReq.InfoCode.InfoEvents.InfoVal[i] > 0)
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+void SetOcpp20EventData(int event_index, char *vendorCode, unsigned char isAbnormal)
+{
+    getNowDatetime(ShmOCPP20Data->NotifyEvent.eventData[event_index].timestamp);
+    ShmOCPP20Data->NotifyEvent.eventData[event_index].eventId = event_index;
+    sprintf((char*)ShmOCPP20Data->NotifyEvent.eventData[event_index].trigger, "Alerting");
+    sprintf((char*)ShmOCPP20Data->NotifyEvent.eventData[event_index].actualValue, isAbnormal ? "true" : "false");
+    ShmOCPP20Data->NotifyEvent.eventData[event_index].cleared = isAbnormal ? NO : YES;
+    sprintf((char*)ShmOCPP20Data->NotifyEvent.eventData[event_index].eventNotificationType, "HardWiredNotification");
+
+    sprintf((char*)ShmOCPP20Data->NotifyEvent.eventData[event_index].techcode, vendorCode);
+    sprintf((char*)ShmOCPP20Data->NotifyEvent.eventData[event_index].techInfo, vendorCode);
+
+    sprintf((char*)ShmOCPP20Data->NotifyEvent.eventData[event_index].component.name, "Charger");
+    ShmOCPP20Data->NotifyEvent.eventData[event_index].component.evse.connectorId = 0;
+    sprintf((char*)ShmOCPP20Data->NotifyEvent.eventData[event_index].variable.name, "Problem");
+}
+
+void UpdateOcpp20EventData(void)
+{
+    int eventCnt = 0;
+    int eventLength = 0;
+    bool abnormal = false;
+    char eventCode[7];
+
+    eventLength = ARRAY_SIZE(ShmOCPP20Data->NotifyEvent.eventData);
+
+    for(int i = 0; i < FaultCodeLength; i++)
+    {
+        for(int j = 0; j < 8; j++)
+        {
+            if((StatusUpdateReq.FaultCode.FaultEvents.FaultVal[i] & (1 << j)) > 0 && eventCnt < eventLength)
+            {
+                abnormal = (ShmStatusCodeData->FaultCode.FaultEvents.FaultVal[i] & (1 << j)) > 0 ? true : false;
+                memset(eventCode, 0x00, sizeof(eventCode));
+                memcpy(eventCode, FaultStatusCode[i * 8 + j], sizeof(eventCode) - 1);
+                // modify power cabinet status code X1XXXX to X4XXXX
+                if(eventCode[1] == '1')
+                {
+                    eventCode[1] = '4';
+                }
+
+                SetOcpp20EventData(eventCnt, eventCode, abnormal);
+                eventCnt++;
+            }
+        }
+    }
+    for(int i = 0; i < AlarmCodeLength; i++)
+    {
+        for(int j = 0; j < 8; j++)
+        {
+            if((StatusUpdateReq.AlarmCode.AlarmEvents.AlarmVal[i] & (1 << j)) > 0 && eventCnt < eventLength)
+            {
+                abnormal = (ShmStatusCodeData->FaultCode.FaultEvents.FaultVal[i] & (1 << j)) > 0 ? true : false;
+                memset(eventCode, 0x00, sizeof(eventCode));
+                memcpy(eventCode, AlarmStatusCode[i * 8 + j], sizeof(eventCode) - 1);
+                // modify power cabinet status code X1XXXX to X4XXXX
+                if(eventCode[1] == '1')
+                {
+                    eventCode[1] = '4';
+                }
+
+                SetOcpp20EventData(eventCnt, eventCode, abnormal);
+                eventCnt++;
+            }
+        }
+    }
+    for(int i = 0; i < InfoCodeLength; i++)
+    {
+        for(int j = 0; j < 8; j++)
+        {
+            if((StatusUpdateReq.InfoCode.InfoEvents.InfoVal[i] & (1 << j)) > 0 && eventCnt < eventLength)
+            {
+                abnormal = (ShmStatusCodeData->FaultCode.FaultEvents.FaultVal[i] & (1 << j)) > 0 ? true : false;
+                memset(eventCode, 0x00, sizeof(eventCode));
+                memcpy(eventCode, InfoStatusCode[i * 8 + j], sizeof(eventCode) - 1);
+                // modify power cabinet status code X1XXXX to X4XXXX
+                if(eventCode[1] == '1')
+                {
+                    eventCode[1] = '4';
+                }
+
+                SetOcpp20EventData(eventCnt, eventCode, abnormal);
+                eventCnt++;
+            }
+        }
+    }
+}
+
 int main(void)
 {
 	int ByteCount,BitCount;
@@ -170,6 +487,7 @@ int main(void)
 	}
 
 	memset((char *)&StatusCodeDisableMask, 0x00, sizeof(struct StatusCodeData));
+	CleanAllUpdateReq();
 
 	// AlarmCode disable mask
 	StatusCodeDisableMask.AlarmCode.AlarmEvents.bits.PsuFuseBurnOut = YES;
@@ -240,6 +558,10 @@ int main(void)
 							ShmStatusCodeData->FaultCode.PreviousFaultVal[ByteCount] |= (1<<BitCount);
 							AddFaultCodeToBuf(EventCodeTmp);
 						}
+
+                        LOG_EVENT("%s", EventCodeTmp);
+                        DB_Insert_Record(localDb, EventCodeTmp);
+						SetFaultUpdateReq(ByteCount, BitCount);
 					}
 				}
 			}
@@ -283,6 +605,13 @@ int main(void)
 							    AddFaultCodeToBuf(EventCodeTmp);
 							}
 						}
+
+                        LOG_EVENT("%s", EventCodeTmp);
+                        DB_Insert_Record(localDb, EventCodeTmp);
+                        if(!(StatusCodeDisableMask.AlarmCode.AlarmEvents.AlarmVal[ByteCount] & (1<<BitCount)))
+                        {
+                            SetAlarmUpdateReq(ByteCount, BitCount);
+                        }
 					}
 				}
 			}
@@ -326,10 +655,48 @@ int main(void)
 							    AddFaultCodeToBuf(EventCodeTmp);
 							}
 						}
+
+                        LOG_EVENT("%s", EventCodeTmp);
+                        DB_Insert_Record(localDb, EventCodeTmp);
+                        if(!(StatusCodeDisableMask.InfoCode.InfoEvents.InfoVal[ByteCount] & (1<<BitCount)))
+                        {
+                            SetInfoUpdateReq(ByteCount, BitCount);
+                        }
 					}
 				}
 			}
 		}
+
+		if(IsStatusCodeUpdateReq())
+		{
+		    if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20 && ShmOCPP20Data->SpMsg.bits.NotifyEventReq == OFF)
+		    {
+		        UpdateOcpp20EventData();
+
+		        ShmOCPP20Data->SpMsg.bits.NotifyEventReq = ON;
+		        CleanAllUpdateReq();
+		    }
+		}
+
+        if((netPreviousStatus.isInternet != ShmSysConfigAndInfo->SysInfo.InternetConn) ||
+                (netPreviousStatus.isOcppConnected != ShmSysConfigAndInfo->SysInfo.OcppConnStatus) ||
+                (netPreviousStatus.ethIsInternet != ShmStatusCodeData->InfoCode.InfoEvents.bits.InternetDisconnectViaEthernet) ||
+                (netPreviousStatus.maln0IsInternet != ShmStatusCodeData->InfoCode.InfoEvents.bits.InternetDisconnectViaWiFi) ||
+                (netPreviousStatus.ppp0IsInternet != ShmStatusCodeData->InfoCode.InfoEvents.bits.InternetDisconnectVia4Gi) ||
+                (netPreviousStatus.rssiWifi != ShmSysConfigAndInfo->SysConfig.AthInterface.WifiRssi) ||
+                (netPreviousStatus.rssi4g != ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomRssi))
+        {
+
+            DB_Network_Insert_Record(networkDb);
+            netPreviousStatus.isInternet = ShmSysConfigAndInfo->SysInfo.InternetConn;
+            netPreviousStatus.isOcppConnected = ShmSysConfigAndInfo->SysInfo.OcppConnStatus;
+            netPreviousStatus.ethIsInternet = ShmStatusCodeData->InfoCode.InfoEvents.bits.InternetDisconnectViaEthernet;
+            netPreviousStatus.maln0IsInternet = ShmStatusCodeData->InfoCode.InfoEvents.bits.InternetDisconnectViaWiFi;
+            netPreviousStatus.ppp0IsInternet = ShmStatusCodeData->InfoCode.InfoEvents.bits.InternetDisconnectVia4Gi;
+            netPreviousStatus.rssiWifi = ShmSysConfigAndInfo->SysConfig.AthInterface.WifiRssi;
+            netPreviousStatus.rssi4g = ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomRssi;
+        }
+
 		usleep(500000);
 	}
 

+ 34 - 2
EVSE/Projects/DO360/Apps/Module_InternalComm.c

@@ -45,7 +45,7 @@
 #define	NO_DEFINE			255
 #define	NDEFAULT_AC_INDEX	2
 
-#define OVP_UVP_CHK_COUNT   3
+#define OVP_UVP_CHK_COUNT   5
 
 struct SysConfigAndInfo			*ShmSysConfigAndInfo;
 struct StatusCodeData 			*ShmStatusCodeData;
@@ -77,6 +77,9 @@ Connector_GFD                   *LocaltionGfd[MAX_GROUP_QUANTITY];
 #define DCIN_OVP_THRESHOLD_VOL      825 // dc input ovp threshold voltage
 #define DCIN_OVP_RECOVERY_VOL       815 // dc input ovp recovery voltage
 
+#define DCIN_UVP_THRESHOLD_VOL      400 // dc input uvp threshold voltage
+#define DCIN_UVP_RECOVERY_VOL       410 // dc input uvp recovery voltage
+
 #define VIN_DROP_VOLTAGE	150	// 小於該值 : ac drop
 
 #define VOUT_MAX_VOLTAGE	995
@@ -132,6 +135,7 @@ bool _isRelayWelding[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
 struct timespec _checkRelayWeldingTimer[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
 
 byte _dcOvpCnt = 0;
+byte _dcUvpCnt = 0;
 byte _threePhaseOvp[3] = {0, 0, 0};
 byte _threePhaseUvp[3] = {0, 0, 0};
 
@@ -413,6 +417,7 @@ void GetPresentInputVol()
         {
             ShmSysConfigAndInfo->SysInfo.InputVoltageDc = dcInputVoltage.DC_Input_1;
 
+            // DC Input OVP
             if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DcInputOVP == NO)
             {
                 if(dcInputVoltage.DC_Input_1 > DCIN_OVP_THRESHOLD_VOL)
@@ -431,13 +436,40 @@ void GetPresentInputVol()
             }
             else
             {
-                if(dcInputVoltage.DC_Input_1 < DCIN_OVP_RECOVERY_VOL)
+                if(dcInputVoltage.DC_Input_1 <= DCIN_OVP_RECOVERY_VOL)
                 {
                     ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DcInputOVP = NO;
                     LOG_INFO("Dc Input OVP Recovery: %.1f V", dcInputVoltage.DC_Input_1);
                 }
                 _dcOvpCnt = 0;
             }
+
+            // DC Input UVP
+            if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DcInputUVP == NO)
+            {
+                if(dcInputVoltage.DC_Input_1 < DCIN_UVP_THRESHOLD_VOL)
+                {
+                    _dcUvpCnt++;
+                    if(_dcUvpCnt >= OVP_UVP_CHK_COUNT)
+                    {
+                        ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DcInputUVP = YES;
+                        LOG_INFO("Dc Input UVP: %.1f V", dcInputVoltage.DC_Input_1);
+                    }
+                }
+                else
+                {
+                    _dcUvpCnt = 0;
+                }
+            }
+            else
+            {
+                if(dcInputVoltage.DC_Input_1 >= DCIN_UVP_RECOVERY_VOL)
+                {
+                    ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DcInputUVP = NO;
+                    LOG_INFO("Dc Input UVP Recovery: %.1f V", dcInputVoltage.DC_Input_1);
+                }
+                _dcUvpCnt = 0;
+            }
         }
     }
     else

+ 106 - 2
EVSE/Projects/DO360/Apps/Module_PsuComm.c

@@ -17,6 +17,7 @@
 #define PRE_CHARG_RANGE		50
 #define CMD_DELAY_TIME 		25000                   // 25us
 #define PSU_TASK_CHECK_TIME 1
+#define PSU_COMM_CHECK_TIME 1
 
 #define GET_PSU_COUNT_INTERVAL          1           // unit: second
 #define GET_PSU_COUNT_TIME              13          // unit: second
@@ -64,6 +65,8 @@
 #define MAX_CHARGING_DELAY_COUNT        15
 #define VOLTAGE_RESUME_STEP             10          // unit: 0.1V, 1V
 #define POWER_ONOFF_RESEND_INTERVAL     1           // unit: 1s, 1s
+#define COMM_LOST_CRITICAL              0
+#define LOST_CNT_CRITICAL               10
 
 #if SAFETY_TEST_ENABLE
 #define PRECHARGE_OFFSET                1           // 0: normal output, 1: precharge voltage offset enable
@@ -91,6 +94,8 @@ byte psuCmdSeq = _PSU_CMD_CAP;
 
 byte startModuleFlag = false;
 bool psuReceiveRecovery = false;
+bool isCommStart = false;
+int lostCnt = 0;
 
 unsigned short evseOutVol[CONNECTOR_QUANTITY] = {0, 0, 0, 0};
 unsigned short evseOutCur[CONNECTOR_QUANTITY] = {0, 0, 0, 0};
@@ -110,6 +115,7 @@ struct timespec _StageCurrent_time[CONNECTOR_QUANTITY];
 struct timespec _CheckSlaveReady_time[CONNECTOR_QUANTITY];
 struct timespec _ChargingDelay_time[CONNECTOR_QUANTITY];
 struct timespec _PoweOnOff_time[CONNECTOR_QUANTITY];
+struct timespec _PsuCommCheck_time;
 
 unsigned short  GCTargetVoltage[CONNECTOR_QUANTITY];
 unsigned short  GCTargetCurrent[CONNECTOR_QUANTITY];
@@ -396,6 +402,8 @@ void AbnormalStopAnalysis(byte gun_index, int errCode)
 // 0x04: PSU_RCmd_ModuleStatus
 void GetStatusCallback(byte group, byte SN, byte temp, int alarm)
 {
+    ShmChargerInfo->Control.CommInfo.PsuComm.RxCnt++;
+
     if(ShmPsuData->Work_Step != Get_PSU_LOCATION)
     {
         return;
@@ -466,6 +474,8 @@ void GetStatusCallback(byte group, byte SN, byte temp, int alarm)
 // 0x02: PSU_RCmd_SysModuleCount
 void GetModuleCountCallback(byte group, byte count)
 {
+    ShmChargerInfo->Control.CommInfo.PsuComm.RxCnt++;
+
 	if(group == SYSTEM_CMD)
 	{
 		ShmPsuData->SystemPresentPsuQuantity = count;
@@ -558,6 +568,8 @@ void GetAvailableCapCallback(byte address, short maxVol, short minVol, short max
 {
     int _groupCurrent = 0, _groupPower = 0;
 
+    ShmChargerInfo->Control.CommInfo.PsuComm.RxCnt++;
+
     if (ShmPsuData->Work_Step < GET_SYS_CAP || address >= ShmPsuData->SystemPresentPsuQuantity ||
         !ShmPsuPosition->PsuLocationInit)
     {
@@ -639,6 +651,8 @@ void GetAvailableCapCallback(byte address, short maxVol, short minVol, short max
 // 0x07: PSU_RCmd_ModuleVersion
 void GetFwCallback(byte address, short dcSwVer, short pfcSwVer, short hwVer)
 {
+    ShmChargerInfo->Control.CommInfo.PsuComm.RxCnt++;
+
     if (ShmPsuData->Work_Step != Get_PSU_VERSION || address >= ShmPsuData->SystemPresentPsuQuantity ||
         !ShmPsuPosition->PsuLocationInit)
     {
@@ -677,6 +691,8 @@ void GetPresentOutputCallback(byte group, unsigned short outVol, unsigned short
 // 0x0E: PSU_RCmd_ModuleMiscInfo
 void GetMisCallback(byte address, unsigned int value, byte type)
 {
+    ShmChargerInfo->Control.CommInfo.PsuComm.RxCnt++;
+
     if (ShmPsuData->Work_Step < GET_SYS_CAP || address >= ShmPsuData->SystemPresentPsuQuantity ||
         !ShmPsuPosition->PsuLocationInit)
     {
@@ -718,6 +734,8 @@ void GetMisCallback(byte address, unsigned int value, byte type)
 // 0x02CCF0XX
 void GetIavailableCallback(byte address, unsigned short Iavail, unsigned short Vext)
 {
+    ShmChargerInfo->Control.CommInfo.PsuComm.RxCnt++;
+
     if (ShmPsuData->Work_Step < GET_SYS_CAP || address >= ShmPsuData->SystemPresentPsuQuantity ||
         !ShmPsuPosition->PsuLocationInit)
     {
@@ -804,6 +822,8 @@ void GetIavailableCallback(byte address, unsigned short Iavail, unsigned short V
 // 0x01: PSU_RCmd_SysOutputVolCur_F
 void GetPresentOutputFCallback(byte group, float outVol, float outCur)
 {
+    ShmChargerInfo->Control.CommInfo.PsuComm.RxCnt++;
+
     if (ShmPsuData->Work_Step < GET_SYS_CAP || group >= _maxGroupCount ||
         !ShmPsuPosition->PsuLocationInit)
     {
@@ -870,6 +890,8 @@ void GetPresentOutputFCallback(byte group, float outVol, float outCur)
 void GetOutputAndTempCallback(byte address, unsigned short outputVol_s,
 		unsigned short outputCur_s, unsigned short outputPower, unsigned char Temperature)
 {
+    ShmChargerInfo->Control.CommInfo.PsuComm.RxCnt++;
+
     if (ShmPsuData->Work_Step < GET_SYS_CAP || address >= ShmPsuData->SystemPresentPsuQuantity ||
         !ShmPsuPosition->PsuLocationInit)
     {
@@ -893,6 +915,8 @@ void GetOutputAndTempCallback(byte address, unsigned short outputVol_s,
 void GetModuleStatusCallback(byte address, unsigned char isErr, unsigned char status,
 		unsigned char err1, unsigned char err2, unsigned char err3, unsigned char err4)
 {
+    ShmChargerInfo->Control.CommInfo.PsuComm.RxCnt++;
+
     if (ShmPsuData->Work_Step < GET_SYS_CAP || address >= ShmPsuData->SystemPresentPsuQuantity ||
         !ShmPsuPosition->PsuLocationInit)
     {
@@ -924,6 +948,8 @@ void GetModuleStatusCallback(byte address, unsigned char isErr, unsigned char st
 void GetModuleInputCallback(byte address, unsigned short inputR,
 		unsigned short inputS, unsigned short inputT)
 {
+    ShmChargerInfo->Control.CommInfo.PsuComm.RxCnt++;
+
     if (ShmPsuData->Work_Step < GET_SYS_CAP || address >= ShmPsuData->SystemPresentPsuQuantity ||
         !ShmPsuPosition->PsuLocationInit)
     {
@@ -3978,6 +4004,68 @@ void PsuGroupingInitial(void)
     }
 }
 
+void PsuCommLostCheck(void)
+{
+    if(ShmPsuData->Work_Step != INITIAL_START &&
+        ShmPsuData->Work_Step != _NO_WORKING &&
+        ShmPsuData->Work_Step != _INIT_PSU_STATUS)
+    {
+        if(!isCommStart)
+        {
+            isCommStart = true;
+            ShmChargerInfo->Control.CommInfo.PsuComm.RxCnt = 0;
+            lostCnt = 0;
+            GetClockTime(&_PsuCommCheck_time);
+        }
+
+        if((GetTimeoutValue(_PsuCommCheck_time) / uSEC_VAL) >= PSU_COMM_CHECK_TIME)
+        {
+            ShmChargerInfo->Control.CommInfo.PsuComm.CommCnt = ShmChargerInfo->Control.CommInfo.PsuComm.RxCnt;
+            ShmChargerInfo->Control.CommInfo.PsuComm.RxCnt = 0;
+
+            if(ShmChargerInfo->Control.CommInfo.PsuComm.CommCnt > COMM_LOST_CRITICAL)
+            {
+                if(ShmChargerInfo->Control.PsuCtrl.bits.CommunicationLost)
+                {
+                    LOG_INFO("Psu Communication Recovery");
+                }
+                ShmChargerInfo->Control.PsuCtrl.bits.CommunicationLost = NO;
+                lostCnt = 0;
+            }
+            else
+            {
+                lostCnt++;
+                if(lostCnt >= LOST_CNT_CRITICAL)
+                {
+                    if(!ShmChargerInfo->Control.PsuCtrl.bits.CommunicationLost)
+                    {
+                        LOG_INFO("Psu Communication Lost");
+                    }
+                    ShmChargerInfo->Control.PsuCtrl.bits.CommunicationLost = YES;
+                }
+            }
+            GetClockTime(&_PsuCommCheck_time);
+        }
+    }
+    else
+    {
+        isCommStart = false;
+        ShmChargerInfo->Control.PsuCtrl.bits.CommunicationLost = NO;
+        lostCnt = 0;
+        /*
+        if(ShmChargerInfo->Control.PsuCtrl.bits.Paused)
+        {
+            system("ifconfig can1 down");
+            sleep(1);
+            system("ifconfig can1 up");
+            sleep(1);
+            LOG_INFO("Psu Can Port Down & Up");
+        }
+        ShmChargerInfo->Control.PsuCtrl.bits.Paused = NO;
+        */
+    }
+}
+
 int main(void)
 {
     byte _TotalModuleCount = 0;
@@ -4025,6 +4113,7 @@ int main(void)
 	_PrePsuWorkStep = _INIT_PSU_STATUS;
 	ShmPsuData->Work_Step = INITIAL_START;
 	isInitialComp = NO;
+	isCommStart = false;
 
 	LOG_INFO("PSU Work Status = %d", ShmPsuData->Work_Step);
 
@@ -4036,6 +4125,8 @@ int main(void)
 	//main loop
 	while (libInitialize)
 	{
+	    PsuCommLostCheck();
+
 		// 斷電狀態
         if (ShmChargerInfo->Control.RelayCtrl.bits.AcContactor == NO ||
             ShmChargerInfo->Control.RelayCtrl.bits.AcContactorOffByPsu == YES ||
@@ -4050,6 +4141,7 @@ int main(void)
 				ShmPsuData->Work_Step = INITIAL_START;
 				psuCmdSeq = _PSU_CMD_STATUS;
 				_TotalModuleCount = 0;
+				PsuGroupingInitial();
 
 				sleep(2);
 				InitialPsuData();
@@ -4059,6 +4151,7 @@ int main(void)
 			{
 			    ShmChargerInfo->Control.PsuCtrl.bits.NeedSelfTest = NO;
 			    ShmChargerInfo->Control.PsuCtrl.bits.SelfTestOK = NO;
+			    memset(ShmChargerInfo->Control.PsuInitQuantity, 0x00, sizeof(ShmChargerInfo->Control.PsuInitQuantity));
 			    LOG_INFO("Psu Need Execute Self Test!");
 			}
 			sleep(1);
@@ -4066,7 +4159,14 @@ int main(void)
 		}
 		else
 		{
-			isInitialComp = NO;
+            if(isInitialComp)
+            {
+                system("ifconfig can1 down");
+                sleep(1);
+                system("ifconfig can1 up");
+                LOG_INFO("Psu Can Port Down & Up");
+            }
+            isInitialComp = NO;
 		}
 
         // only for test & debug purpose
@@ -4391,6 +4491,10 @@ int main(void)
 				else
 				{
 				    LOG_INFO("== PSU == Self Test OK!");
+                    for(int i = 0; i < MAX_GROUP_QUANTITY; i++)
+                    {
+                        ShmChargerInfo->Control.PsuInitQuantity[i] = ShmPsuData->PsuGroup[i].GroupPresentPsuQuantity;
+                    }
 				}
 				ShmChargerInfo->Control.PsuCtrl.bits.SelfTestOK = true;
 				sleep(1);
@@ -4430,7 +4534,7 @@ int main(void)
                             GetModuleInput(group);
                         }
                     }
-				    GetClockTime(&_cmdSubPriority_time);
+                    GetClockTime(&_cmdSubPriority_time);
 				}
 
 				PsuGroupRoutineQuery();

+ 534 - 129
EVSE/Projects/DO360/Apps/ReadCmdline.c

@@ -42,12 +42,21 @@
 #include    "Common.h"
 
 typedef unsigned char			byte;
-#define	NO_DEFINE			255
-#define DEFAULT_AC_INDEX	2
+#define	NO_DEFINE			    255
 
-#define TTY_PATH            "/dev/tty"
-#define STTY_US             "stty raw -echo -F "
-#define STTY_DEF            "stty -raw echo -F "
+#define OPTION_CNT              3
+#define STR_OPTION              '-'
+#define OPTION_REFLASH          0x00000001
+#define OPTION_LOOP             0x00000002
+#define OPTION_TIME             0x00000004
+
+#define STR_OPT_REFLASH         'f'
+#define STR_OPT_LOOP            'l'
+#define STR_OPT_TIME            't'
+
+#define TTY_PATH                "/dev/tty"
+#define STTY_US                 "stty raw -echo -F "
+#define STTY_DEF                "stty -raw echo -F "
 
 struct SysConfigAndInfo			*ShmSysConfigAndInfo;
 struct StatusCodeData 			*ShmStatusCodeData;
@@ -269,6 +278,21 @@ int InitShareMemory()
     return result;
 }
 
+void Get_Ocpp_TransactionId(int gun_index, char *transactionId)
+{
+    if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16)
+    {
+        sprintf(transactionId, "%d", ShmOCPP16Data->StartTransaction[gun_index].ResponseTransactionId);
+        return;
+    }
+    if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20)
+    {
+        strcpy(transactionId, (char *)&ShmOCPP20Data->TransactionEvent [gun_index].transactionInfo.transactionId[0]);
+        return;
+    }
+    sprintf(transactionId, "%d", 0);
+}
+
 static void get_char(char *word)
 {
     fd_set rfds;
@@ -286,7 +310,7 @@ static void get_char(char *word)
     }
 }
 
-// return string length
+// return command length
 int ParsingCmd(char *inputString, char *outputString)
 {
     bool valid = false, done = false;
@@ -304,7 +328,7 @@ int ParsingCmd(char *inputString, char *outputString)
         }
         else
         {
-            if(inputString[i] == ' ' || inputString[i] == '\0' || inputString[i] == '\r' || inputString[i] == '\n' || len >= 10)
+            if(inputString[i] == ' ' || inputString[i] == '\0' || inputString[i] == '\r' || inputString[i] == '\n' || len >= 32)
             {
                 done = true;
                 break;
@@ -323,6 +347,97 @@ int ParsingCmd(char *inputString, char *outputString)
     return len;
 }
 
+bool IsOption(char *strCmd, unsigned int *opt)
+{
+    int len = 0;
+    char str_opt[OPTION_CNT] = {STR_OPT_REFLASH, STR_OPT_LOOP, STR_OPT_TIME};
+    unsigned int opt_value[OPTION_CNT] = {OPTION_REFLASH, OPTION_LOOP, OPTION_TIME};
+
+    len = strlen(strCmd);
+
+    if(len == 2)
+    {
+        if(strCmd[0] == STR_OPTION)
+        {
+            for(int i = 0; i < OPTION_CNT; i++)
+            {
+                if(strCmd[1] == str_opt[i])
+                {
+                    *opt |= opt_value[i];
+                    return true;
+                }
+            }
+        }
+    }
+
+    return false;
+}
+
+//  inputCmdString: console input string
+// outputCmdString: input string parsed
+// return command quantity
+int InputStringNormalize(char *inputCmdString, char *outputCmdString, unsigned int *opt)
+{
+    int len = 0, cnt = 0, start = 0;
+    int cmdLen = 0, totalLen = 0;
+
+    len = strlen(inputCmdString);
+    *opt = 0;
+
+    if(len > 0)
+    {
+        while(start < len - 1)
+        {
+            if(inputCmdString[start] != ' ' && inputCmdString[start] != '\0')
+            {
+                cmdLen = ParsingCmd(&inputCmdString[start], &outputCmdString[totalLen]);
+
+                if(cmdLen > 0)
+                {
+                    //printf("Find %d Cmd: %s\r\n", cnt + 1, &outputCmdString[totalLen]);
+
+                    if(!IsOption(&outputCmdString[totalLen], opt))
+                    {
+                        outputCmdString[totalLen + cmdLen] = ' ';
+                        cnt++;
+                        totalLen += cmdLen + 1;
+                    }
+                    start += cmdLen;
+                }
+            }
+            else
+            {
+                start++;
+            }
+        }
+        outputCmdString[totalLen - 1] = '\0';
+    }
+    return cnt;
+}
+
+int MainAndSubCommandParsing(char *normalCmd, char *mainCmd, char *subCmd)
+{
+    int len = 0, totalLen = 0;
+
+    strcpy(mainCmd, "");
+    strcpy(subCmd, "");
+
+    totalLen = strlen(normalCmd);
+
+    if(totalLen > 0)
+    {
+        len = ParsingCmd(normalCmd, mainCmd);
+        //printf("Find MainCmd: %s\r\n", mainCmd);
+
+        if(len > 0 && totalLen > len)
+        {
+            strcpy(subCmd, &normalCmd[len + 1]);
+            //printf("Find SubCmd: %s\r\n", subCmd);
+        }
+    }
+    return 0;
+}
+
 int GetCommandSring(char *outputCmdString)
 {
     int len = 0, cnt = 0;
@@ -385,6 +500,19 @@ bool IsLoopStopCmd(void)
     return stop;
 }
 
+void ConsoleReflash(int groupCnt, int lineCnt)
+{
+    for(int i = 0; i < groupCnt; i++)
+    {
+        for(int i = 0; i < lineCnt; i++)
+        {
+            printf("\033[1A");
+            printf("\033[K");
+        }
+    }
+    printf("\r");
+}
+
 void RunStatusProc(char *v1, char *v2)
 {
 	printf("OrderCharging = %d \n", ShmSysConfigAndInfo->SysInfo.OrderCharging);
@@ -746,52 +874,6 @@ void GetSystemInfo()
 	printf("\r\n\r\n");
 }
 
-void ChangeGunNum()
-{
-	if (ShmSysConfigAndInfo->SysInfo.CurGunSelected + 1 < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount)
-	{
-		ShmSysConfigAndInfo->SysInfo.CurGunSelected += 1;
-		ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc = NO_DEFINE;
-	}
-	else if (ShmSysConfigAndInfo->SysConfig.AcConnectorCount > 0 &&
-			ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc == NO_DEFINE)
-		ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc = DEFAULT_AC_INDEX;
-	else
-	{
-		ShmSysConfigAndInfo->SysInfo.CurGunSelected = 0;
-		ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc = NO_DEFINE;
-	}
-}
-
-void GetGunSelectedNum(char *v1)
-{
-	if (strcmp(v1, "-1") == 0 || strcmp(v1, "") == 0)
-	{
-		if (AC_QUANTITY > 0 &&
-			ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc != NO_DEFINE)
-		{
-			printf("connector select changed = AC \n");
-		}
-		else
-			printf("connector selected = %d \n", ShmSysConfigAndInfo->SysInfo.CurGunSelected);
-	}
-	else
-	{
-		int _index = atoi(v1);
-		if (_index <= 1)
-		{
-			ShmSysConfigAndInfo->SysInfo.CurGunSelected = _index;
-			ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc = NO_DEFINE;
-			printf("connector select changed = %d \n", _index);
-		}
-		else if (AC_QUANTITY > 0)
-		{
-			ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc = DEFAULT_AC_INDEX;
-			printf("connector select changed = AC \n");
-		}
-	}
-}
-
 void SetFanSpeed(char *v1)
 {
 	int speed = atoi(v1);
@@ -825,25 +907,32 @@ void SetGFDMode(char *v1)
 //                        PSU 0        PSU 1        PSU 2        ...
 // Gun  Temp  Chiller   DD/PFC/Amb   DD/PFC/Amb   DD/PFC/Amb   DD/PFC/Amb
 //  1    XXX    XXX    XXX/XXX/XXX  XXX/XXX/XXX  XXX/XXX/XXX  XXX/XXX/XXX
-void GetTemperature(char *v1)
+void GetTemperature(char *inputCmd, unsigned int opt)
 {
-    bool loop = false;
+    bool keepRun = false;
+    bool reflash = false;
     int time = 0;
     struct timespec _Loop_time;
     char strGunTemp[16], strChillerTemp[16];
 
-    if(strcmp(v1, "c") == 0)
+    if((opt & OPTION_REFLASH) || (opt & OPTION_LOOP) > 0)
     {
-        loop = true;
+        keepRun = true;
     }
 
+    printf("\r\n");
+    printf("                        PSU 0        PSU 1        PSU 2        .....\r\n");
+    printf(" Gun  Temp  Chiller   DD/PFC/Amb   DD/PFC/Amb   DD/PFC/Amb   DD/PFC/Amb\r\n");
+
     do
     {
         time = GetTimeoutValue(_Loop_time) / mSEC_VAL;
         if(time >= 1000)
         {
-            printf("                        PSU 0        PSU 1        PSU 2        .....\r\n");
-            printf(" Gun  Temp  Chiller   DD/PFC/Amb   DD/PFC/Amb   DD/PFC/Amb   DD/PFC/Amb\r\n");
+            if(reflash)
+            {
+                ConsoleReflash(CONNECTOR_QUANTITY, 1);
+            }
 
             for(int i = 0; i < CONNECTOR_QUANTITY; i++)
             {
@@ -869,34 +958,44 @@ void GetTemperature(char *v1)
                 }
                 printf("\r\n");
             }
-            printf("\r\n");
             GetClockTime(&_Loop_time);
+
+            if((opt & OPTION_REFLASH) > 0)
+            {
+                reflash = true;
+            }
         }
 
-        if(loop)
+        if(keepRun)
         {
-            loop = IsLoopStopCmd() ? false : true;
+            keepRun = IsLoopStopCmd() ? false : true;
             usleep(10000);
         }
-    }while(loop);
+    }while(keepRun);
 }
 
-void GetInputVol(char *v1)
+void GetInputVol(char *inputCmd, unsigned int opt)
 {
-    bool loop = false;
+    bool keepRun = false;
+    bool reflash = false;
     int time = 0;
     struct timespec _Loop_time;
 
-    if(strcmp(v1, "c") == 0)
+    if((opt & OPTION_REFLASH) || (opt & OPTION_LOOP) > 0)
     {
-        loop = true;
+        keepRun = true;
     }
 
+    printf("\r\n");
     do
     {
         time = GetTimeoutValue(_Loop_time) / mSEC_VAL;
         if(time >= 1000)
         {
+            if(reflash)
+            {
+                ConsoleReflash(1, 1);
+            }
             printf("L1N_L12 = %4.1f V, L2N_L23 = %4.1f V, L3N_L31 = %4.1f V, DC Input: %4.1f V\r\n",
                     ShmSysConfigAndInfo->SysInfo.InputVoltageR,
                     ShmSysConfigAndInfo->SysInfo.InputVoltageS,
@@ -904,14 +1003,19 @@ void GetInputVol(char *v1)
                     ShmSysConfigAndInfo->SysInfo.InputVoltageDc);
 
             GetClockTime(&_Loop_time);
+
+            if((opt & OPTION_REFLASH) > 0)
+            {
+                reflash = true;
+            }
         }
 
-        if(loop)
+        if(keepRun)
         {
-            loop = IsLoopStopCmd() ? false : true;
+            keepRun = IsLoopStopCmd() ? false : true;
             usleep(10000);
         }
-    }while(loop);
+    }while(keepRun);
     printf("\r\n");
 }
 
@@ -2181,14 +2285,16 @@ void RunSimplePsuGrouping(char *v1, char *v2)
     }
 }
 
+
 void ShowCabinetInfo(void)
 {
     int ipAddress = 0;
 
-    printf("\r\nPower Cabinet Charging Mode = %d, ReAssignedFlag = %d, Psu Work Step = %d",
-        ShmSysConfigAndInfo->SysInfo.MainChargingMode, ShmSysConfigAndInfo->SysInfo.ReAssignedFlag, ShmPsuData->Work_Step);
+    printf("\r\n");
+    printf("Psu Work Step = %d, PsuComm: %d\r\n", ShmPsuData->Work_Step, ShmChargerInfo->Control.CommInfo.PsuComm.CommCnt);
+    printf("Psu RxCnt: %d\r\n", ShmChargerInfo->Control.CommInfo.PsuComm.RxCnt);
 
-    printf("\r\n Dispenser: %d / %d, Connector: %d / %d",
+    printf(" Dispenser: %d / %d, Connector: %d / %d\r\n",
         ShmSysConfigAndInfo->SysInfo.DispenserInfo.PresentDispenserQuantity,
         ShmSysConfigAndInfo->SysInfo.DispenserInfo.DispenserQuantity,
         ShmSysConfigAndInfo->SysInfo.DispenserInfo.PresentConnectorQuantity,
@@ -2198,7 +2304,7 @@ void ShowCabinetInfo(void)
     {
         ipAddress = ShmSysConfigAndInfo->SysInfo.DispenserInfo.ConnectionInfo[i].IpAddress;
 
-        printf("\r\n Dispenser Connection[%d] Status: %d, DispenserIndex: %d, IP: %d.%d.%d.%d", i,
+        printf(" Dispenser Connection[%d] Status: %d, DispenserIndex: %d, IP: %d.%d.%d.%d\r\n", i,
                 ShmSysConfigAndInfo->SysInfo.DispenserInfo.ConnectionInfo[i].Status,
                 ShmSysConfigAndInfo->SysInfo.DispenserInfo.ConnectionInfo[i].DispenserIndex,
                 ((ipAddress >> 0) & 0xFF), ((ipAddress >> 8) & 0xFF), ((ipAddress >> 16) & 0xFF), ((ipAddress >> 24) & 0xFF));
@@ -2206,13 +2312,13 @@ void ShowCabinetInfo(void)
     printf("\r\n");
     for(int i = 0; i < GENERAL_GUN_QUANTITY; i++)
     {
-        printf("\r\n Connector[%d] Index: %2X, Status = %2d , %s", i, _chargingData[i]->Index, _chargingData[i]->SystemStatus,
+        printf(" Connector[%d] Index: %2X, Status = %2d , %s\r\n", i, _chargingData[i]->Index, _chargingData[i]->SystemStatus,
             ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].Enable ? "Enable" : "Disable");
     }
 
     for(int i = 0; i < ShmSysConfigAndInfo->SysInfo.DispenserInfo.DispenserQuantity; i++)
     {
-        printf("\r\n  Dispenser[%d] Status: %d", i, ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].LocalStatus);
+        printf("  Dispenser[%d] Status: %d", i, ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].LocalStatus);
         if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].LocalStatus != _DS_None &&
             ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].LocalStatus != _DS_Timeout)
         {
@@ -2225,20 +2331,20 @@ void ShowCabinetInfo(void)
                     ipAddress = ShmSysConfigAndInfo->SysInfo.DispenserInfo.ConnectionInfo[j].IpAddress;
                 }
             }
-            printf(", ModelName: %s, IP: %d.%d.%d.%d", ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].ModelName,
+            printf(", ModelName: %s, IP: %d.%d.%d.%d\r\n", ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].ModelName,
                 ((ipAddress >> 0) & 0xFF), ((ipAddress >> 8) & 0xFF), ((ipAddress >> 16) & 0xFF), ((ipAddress >> 24) & 0xFF));
             for(int j = 0; j < ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].ConnectorQuantity; j++)
             {
                 unsigned char gun = ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].ConnectorID[j];
-                printf("\r\n   - Connector[%d] Gun %d, %s", j, gun, _chargingData[gun - 1]->ConnectorPlugIn ? "Plugged" : "Unplugged");
+                printf("   - Connector[%d] Gun %d, %s\r\n", j, gun, _chargingData[gun - 1]->ConnectorPlugIn ? "Plugged" : "Unplugged");
             }
         }
         else
         {
-            printf(", No Information");
+            printf(", No Information\r\n");
         }
     }
-    printf("\r\n\r\n");
+    printf("\r\n");
 }
 
 void SetTestControl(char *v1, char *v2)
@@ -3111,8 +3217,290 @@ void SetGunCommand(char *v1, char *v2, char *v3)
     printf("\r\n");
 }
 
+void ShowWebSystemInfo(void)
+{
+    char *str_led_intensity[] = {STR_DARKEST, STR_MEDIUM, STR_BRIGHTEST};
+    char *str_qr_code_made[] = {STR_QR_DEFAULT, STR_QR_CUSTOMIZED, STR_QR_CHARGEBOXID};
+    char *str_rfid_endian[] = {STR_LITTLE_ENDIAN, STR_BIG_ENDIAN};
+
+    printf("\r\n");
+    printf("Web [System]\r\n");
+    printf(" *System ID: %s\r\n", ShmSysConfigAndInfo->SysConfig.SystemId);
+    printf(" *AuthorisationMode[%7s]\r\n",
+        ShmSysConfigAndInfo->SysConfig.AuthorisationMode == AUTH_MODE_ENABLE ? "Enable" : "Disable");
+    printf("  - APP    [%7s]\r\n", ShmSysConfigAndInfo->SysConfig.isAPP > 0 ? "Enable" : "Disable");
+    printf("  - QRCode [%7s]\r\n", ShmSysConfigAndInfo->SysConfig.isQRCode > 0 ? "Enable" : "Disable");
+    printf("  - RFID   [%7s]\r\n", ShmSysConfigAndInfo->SysConfig.isRFID > 0 ? "Enable" : "Disable");
+    printf("  - EVCCID [%7s]\r\n", ShmSysConfigAndInfo->SysConfig.isAuthrizeByEVCCID > 0 ? "Enable" : "Disable");
+
+    if(ShmSysConfigAndInfo->SysConfig.RfidCardNumEndian <= RFID_ENDIAN_BIG)
+    {
+        printf(" *RfidCardNumEndian [%s]\r\n", str_rfid_endian[ShmSysConfigAndInfo->SysConfig.RfidCardNumEndian]);
+    }
+    else
+    {
+        printf(" *RfidCardNumEndian: %d\r\n", ShmSysConfigAndInfo->SysConfig.RfidCardNumEndian);
+    }
+
+    if(ShmSysConfigAndInfo->SysConfig.QRCodeMadeMode <= _QR_MODE_Customized)
+    {
+        printf(" *QR Code Made [%s]\r\n", str_qr_code_made[ShmSysConfigAndInfo->SysConfig.QRCodeMadeMode]);
+    }
+    else
+    {
+        printf(" *QR Code Made: %d\r\n", ShmSysConfigAndInfo->SysConfig.QRCodeMadeMode);
+    }
+    if(ShmSysConfigAndInfo->SysConfig.QRCodeMadeMode == _QR_MODE_Customized)
+    {
+        printf("  - QR Code Content: %s\r\n", ShmSysConfigAndInfo->SysConfig.QRCodeContent);
+    }
+
+    if(ShmChargerInfo->AuthInfo.QRCodeMode <= _QR_MODE_ChargeBoxId)
+    {
+        printf(" *QR Code Mode [%s]\r\n", str_qr_code_made[ShmChargerInfo->AuthInfo.QRCodeMode]);
+    }
+    else
+    {
+        printf(" *QR Code Mode: %d\r\n", ShmChargerInfo->AuthInfo.QRCodeMode);
+    }
+
+    if(ShmSysConfigAndInfo->SysConfig.LedInfo.Intensity <= _LED_INTENSITY_BRIGHTEST)
+    {
+        printf(" *LED Intensity[%s]\r\n", str_led_intensity[ShmSysConfigAndInfo->SysConfig.LedInfo.Intensity]);
+    }
+    else
+    {
+        printf(" *LED Intensity[%d]\r\n",  ShmSysConfigAndInfo->SysConfig.LedInfo.Intensity);
+    }
+}
+
+void ShowWebChargingInfo(void)
+{
+    printf("\r\n");
+    printf("Web [Charging]\r\n");
+    printf(" *Max Charging Energy  : %4d kWh\r\n", ShmSysConfigAndInfo->SysConfig.MaxChargingEnergy);
+    printf(" *Max Charging Power   : %4d kW\r\n", ShmSysConfigAndInfo->SysConfig.MaxChargingPower);
+    printf(" *Max Charging Current : %4d A\r\n", ShmSysConfigAndInfo->SysConfig.MaxChargingCurrent);
+    printf(" *Max Charging Duration: %4d Minutes\r\n", ShmSysConfigAndInfo->SysConfig.MaxChargingDuration);
+    printf(" *StopCharging By Button[%7s]\r\n", ShmSysConfigAndInfo->SysConfig.StopChargingByButton > 0 ? "Enable" : "Disable");
+    printf(" *Billing[%7s]\r\n", ShmSysConfigAndInfo->SysConfig.BillingData.isBilling > 0 ? "Enable" : "Disable");
+    printf("  - Currency[%2d]\r\n", ShmSysConfigAndInfo->SysConfig.BillingData.Currency);
+}
+
+void ShowWebNetworkInfo(void)
+{
+    char *str_wifi_mode[] = {"Disable", "Station", "AP Mode"};
+
+    printf("\r\n");
+    printf("Web [Network]\r\n");
+    printf(" *NetworkStatus[%s]\r\n", ShmSysConfigAndInfo->SysInfo.InternetConn > 0 ? "Connected" : "Disconnected");
+    printf(" *DHCP Client[%7s]\r\n", ShmSysConfigAndInfo->SysConfig.Eth0Interface.EthDhcpClient == 0 ? "Enable" : "Disable");
+    if(ShmSysConfigAndInfo->SysConfig.AthInterface.WifiMode <= _SYS_WIFI_MODE_AP)
+    {
+        printf(" *WiFi Mode  [%7s]\r\n", str_wifi_mode[ShmSysConfigAndInfo->SysConfig.AthInterface.WifiMode]);
+    }
+    else
+    {
+        printf(" *WiFi Mode  [%d]\r\n", ShmSysConfigAndInfo->SysConfig.AthInterface.WifiMode);
+    }
+    printf("  - ConnStatus[%s]\r\n", ShmSysConfigAndInfo->SysConfig.AthInterface.WifiNetworkConn == YES ? "Connected" : "Disconnected");
+    printf(" *3G/4G Mode [%7s]\r\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomEnabled == YES ? "Enable" : "Disable");
+    printf("  - ConnStatus[%s]\r\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomNetworkConn  == YES ? "Connected" : "Disconnected");
+    printf("  - APN : %s\r\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomApn);
+    printf("  - RSSI: %d dBm\r\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomRssi);
+}
+
+void ShowWebBackendInfo(void)
+{
+    char *str_offline_policy[] = {"Local List", "Phihong RFID", "Free Charging", "No Charging"};
+    char *str_security_profile[] = {
+        "None security",
+        "Unsecured Transport with Basic Atuentication",
+        "TLS with Basic Authentication",
+        "TLS with Client Side Certificates"
+    };
+
+    printf("\r\n");
+    printf("Web [Backend]\r\n");
+    printf(" *Common\r\n");
+    printf("  - Backend Timeout   : %d s\r\n", ShmSysConfigAndInfo->SysConfig.BackendConnTimeout);
+    if(ShmSysConfigAndInfo->SysConfig.OfflinePolicy <= _OFFLINE_POLICY_NO_CHARGING)
+    {
+        printf("  - Offline Policy    : %s\r\n", str_offline_policy[ShmSysConfigAndInfo->SysConfig.OfflinePolicy]);
+    }
+    else
+    {
+        printf("  - Offline Policy    : %d\r\n", ShmSysConfigAndInfo->SysConfig.OfflinePolicy);
+    }
+    printf("  - OfflineMaxEnergy  : %4d kWh\r\n", ShmSysConfigAndInfo->SysConfig.OfflineMaxChargeEnergy);
+    printf("  - OfflineMaxDuration: %4d Minutes\r\n", ShmSysConfigAndInfo->SysConfig.OfflineMaxChargeDuration);
+    printf(" *OCPP\r\n");
+    printf("  - OcppStatus[%s]\r\n", ShmSysConfigAndInfo->SysInfo.OcppConnStatus == YES ? "Connected" : "Disconnected");
+    printf("  - OcppURL    : %s\r\n", ShmSysConfigAndInfo->SysConfig.OcppServerURL);
+    printf("  - ChargeBoxId: %s\r\n", ShmSysConfigAndInfo->SysConfig.ChargeBoxId);
+    printf("  - Vendor     : %s\r\n", ShmSysConfigAndInfo->SysConfig.chargePointVendor);
+    if(ShmSysConfigAndInfo->SysConfig.OcppSecurityProfile <= 3)
+    {
+        printf("  - Security   : %s\r\n", str_security_profile[ShmSysConfigAndInfo->SysConfig.OcppSecurityProfile]);
+    }
+    else
+    {
+        printf("  - Security   : %d\r\n", ShmSysConfigAndInfo->SysConfig.OcppSecurityProfile);
+    }
+    printf("  - MaintainStatus[%s]\r\n", ShmSysConfigAndInfo->SysInfo.MaintainServerConnStatus == YES ? "Connected" : "Disconnected");
+    printf("  - MaintainURL     : %s\r\n", ShmSysConfigAndInfo->SysConfig.MaintainServerURL);
+    if(ShmSysConfigAndInfo->SysConfig.MaintainServerSecurityProfile <= 3)
+    {
+        printf("  - MaintainSecurity: %s\r\n", str_security_profile[ShmSysConfigAndInfo->SysConfig.MaintainServerSecurityProfile]);
+    }
+    else
+    {
+        printf("  - MaintainSecurity: %d\r\n", ShmSysConfigAndInfo->SysConfig.MaintainServerSecurityProfile);
+    }
+    printf(" *TTIA[%7s]\r\n", ShmSysConfigAndInfo->SysConfig.TTIA_Info.isEnableTTIA == YES ? "Enable" : "Disable");
+    if(ShmSysConfigAndInfo->SysConfig.TTIA_Info.isEnableTTIA == YES)
+    {
+        printf("  - ServerAddress: %s\r\n", ShmSysConfigAndInfo->SysConfig.TTIA_Info.server_addr);
+        printf("  - ServerPort   : %d\r\n", ShmSysConfigAndInfo->SysConfig.TTIA_Info.server_port);
+        printf("  - BusVenderId  : %d\r\n", ShmSysConfigAndInfo->SysConfig.TTIA_Info.busVenderId);
+        printf("  - Provider     : %s\r\n", ShmSysConfigAndInfo->SysConfig.TTIA_Info.EquipmentProvider);
+        printf("  - CompanyNo    : %d\r\n", ShmSysConfigAndInfo->SysConfig.TTIA_Info.TransportationCompanyNo);
+        printf("  - ChargeBoxId  : %d\r\n", ShmSysConfigAndInfo->SysConfig.TTIA_Info.ChargeBoxId);
+        printf("  - EVSEStation  : %s\r\n", ShmSysConfigAndInfo->SysConfig.TTIA_Info.evseStation);
+    }
+}
+
+void ShowWebAllInfo(void)
+{
+    ShowWebSystemInfo();
+    ShowWebChargingInfo();
+    ShowWebNetworkInfo();
+    ShowWebBackendInfo();
+}
+
+void ShowWebInfo(char *v1)
+{
+    bool find = false;
+    int showItem = 0;
+    int itemLen = 5;
+    char strItem[32][32] = {"system", "charging", "network", "backend", "all"};
+    void *actionList[32] = {&ShowWebSystemInfo, &ShowWebChargingInfo, &ShowWebNetworkInfo, &ShowWebBackendInfo, &ShowWebAllInfo};
+    void (*ItemAction)();
+
+    for(showItem = 0; showItem < itemLen; showItem++)
+    {
+        if(strcmp((char *)&strItem[showItem][0], v1) == 0)
+        {
+            find = true;
+            break;
+        }
+    }
+
+    if(find)
+    {
+        ItemAction = actionList[showItem];
+        ItemAction();
+    }
+    else
+    {
+        printf("\r\n");
+        printf ("Input cmd fail ------  web [cmd]\r\n");
+        for(int i = 0; i < itemLen; i++)
+        {
+            printf(" [cmd] %s\r\n", (char *)&strItem[i][0]);
+        }
+    }
+
+    printf("\r\n");
+}
+
+// Gun 1 (  CCS  )   Soc:   XXX %,  Energy:   XXXXX.X kWh, IdTag [XXXXXXXXXXXXXXXX] Transaction [0]
+// Gun 1 (  CCS  ) IdTag: XXXXXXXXXXXXXXXX,   Soc:  XXX %, Energy: XXXX.X kWh
+//  (XX)    (X)   Target:  XXXX V,  XXXX A,   Cap: XXXX A, XXXX kW
+//                Output:  XXXX V,  XXXX A, Limit: XXXX A, XXXX kW
+void ShowGunInfo(int gun)
+{
+    char *str_gun_type[] = {"CHAdeMO", "  CCS  ", "  GBT  "};
+    char acceptId[128];
+    Get_Ocpp_TransactionId(gun, acceptId);
+    printf(" Gun %d (%s)   Soc:   %3d %s,  Energy:   %7.1f kWh, IdTag [%16s] Transaction [%s]\r\n",
+        gun + 1,
+        ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun].Enable ? str_gun_type[_chargingData[gun]->Type] : "Disable",
+        _chargingData[gun]->EvBatterySoc, "%",
+        _chargingData[gun]->PresentChargedEnergy,
+        _chargingData[gun]->StartUserId,
+        acceptId);
+    //printf(" Gun %d (%s) IdTag [%16s]    Soc:  %3d %s, Energy: %4.1f kWh\r\n",
+    //    i + 1,
+    //    ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].Enable ? str_gun_type[_chargingData[i]->Type] : "Disable",
+    //    _chargingData[i]->StartUserId,
+    //    _chargingData[i]->EvBatterySoc, "%",
+    //    _chargingData[i]->PresentChargedEnergy);
+    printf("  (%2d)    (%s)   Target:  %4d V,  %4d A,   Cap: %4d A, %4d kW\r\n",
+        _chargingData[gun]->SystemStatus,
+        _chargingData[gun]->ConnectorPlugIn ? "O" : "X",
+        (int)_chargingData[gun]->EvBatterytargetVoltage,
+        (int)_chargingData[gun]->EvBatterytargetCurrent,
+        (int)(_chargingData[gun]->AvailableChargingCurrent / 10),
+        (int)(_chargingData[gun]->AvailableChargingPower / 10));
+    printf("                Output:  %4d V,  %4d A, Limit: %4d A, %4d kW\r\n",
+        (int)(_chargingData[gun]->PresentChargingVoltage),
+        (int)(_chargingData[gun]->PresentChargingCurrent),
+        (int)(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun].CapabilityCurrent / 10),
+        (int)(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun].CapabilityPower / 10));
+}
+
+void ShowInfo(char *inputCmd, unsigned int opt)
+{
+    bool keepRun = false;
+    bool reflash = false;
+    int time = 0;
+    struct timespec _Loop_time;
+
+    if((opt & OPTION_REFLASH) || (opt & OPTION_LOOP) > 0)
+    {
+        keepRun = true;
+    }
+
+    do
+    {
+        time = GetTimeoutValue(_Loop_time) / mSEC_VAL;
+        if(time >= 1000)
+        {
+            if(reflash)
+            {
+                ConsoleReflash(CONNECTOR_QUANTITY, 4);
+            }
+
+            for(int i = 0; i < GENERAL_GUN_QUANTITY; i++)
+            {
+                printf("\r\n");
+                ShowGunInfo(i);
+            }
+            GetClockTime(&_Loop_time);
+
+            if((opt & OPTION_REFLASH) > 0)
+            {
+                reflash = true;
+            }
+        }
+
+        if(keepRun)
+        {
+            keepRun = IsLoopStopCmd() ? false : true;
+            usleep(10000);
+        }
+    }while(keepRun);
+    printf("\r\n");
+}
+
 int main(void)
 {
+    char newString[32][32];
+    char inputString[128], normalCmd[128], mainCmd[128], subCmd[128], multiCmd[128];
+    int cmdCnt = 0, parseCnt = 0;
+    unsigned int option = 0;
+
 	if(InitShareMemory() == FAIL)
 	{
 		printf ("InitShareMemory = FAIL \n");
@@ -3132,46 +3520,63 @@ int main(void)
         }
     }
 
-    /*
-    memset(&ShmChargerInfo->PsuGrouping.GroupCollection[0], 0x00, sizeof(PsuGroupCollectionData));
-    memset(&ShmChargerInfo->PsuGrouping.GroupCollection[1], 0x00, sizeof(PsuGroupCollectionData));
-    memset(&ShmChargerInfo->PsuGrouping.GroupCollection[2], 0x00, sizeof(PsuGroupCollectionData));
-    memset(&ShmChargerInfo->PsuGrouping.GroupCollection[3], 0x00, sizeof(PsuGroupCollectionData));
-    ShmChargerInfo->PsuGrouping.GroupCollection[0].Index = 0;
-    ShmChargerInfo->PsuGrouping.GroupCollection[1].Index = 1;
-    ShmChargerInfo->PsuGrouping.GroupCollection[2].Index = 2;
-    ShmChargerInfo->PsuGrouping.GroupCollection[3].Index = 3;
-    ShmChargerInfo->PsuGrouping.GroupCollection[0].Location = 0;
-    ShmChargerInfo->PsuGrouping.GroupCollection[1].Location = 3;
-    ShmChargerInfo->PsuGrouping.GroupCollection[2].Location = 1;
-    ShmChargerInfo->PsuGrouping.GroupCollection[3].Location = 2;
-    */
+    // clean command
+    memset(mainCmd, 0x00, sizeof(mainCmd));
+    memset(subCmd, 0x00, sizeof(subCmd));
+    for(int i = 0; i < 32; i++)
+    {
+        memset(&newString[i], 0x00, 32);
+    }
 
 	for(;;)
 	{
-		char word[128];
-		char newString[7][32];
-		int i,j,ctr;
+        memset(inputString, 0x00, sizeof(inputString));
+        memset(normalCmd, 0x00, sizeof(normalCmd));
+
+        get_char(inputString);
+        cmdCnt = InputStringNormalize(inputString, normalCmd, &option);
+        if(cmdCnt > 0)
+        {
+            // clean command
+            memset(mainCmd, 0x00, sizeof(mainCmd));
+            memset(subCmd, 0x00, sizeof(subCmd));
+            for(int i = 0; i < 32; i++)
+            {
+                memset(&newString[i], 0x00, 32);
+            }
 
-		fgets(word, sizeof(word), stdin);
+            //printf("CmdCnt: %d\r\n", cmdCnt);
+            //printf("Input: %s", inputString);
+            //printf("Normalize: %s\r\n", normalCmd);
+            //printf("option: %08X\r\n", option);
 
-		j=0; ctr=0;
-		strcpy(newString[1], "-1");
-		strcpy(newString[2], "-1");
-		for (i = 0; i <= (strlen(word)); i++)
-		{
-			if (word[i] == ' ' || word[i] == '\0' || word[i] == 10)
-			{
-				newString[ctr][j] = '\0';
-				ctr++;
-				j = 0;
-			}
-			else
-			{
-				newString[ctr][j] = word[i];
-				j++;
-			}
-		}
+            MainAndSubCommandParsing(normalCmd, mainCmd, subCmd);
+            //printf("MainCmd: %s\r\n", mainCmd);
+            //printf("SubCmd: %s\r\n", subCmd);
+
+            parseCnt = 0;
+            strcpy(multiCmd, normalCmd);
+            do
+            {
+                MainAndSubCommandParsing(multiCmd, &newString[parseCnt][0], &newString[parseCnt + 1][0]);
+                strcpy(multiCmd, &newString[parseCnt + 1][0]);
+                //printf("MultiCmd Parse %d\r\n", parseCnt + 1);
+                //printf("MainCmd: %s\r\n", &newString[parseCnt][0]);
+                //printf("SubCmd: %s\r\n", &newString[parseCnt + 1][0]);
+                parseCnt++;
+            }while(parseCnt < cmdCnt - 1);
+
+            //printf("\r\n");
+            //for(int i = 0; i < cmdCnt; i++)
+            //{
+            //    printf("MultiCmd %d: [%s]\r\n", i + 1, &newString[i][0]);
+            //}
+        }
+        else
+        {
+            usleep(100000);
+            continue;
+        }
 
 		if(strcmp(newString[0], "state") == 0)
 		{
@@ -3248,16 +3653,6 @@ int main(void)
 		{
 			GetSystemInfo();
 		}
-		else if(strcmp(newString[0], "select") == 0)
-		{
-		    // 取得 / 設定 當前選的槍號
-			GetGunSelectedNum(newString[1]);
-		}
-		else if(strcmp(newString[0], "change") == 0)
-		{
-		    // 模擬按鈕改變選槍
-			ChangeGunNum();
-		}
 		else if(strcmp(newString[0], "fan") == 0)
 		{
 		    // 設定風扇速度
@@ -3278,15 +3673,15 @@ int main(void)
 		    // 設定盲沖使用 GFD 功能
 			SetGFDMode(newString[1]);
 		}
-		else if(strcmp(newString[0], "temp") == 0)
+		else if(strcmp(mainCmd, "temp") == 0)
 		{
 		    // 取得溫度
-		    GetTemperature(newString[1]);
+		    GetTemperature(subCmd, option);
 		}
-		else if(strcmp(newString[0], "acin") == 0)
+		else if(strcmp(mainCmd, "acin") == 0)
 		{
 		    // 取得三向輸入電壓
-			GetInputVol(newString[1]);
+			GetInputVol(subCmd, option);
 		}
 		else if(strcmp(newString[0], "psu") == 0)
 		{
@@ -3497,9 +3892,19 @@ int main(void)
                 continue;
             }
             SetGunCommand(newString[1], newString[2], newString[3]);
+        }
+        else if(strcmp(newString[0], "web") == 0)
+        {
+            ShowWebInfo(newString[1]);
+        }
+        else if(strcmp(mainCmd, "info") == 0)
+        {
+            ShowInfo(subCmd, option);
         }
 		else
+		{
 			printf ("%s\n", msg);
+		}
 		usleep(100000);
 	}
 

+ 1 - 0
EVSE/Projects/DO360/Apps/kill.sh

@@ -12,6 +12,7 @@ pkill Module_ProduceUtils
 pkill Module_ChargerSelfTest
 pkill Module_CabinetParallel
 pkill Module_LedIndication
+pkill Module_Authorize
 pkill main
 
 sleep 1

Fișier diff suprimat deoarece este prea mare
+ 207 - 674
EVSE/Projects/DO360/Apps/main.c


BIN
EVSE/Projects/DO360/Images/FactoryDefaultConfig.bin


BIN
EVSE/Projects/DO360/Images/ramdisk.gz


+ 2 - 1
EVSE/Projects/define.h

@@ -715,7 +715,8 @@ typedef union
         unsigned int StopButtonStatusRequest:1;         // 0: no request,   1: stop charging button status has changed          ( cabinet -> dispenser)
         unsigned int AuthModeConfigRequest:1;           // 0: no request,   1: AuthMode Config has changed                      ( cabinet -> dispenser)
         unsigned int EVCCIDConfigRequest:1;             // 0: no request,   1: EVCCID Config has changed                        ( cabinet -> dispenser)
-        unsigned int res:8;
+        unsigned int LEDIntensityRequest:1;             // 0: no request,   1: LED Intensity has changed                        ( cabinet -> dispenser)
+        unsigned int res:7;
     }bits;
 }DispenserSettingFlag;
 

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff