Эх сурвалжийг харах

2022-12-19 / Wendell

Actions
1. [add] ocmf upload
2. [add] customized standby time for e4u
3. [add] self test of tilt sensor
4. [add] stop charging when all one psu in a group are alarm/fault
5. [add] start id type
6. [add] occupancy fee force cancel
7. [add] add status code when charging pwemission is not permitted
8. [add] psu Indication
9. [add] diagnostics of dispenser
10.[add] add information to database(model_name column of reboot_record table)(connector cloumn of )
11.[mod] modify StartTransactionConf logic for ocpp 2.0
12.[mod] improve update firmware logic
13.[mod] improve otp logic
14.[mod] improve output limit logic
15.[mod] clean default maintain server
16.[mod] modify infy power module controll logic
17.[fix] psu input voltage
18.[fix] fix RemoteMaxPhysicalVoltage & RemoteMaxPhysicalCurrent is null
19.[fix] fix extend psu logic
20.modify subVersion to 03

Files
1. As follow commit history

Image version : V2.05.XX.XXXX.XX
Wendell 2 жил өмнө
parent
commit
d579be974d

+ 70 - 10
EVSE/Projects/DO360/Apps/Common.c

@@ -12,6 +12,9 @@
 #include <stdarg.h>
 #include <time.h>
 #include <sys/timeb.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
 #include "Common.h"
 
 int StoreSysLogMsg(const char *fmt, ...)
@@ -66,7 +69,7 @@ int StorePsuLogMsg(const char *fmt, ...)
     return rc;
 }
 
-int StoreEventLogMsg(const char *fmt, ...)
+int StoreAuthLogMsg(const char *fmt, ...)
 {
     char Buf[4096+256];
     char buffer[4096];
@@ -83,7 +86,7 @@ int StoreEventLogMsg(const char *fmt, ...)
     SeqEndTime.time = time(NULL);
     tm=localtime(&SeqEndTime.time);
 
-    sprintf(Buf,"echo \"%04d-%02d-%02d %02d:%02d:%02d:%03d - %s\" >> /Storage/EventLog/[%04d.%02d]EventLog",
+    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);
@@ -92,7 +95,7 @@ int StoreEventLogMsg(const char *fmt, ...)
     return rc;
 }
 
-int StoreAuthLogMsg(const char *fmt, ...)
+int StoreEvCommMsg(const char *fmt, ...)
 {
     char Buf[4096+256];
     char buffer[4096];
@@ -109,7 +112,7 @@ int StoreAuthLogMsg(const char *fmt, ...)
     SeqEndTime.time = time(NULL);
     tm=localtime(&SeqEndTime.time);
 
-    sprintf(Buf,"echo \'%04d-%02d-%02d %02d:%02d:%02d:%03d - %s\' >> /Storage/SystemLog/[%04d.%02d]AuthLog",
+    sprintf(Buf,"echo \'%04d-%02d-%02d %02d:%02d:%02d:%03d - %s\' >> /Storage/SystemLog/[%04d.%02d]EvCommLog",
         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);
@@ -118,7 +121,7 @@ int StoreAuthLogMsg(const char *fmt, ...)
     return rc;
 }
 
-int StoreEvCommMsg(const char *fmt, ...)
+int StoreDbMsg(const char *fmt, ...)
 {
     char Buf[4096+256];
     char buffer[4096];
@@ -135,7 +138,7 @@ int StoreEvCommMsg(const char *fmt, ...)
     SeqEndTime.time = time(NULL);
     tm=localtime(&SeqEndTime.time);
 
-    sprintf(Buf,"echo \'%04d-%02d-%02d %02d:%02d:%02d:%03d - %s\' >> /Storage/SystemLog/[%04d.%02d]EvCommLog",
+    sprintf(Buf,"echo \'%04d-%02d-%02d %02d:%02d:%02d:%03d - %s\' >> /Storage/SystemLog/[%04d.%02d]DbLog",
         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);
@@ -144,7 +147,7 @@ int StoreEvCommMsg(const char *fmt, ...)
     return rc;
 }
 
-int StoreDbMsg(const char *fmt, ...)
+int StoreOccupancyMsg(const char *fmt, ...)
 {
     char Buf[4096+256];
     char buffer[4096];
@@ -161,7 +164,7 @@ int StoreDbMsg(const char *fmt, ...)
     SeqEndTime.time = time(NULL);
     tm=localtime(&SeqEndTime.time);
 
-    sprintf(Buf,"echo \'%04d-%02d-%02d %02d:%02d:%02d:%03d - %s\' >> /Storage/SystemLog/[%04d.%02d]DbLog",
+    sprintf(Buf,"echo \'%04d-%02d-%02d %02d:%02d:%02d:%03d - %s\' >> /Storage/SystemLog/[%04d.%02d]OccupancyLog",
         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);
@@ -170,7 +173,7 @@ int StoreDbMsg(const char *fmt, ...)
     return rc;
 }
 
-int StoreOccupancyMsg(const char *fmt, ...)
+int StoreReadCmdLineMsg(const char *fmt, ...)
 {
     char Buf[4096+256];
     char buffer[4096];
@@ -187,7 +190,7 @@ int StoreOccupancyMsg(const char *fmt, ...)
     SeqEndTime.time = time(NULL);
     tm=localtime(&SeqEndTime.time);
 
-    sprintf(Buf,"echo \'%04d-%02d-%02d %02d:%02d:%02d:%03d - %s\' >> /Storage/SystemLog/[%04d.%02d]OccupancyLog",
+    sprintf(Buf,"echo \'%04d-%02d-%02d %02d:%02d:%02d:%03d - %s\' >> /Storage/SystemLog/[%04d.%02d]ReadCmdLineLog",
         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);
@@ -667,6 +670,63 @@ unsigned short ParsingRatingPower(char *modelname)
     return value;
 }
 
+unsigned int cal_crc32(unsigned char *data, unsigned int length)
+{
+    unsigned int crc = 0xFFFFFFFF;
+
+    for(size_t i = 0; i < length; i++)
+    {
+        char ch = data[i];
+
+        for(size_t j = 0; j < 8; j++)
+        {
+            unsigned int b = (ch ^ crc) & 1;
+
+            crc >>= 1;
+            if(b)
+            {
+                crc=crc^0xEDB88320;
+            }
+            ch>>=1;
+        }
+    }
+    return ~crc;
+}
+
+unsigned int getFileCrc32(char *filename)
+{
+    unsigned int result = 0;
+
+    int fd = open(filename, O_RDONLY);
+
+    if(fd < 0)
+    {
+        LOG_ERROR("Get File Crc32 Error, Can not open file %s", filename);
+    }
+    else
+    {
+        struct stat st;
+
+        stat(filename, &st);
+        unsigned char *data;
+
+        data = malloc(st.st_size);
+
+        if(read(fd,data,st.st_size) == st.st_size)
+        {
+            result = cal_crc32(data, st.st_size);
+            close(fd);
+        }
+        else
+        {
+            LOG_ERROR("Read file Error %d", st.st_size);
+        }
+
+        free(data);
+    }
+
+    return result;
+}
 
 //***************************************** No Use *****************************************
 float TariffParsing(char *StringItem, char *TariffCode)

+ 3 - 2
EVSE/Projects/DO360/Apps/Common.h

@@ -33,22 +33,22 @@
 #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 EvMsg_INFO(format, args...) StoreEvCommMsg("[%s:%4d][%s][EvMsg] "format, (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__), __LINE__, __FUNCTION__, ##args)
 #define Database_INFO(format, args...) StoreDbMsg("[%s:%4d][%s][DB] "format, (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__), __LINE__, __FUNCTION__, ##args)
 #define Occupancy_INFO(format, args...) StoreOccupancyMsg("[%s:%4d][%s][OF] "format, (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__), __LINE__, __FUNCTION__, ##args)
+#define ReadCmd_INFO(format, args...) StoreReadCmdLineMsg(" "format, ##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, ...);
 int StoreEvCommMsg(const char *fmt, ...);
 int StoreDbMsg(const char *fmt, ...);
 int StoreOccupancyMsg(const char *fmt, ...);
+int StoreReadCmdLineMsg(const char *fmt, ...);
 
 void GetClockTime(struct timespec *_now_time);
 unsigned long GetTimeoutValue(struct timespec _start_time);
@@ -78,6 +78,7 @@ float GetNowTimePricing(float *price);
 float TccDefaultPriceParsing(char *costString, float *price);
 
 unsigned short ParsingRatingPower(char *modelname);
+unsigned int getFileCrc32(char *filename);
 
 //***************************************** No Use *****************************************
 float TariffParsing(char *StringItem, char *TariffCode);

+ 162 - 17
EVSE/Projects/DO360/Apps/Config.h

@@ -55,6 +55,7 @@ typedef unsigned char               byte;
 #define MAX_MODULE_PER_GROUP        12
 #define INFY_SINGLE_PSU_POWER       30000           // unit: 1W
 #define SM_ChargerInfoKey           3000
+#define MAX_OUTPUT_VOLTAGE          9500
 
 #define SAFETY_TEST_ENABLE          0
 
@@ -149,16 +150,6 @@ enum _SYSTEM_STATUS
 	S_NONE,
 };
 
-enum _AC_SYSTEM_STATUS
-{
-	AC_SYS_NONE = 	0,
-	AC_SYS_A,
-	AC_SYS_B,
-	AC_SYS_C,
-	AC_SYS_D,
-	AC_SYS_E
-};
-
 #define STR_GUN_TYPE_CHADEMO        "CHAdeMO"
 #define STR_GUN_TYPE_CCS            "CCS"
 #define STR_GUN_TYPE_GBT            "GBT"
@@ -718,6 +709,62 @@ typedef struct
     int EvCanFd;
 }FdControl;
 
+typedef enum
+{
+    _TILT_SENSOR_NONE           = 0,
+    _TILT_SENSOR_WAIT           = 1,
+    _TILT_SENSOR_START          = 2,
+    _TILT_SENSOR_WAIT_RESPONSE  = 3,
+    _TILT_SENSOR_OUTCOME        = 4,
+    _TILT_SENSOR_STOP           = 5,
+    _TILT_SENSOR_WAIT_STOP      = 6,
+    _TILT_SENSOR_FINISH         = 7,
+}_TILT_SENSOR_TEST_STEP;
+
+typedef union
+{
+    unsigned int CtrlValue;
+    struct
+    {
+        unsigned int StandbyTimeDisable:1;          // 0: no effect,                1: disable standby time
+        unsigned int StandbyTimeDisableForTcc:1;    // 0: no effect,                1: disable standby time at specific time for tcc
+        unsigned int StandbyImmediately:1;          // 0: no effect,                1: standby immediately
+        unsigned int CustomizedStandbyTime:1;       // 0: no effect,                1: enable customized standby time
+        unsigned int TiltSensorEnable:1;            // 0: no effect,                1: enable tilt sensor
+        unsigned int res:27;
+    }bits;
+}CustomizedFlagInfo;
+
+typedef struct
+{
+    int TiltSensorStep;
+    int TiltSensorFail;
+    int StandbyTime;                                // unit: 1 minute
+    CustomizedFlagInfo Flag;
+}CustomizedFunctionInfo;
+
+#define DIAGNOSTICS_TYPE_NONE       0
+#define DIAGNOSTICS_TYPE_ALL        1
+
+typedef union
+{
+    unsigned int CtrlValue;
+    struct
+    {
+        unsigned int Request:1;                     // 0: no effect,                1: diagnostics request
+        unsigned int Confirm:1;                     // 0: no effect,                1: diagnostics confirm
+        unsigned int Completed:1;                   // 0: no effect,                1: diagnostics completed
+        unsigned int Stop:1;                        // 0: no effect,                1: diagnostics stop
+        unsigned int res:28;
+    }bits;
+}DiagnosticsFlagInfo;
+
+typedef struct
+{
+    int DiagnosticsType;
+    DiagnosticsFlagInfo DispenserDiagnostics[MAX_DISPENSER_QUANTITY];
+}DiagnosticsInfo;
+
 typedef struct
 {
     unsigned char   MaxDispenser;
@@ -747,6 +794,9 @@ typedef struct
     unsigned char   GunAvailable[MAX_GROUP_QUANTITY];
     unsigned char   PsuInitQuantity[MAX_GROUP_QUANTITY];
     char            ResevedIdTag[MAX_GROUP_QUANTITY][32];
+
+    CustomizedFunctionInfo  CustomizedInfo;
+    DiagnosticsInfo Diagnostics;
 }SysControl;
 // ************************************************************************************************* //
 typedef struct
@@ -788,17 +838,55 @@ typedef union
     unsigned int StatusVal;
     struct
     {
-        unsigned int Changed:1;                     // 0: no output,                1: psu is output
-        unsigned int res:31;
+        unsigned int Changed:1;
+        unsigned int Indicated:1;
+        unsigned int res:30;
     }bits;
 }PsuErrorStatusInfo;
 
 typedef struct
 {
     int ErrorCount;
-    PsuErrorStatusInfo ErrFlag;
+    PsuErrorStatusInfo PhPwrStateFlag;
     unsigned char PsuError[8];
-}PsuErrorCodeInfo;
+}PhPwrStateInfo;
+
+typedef union
+{
+    unsigned char StateVal[4];
+    struct
+    {
+        //StateVal[0]
+        unsigned char OutputShort:1;                // OFF, Red
+        unsigned char State_0_1_7:7;
+        //StateVal[1]
+        unsigned char PsuOff:1;                     // OFF
+        unsigned char PsuFault:1;                   // OFF, Red
+        unsigned char PsuProtect:1;                 // OFF, Yellow
+        unsigned char FanFault:1;                   // OFF, Red Blink
+        unsigned char OverTemperature:1;            // OFF, Yellow
+        unsigned char OutputOverVoltage:1;          // OFF, Red
+        unsigned char WalkInEnable:1;
+        unsigned char CanCommInterrupt:1;           // OFF, Yellow Blink
+        //StateVal[2]
+        unsigned char PowerLimit:1;                 //  ON
+        unsigned char PsuIdRepetition:1;            // OFF, Red
+        unsigned char LoadUnsharing:1;              //  ON, Red
+        unsigned char InputPhaseLost:1;             // OFF, Yellow
+        unsigned char InputUnbalance:1;             //
+        unsigned char InputUnderVoltage:1;          // OFF, Yellow
+        unsigned char InputOverVoltage:1;           // OFF, Yellow
+        unsigned char PfcOff:1;                     // OFF
+        //StateVal[3]
+        unsigned char State_3:8;
+    }bits;
+}InfyPsuStateFlagInfo;
+
+typedef struct
+{
+    PsuErrorStatusInfo InfyPwrStateFlag;
+    InfyPsuStateFlagInfo InfyPwrState;
+}InfyPwrStateInfo;
 
 typedef struct
 {
@@ -808,7 +896,8 @@ typedef struct
     GroupInfoData       GroupLocationInfo[MAX_GROUP_QUANTITY];
     PsuAddressInfoData  PsuAddressInfo[MAX_PSU_MODULE_QUANTITY];
     PsuStatusInfo       SinglePsuStatus[MAX_PSU_MODULE_QUANTITY];
-    PsuErrorCodeInfo    SinglePsuError[MAX_PSU_MODULE_QUANTITY];
+    PhPwrStateInfo      SinglePhPsuError[MAX_PSU_MODULE_QUANTITY];
+    InfyPwrStateInfo    SingleInfyPwrState[MAX_PSU_MODULE_QUANTITY];
 }PsuPositionInfoData;
 // ************************************************************************************************* //
 typedef enum
@@ -947,6 +1036,7 @@ typedef struct
     float                   DiffPower_Capability;               // unit: 1kW, different power between output power and Capability power
     float                   DiffPower_Available;                // unit: 1kW, different power between output power and Available power
     float                   DiffPower_PhysicalLimit;            // unit: 1kW, different power between output power and PhysicalLimit power
+    float                   DiffPower_ConfigLimit;              // unit: 1kW, different power between output power and config power
 }PsuGroupCollectionData;
 
 typedef struct
@@ -1388,7 +1478,7 @@ typedef union
         unsigned int OutputRelayDrivingFault:1;         // 0: no effect,    1: DrivingFault
         unsigned int ParallelRelayWelding:1;            // 0: no effect,    1: Welding
         unsigned int ParallelRelayDrivingFault:1;       // 0: no effect,    1: DrivingFault
-        unsigned int PsuGroupAllAlarmFault:1;           // 0: no effect,    1: psu group all alarm or fault
+        unsigned int PsuGroupNoResource:1;              // 0: no effect,    1: psu group all alarm or fault >> group no resource
         unsigned int res:27;
     }bits;
 }GunErrorFlag;
@@ -1420,6 +1510,11 @@ typedef struct
     int GunManualLimitPower[MAX_GUN_QUANTITY];          // unit: W
     int GunManualLimitVoltage[MAX_GUN_QUANTITY];        // unit: 0.1V
     int GunManualLimitCurrent[MAX_GUN_QUANTITY];        // unit: 0.1A
+
+    // final output limitation
+    int GunLimitPower[MAX_GUN_QUANTITY];                // unit: 0.1kW
+    int GunLimitVoltage[MAX_GUN_QUANTITY];              // unit: 0.1V
+    int GunLimitCurrent[MAX_GUN_QUANTITY];              // unit: 0.1A
 }OutputLimitation;
 
 typedef enum
@@ -1499,12 +1594,14 @@ typedef enum
 #define STR_NOTIFY_NONE             "Notify None"
 #define STR_GET_OCCUPANCY_FEE       "GetOccupancyFee"
 #define STR_CANCEL_OCCUPANCY_DEDUCT "CancelDeduction"
+#define STR_CANCEL_OCCUPANCY_FEE    "CancelOccupancyFee"
 
 typedef enum
 {
     _Notify_None                    = 0x00,             // act: None
     _Notify_GetOccupancyFee         = 0x01,             // act: Get OccupancyFee
     _Notify_CancelLocalDeduction    = 0x02,             // act: Cancel Local Deduction
+    _Notify_CancelOccupancyFee      = 0x03,             // act: Cancel Occupancy Fee
 }NotifyOccupancyFeeAct;
 
 typedef struct
@@ -1541,8 +1638,9 @@ typedef union
     {
         unsigned int DeductReq:1;                       // 0: no request,               1: deduct request
         unsigned int KeepCounting:1;                    // 0: no effect,                1: occupancy keep counting
+        unsigned int ForceCancel:1;                     // 0: no effect,                1: force cancel occupancy fee because of charging status
         unsigned int SelfReq:1;                         // 0: no request,               1: self request
-        unsigned int res:29;
+        unsigned int res:28;
     }bits;
 }OccupancyReqFlag;
 
@@ -1565,6 +1663,52 @@ typedef struct
     ChargingBillInfoData GunBill[MAX_GUN_QUANTITY];
     OccupancyInfoData OccupancyInfo[MAX_GUN_QUANTITY];
 }AllBillInfoData;
+
+#define OCMF_SATAUS_INSERTED                            0
+#define OCMF_SATAUS_UPDATED_OK                          1
+
+typedef union
+{
+    unsigned int CtrlValue;
+    struct
+    {
+        unsigned int OcmfReceived:1;                    // 0: no request,               1: ocmf info received
+        unsigned int res:31;
+    }bits;
+}GunOcmfFlag;
+
+typedef struct
+{
+    // ocmf file path: /mnt
+    // ocmf file name: Gun_X_TxId_OCMF
+    // X: Gun Id
+    // TxId: Transaction Id
+    char OcmfTxId[36];
+    char PublicKey[200];
+    GunOcmfFlag OcmfFlag;
+}OCMFInfoData;
+
+typedef union
+{
+    unsigned int CtrlValue;
+    struct
+    {
+        unsigned int OcmfPending:1;                     // 0: no request,               1: exist pending ocmf
+        unsigned int OcmfNeedUpload:1;                  // 0: no request,               1: ocmf need upload
+        unsigned int OcmfUploading:1;                   // 0: no request,               1: ocmf is uploading
+        unsigned int res:29;
+    }bits;
+}SysOcmfFlag;
+
+typedef struct
+{
+    int SysOcmfIndex;
+    char SysOcmfTxId[36];
+    char SysOcmfPublicKey[200];
+    char SysOcmfInfo[2048];
+    SysOcmfFlag SysOcmfFlag;
+    OCMFInfoData GunOcmf[MAX_GUN_QUANTITY];
+}SysOCMFInfoData;
 // ************************************************************************************************* //
 
 typedef struct
@@ -1595,6 +1739,7 @@ typedef struct
     GunError GunError[MAX_GUN_QUANTITY];
     OutputLimitation OutputLimit;
     AllBillInfoData AllBill;
+    SysOCMFInfoData OcmfInfo;
 }ChargerInfoData;
 
 #endif /* CONFIG_H_ */

+ 7 - 7
EVSE/Projects/DO360/Apps/FactoryConfig.c

@@ -252,14 +252,14 @@ int main(int argc,char *argv[])
 	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
-	{
+	//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;
 

+ 3 - 3
EVSE/Projects/DO360/Apps/InfyGroup_PsuCommObj.c

@@ -305,9 +305,9 @@ void ReceiveDataFromCanBus()
                     case PSU_RCmd_ModuleInputVoltage:
                     {
                         // 回傳三向輸入電壓
-                        short abVol = ((frame.data[0] << 8) + frame.data[1]) / 10;
-                        short bcVol = ((frame.data[2] << 8) + frame.data[3]) / 10;
-                        short caVol = ((frame.data[4] << 8) + frame.data[5]) / 10;
+                        short abVol = ((frame.data[0] << 8) + frame.data[1]);
+                        short bcVol = ((frame.data[2] << 8) + frame.data[3]);
+                        short caVol = ((frame.data[4] << 8) + frame.data[5]);
 
                         return_input_vol(address, abVol, bcVol, caVol);
                     }

+ 9 - 1
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 AuthorizeTask LedIndication EvCommTask EventLoggingTask InternalCommTask LcmControlTask PrimaryCommTask InfyGroup_PsuCommObj PhGroup_PsuCommObj PsuCommTask PhPsuCommTask ReadCmdlineTask FactoryConfigApp OtherTools
+apps: Common MainTask CabinetParallel SelfTestTask AuthorizeTask LedIndication EvCommTask EventLoggingTask InternalCommTask LcmControlTask PrimaryCommTask InfyGroup_PsuCommObj PhGroup_PsuCommObj PsuCommTask PhPsuCommTask ReadCmdlineTask DispenserDiagnostics FactoryConfigApp OtherTools
 
 Common:
 	rm -f Common.o
@@ -113,6 +113,12 @@ ReadCmdlineTask:
 	$(CC) -o ReadCmdline ReadCmdline.o Common.o ../../../Modularization/libModule_RatedCurrent.a -lrt -lm
 	cp -f ReadCmdline ../Images/root
 
+DispenserDiagnostics:
+	rm -f Module_Diagnostics; 
+	$(CC) -D $(Project) -includeConfig.h -O0 -g3 -Wall -c -fmessage-length=0 -o Module_Diagnostics.o Module_Diagnostics.c
+	$(CC) -o Module_Diagnostics Module_Diagnostics.o Common.o -lrt -lm
+	cp -f Module_Diagnostics ../Images/root
+
 UnsafetyOutputTool:
 	rm -f UnsafetyOutputTask; 
 	$(CC) -D $(Project) -include../../../Modularization/Infypwr_PsuCommObj.h -O0 -g3 -Wall -c -fmessage-length=0 -o OutputTask.o OutputTask.c
@@ -157,6 +163,8 @@ CleanExecute:
 	rm -f Module_LcmControl
 	rm -f Module_PrimaryComm
 	rm -f Module_PsuComm
+	rm -f Module_PsuComm_PH
 	rm -f ReadCmdline
+	rm -f Module_Diagnostics
 	rm -f FactoryConfig
 	rm -f UnsafetyOutputTask

+ 444 - 0
EVSE/Projects/DO360/Apps/Module_Diagnostics.c

@@ -0,0 +1,444 @@
+/*
+ * Module_Diagnostics.c
+ *
+ *  Created on: 2022年12月12日
+ *      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/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    <math.h>
+#include    <stdbool.h>
+#include    "../../define.h"
+#include    "Config.h"
+#include    "Common.h"
+#include    "Module_EvComm.h"
+
+struct SysConfigAndInfo         *ShmSysConfigAndInfo;
+struct StatusCodeData           *ShmStatusCodeData;
+struct PrimaryMcuData           *ShmPrimaryMcuData;
+struct PsuData                  *ShmPsuData;
+struct RelayModuleData          *ShmRelayModuleData[2];
+struct FanModuleData            *ShmFanModuleData;
+struct LedModuleData            *ShmLedModuleData;
+ChargerInfoData                 *ShmChargerInfo;
+struct OCPP16Data               *ShmOCPP16Data;
+struct OCPP20Data               *ShmOCPP20Data;
+struct OCPP16Data               *ShmOCPP16DataPH;
+
+int InitSysConfigAndInfoShareMemory(void)
+{
+    int result = PASS;
+    int MeterSMId;
+
+    //initial ShmSysConfigAndInfo
+    if((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo),  0777)) < 0)
+    {
+        result = FAIL;
+    }
+    else if((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+    {
+        result = FAIL;
+    }
+
+    return result;
+}
+
+int InitStatusCodeShareMemory(void)
+{
+    int result = PASS;
+    int MeterSMId;
+
+    //initial ShmStatusCodeData
+    if((MeterSMId = shmget(ShmStatusCodeKey, sizeof(struct StatusCodeData),  0777)) < 0)
+    {
+        result = FAIL;
+    }
+    else if ((ShmStatusCodeData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+    {
+        result = FAIL;
+    }
+
+    return result;
+}
+
+int InitPrimaryMcuShareMemory(void)
+{
+    int result = PASS;
+    int MeterSMId;
+
+    //initial ShmPrimaryMcuData
+    if((MeterSMId = shmget(ShmPrimaryMcuKey, sizeof(struct PrimaryMcuData), 0777)) < 0)
+    {
+        result = FAIL;
+    }
+    else if((ShmPrimaryMcuData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+    {
+        result = FAIL;
+    }
+
+    return result;
+}
+
+int InitPsuShareMemory(void)
+{
+    int result = PASS;
+    int MeterSMId;
+
+    //initial ShmPsuData
+    if((MeterSMId = shmget(ShmPsuKey, sizeof(struct PsuData), 0777)) < 0)
+    {
+        result = FAIL;
+    }
+    else if((ShmPsuData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+    {
+        result = FAIL;
+    }
+
+    return result;
+}
+
+int InitRelayModuleShareMemory(void)
+{
+    int result = PASS;
+    int MeterSMId;
+
+    //initial ShmRelayModuleData
+    if((MeterSMId = shmget(ShmRelayBdKey, sizeof(struct RelayModuleData),  0777)) < 0)
+    {
+        result = FAIL;
+    }
+    else if((ShmRelayModuleData[0] = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+    {
+        result = FAIL;
+    }
+
+    return result;
+}
+
+int InitRelay2ModuleShareMemory(void)
+{
+    int result = PASS;
+    int MeterSMId;
+
+    //initial ShmRelayModuleData
+    if((MeterSMId = shmget(ShmRelay2BdKey, sizeof(struct RelayModuleData),  0777)) < 0)
+    {
+        result = FAIL;
+    }
+    else if((ShmRelayModuleData[1] = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+    {
+        result = FAIL;
+    }
+
+    return result;
+}
+
+int InitFanModuleShareMemory(void)
+{
+    int result = PASS;
+    int MeterSMId;
+
+    //initial ShmFanModuleData
+    if((MeterSMId = shmget(ShmFanBdKey, sizeof(struct FanModuleData),  0777)) < 0)
+    {
+        result = FAIL;
+    }
+    else if((ShmFanModuleData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+    {
+        result = FAIL;
+    }
+
+    return result;
+}
+
+int InitLedModuleShareMemory(void)
+{
+    int result = PASS;
+    int MeterSMId;
+
+    //initial ShmLedModuleData
+    if((MeterSMId = shmget(ShmLedBdKey, sizeof(struct LedModuleData),  0777)) < 0)
+    {
+        result = FAIL;
+    }
+    else if((ShmLedModuleData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+    {
+        result = FAIL;
+    }
+
+    return result;
+}
+
+int InitChargerInfoShareMemory(void)
+{
+    int result = PASS;
+    int MeterSMId;
+
+    //initial ShmChargerInfo
+    if((MeterSMId = shmget(SM_ChargerInfoKey, sizeof(ChargerInfoData),  0777)) < 0)
+    {
+        result = FAIL;
+    }
+    else if((ShmChargerInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+    {
+        result = FAIL;
+    }
+
+    return result;
+}
+
+int InitOCPP16ShareMemory(void)
+{
+    int result = PASS;
+    int MeterSMId;
+
+    //initial ShmOCPP16Data
+    if((MeterSMId = shmget(ShmOcppModuleKey, sizeof(struct OCPP16Data), 0777)) < 0)
+    {
+        result = FAIL;
+    }
+    else if((ShmOCPP16Data = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+    {
+        result = FAIL;
+    }
+
+    return result;
+}
+
+int InitOCPP16PHShareMemory(void)
+{
+    int result = PASS;
+    int MeterSMId;
+
+    //initial ShmOCPP16Data
+    if((MeterSMId = shmget(ShmOcppPHModuleKey, sizeof(struct OCPP16Data), 0777)) < 0)
+    {
+        result = FAIL;
+    }
+    else if((ShmOCPP16DataPH = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+    {
+        result = FAIL;
+    }
+
+    return result;
+}
+
+int InitOCPP20ShareMemory(void)
+{
+    int result = PASS;
+    int MeterSMId;
+
+    //initial ShmOCPP20Data
+    if((MeterSMId = shmget(ShmOcpp20ModuleKey, sizeof(struct OCPP20Data), 0777)) < 0)
+    {
+        result = FAIL;
+    }
+    else if((ShmOCPP20Data = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+    {
+        result = FAIL;
+    }
+
+    return result;
+}
+
+int InitShareMemory(void)
+{
+    int result = PASS;
+
+    //initial ShmSysConfigAndInfo
+    if(InitSysConfigAndInfoShareMemory() == FAIL)
+    {
+        result = FAIL;
+    }
+
+    //initial ShmStatusCodeData
+    if(InitStatusCodeShareMemory() == FAIL)
+    {
+        result = FAIL;
+    }
+
+    //initial ShmPrimaryMcuData
+    if(InitPrimaryMcuShareMemory() == FAIL)
+    {
+        result = FAIL;
+    }
+
+    //initial ShmPsuData
+    if(InitPsuShareMemory() == FAIL)
+    {
+        result = FAIL;
+    }
+
+    //initial ShmRelayModuleData
+    if(InitRelayModuleShareMemory() == FAIL)
+    {
+        result = FAIL;
+    }
+
+    if(InitRelay2ModuleShareMemory() == FAIL)
+    {
+        result = FAIL;
+    }
+
+    //initial ShmFanModuleData
+    if(InitFanModuleShareMemory() == FAIL)
+    {
+        result = FAIL;
+    }
+
+    //initial ShmLedModuleData
+    if(InitLedModuleShareMemory() == FAIL)
+    {
+        result = FAIL;
+    }
+
+    //initial ShmChargerInfo
+    if(InitChargerInfoShareMemory() == FAIL)
+    {
+        result = FAIL;
+    }
+
+    //initial ShmOCPP16Data
+    if(InitOCPP16ShareMemory() == FAIL)
+    {
+        result = FAIL;
+    }
+
+    if(InitOCPP16PHShareMemory() == FAIL)
+    {
+        result = FAIL;
+    }
+
+    //initial ShmOCPP20Data
+    if(InitOCPP20ShareMemory() == FAIL)
+    {
+        result = FAIL;
+    }
+
+    return result;
+}
+
+// ./Module_Diagnostics X AAA.AAA.AAA.AAA
+// Dispenser ID: X, start from 1 ~ 4
+// Dispenser IP: AAA.AAA.AAA.AAA
+int main(int argc, char *argv[])
+{
+    int success = FAIL;
+    bool _find = false;
+    int _dispenserId = 0;
+    char _address[128];
+    char dispenserStr[64];
+
+    memset(_address, 0x00, sizeof(_address));
+    memset(dispenserStr, 0x00, sizeof(dispenserStr));
+
+    if(InitShareMemory() == FAIL)
+    {
+        LOG_ERROR("InitShareMemory NG");
+        return FAIL;
+    }
+
+    if(argc == 3)
+    {
+        _dispenserId = atoi(argv[1]);
+        strcpy(_address, argv[2]);
+
+        if(_dispenserId > 0)
+        {
+            for(int i = 0; i < GENERAL_GUN_QUANTITY; i++)
+            {
+                if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.ConnectionInfo[i].Status == _CNS_DispenserMatched)
+                {
+                    if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.ConnectionInfo[i].IpAddress == inet_addr(_address) &&
+                        ShmSysConfigAndInfo->SysInfo.DispenserInfo.ConnectionInfo[i].DispenserIndex == (_dispenserId - 1))
+                    {
+                        _find = true;
+                    }
+                }
+            }
+        }
+
+        if(_find)
+        {
+            sprintf(dispenserStr, "Dispenser %d ", _dispenserId);
+            ShmChargerInfo->Control.Diagnostics.DispenserDiagnostics[_dispenserId - 1].bits.Confirm = ShmChargerInfo->Control.Diagnostics.DispenserDiagnostics[_dispenserId - 1].bits.Request;
+        }
+        LOG_INFO("Set Diagnostics Request to %s[%s]", dispenserStr, _address);
+
+        char cmdBuf[512] = {0};
+        sprintf(cmdBuf, "curl -k -X POST --data \"logCnt=2\" https://%s/log_download_action.php", _address);
+        if(system(cmdBuf) == 0)
+        {
+            success = PASS;
+        }
+
+        LOG_INFO("%s[%s] Latest log file is %s", dispenserStr, _address, success == PASS ? "OK" : "NG");
+
+        if(success == PASS)
+        {
+            struct timeb  SeqEndTime;
+            struct tm *tm;
+            ftime(&SeqEndTime);
+            SeqEndTime.time = time(NULL);
+            tm=localtime(&SeqEndTime.time);
+            char _fileName[64];
+
+            if(_find)
+            {
+                sprintf(_fileName, "%d", _dispenserId);
+            }
+            else
+            {
+                sprintf(_fileName, "[%02d.%02d]", tm->tm_mon + 1, tm->tm_mday);
+            }
+
+            sprintf((char*)cmdBuf,"ftpget -u root -p y42j/4cj84 %s \"/Storage/SystemLog/[%04d.%02d]Dispenser%sLog.zip\" /mnt/log.zip",
+                _address, tm->tm_year + 1900, tm->tm_mon + 1, _fileName);
+
+            if(system(cmdBuf) != 0)
+            {
+                success = FAIL;
+            }
+
+            LOG_INFO("Diagnostics %s[%s] %s", dispenserStr, _address, success == PASS ? "OK" : "NG");
+            if(success)
+            {
+                ShmChargerInfo->Control.Diagnostics.DispenserDiagnostics[_dispenserId - 1].bits.Completed = ShmChargerInfo->Control.Diagnostics.DispenserDiagnostics[_dispenserId - 1].bits.Confirm;
+            }
+        }
+    }
+    else
+    {
+        LOG_INFO("Diagnostics input parameter error!");
+    }
+
+    return success;
+}
+

+ 119 - 1
EVSE/Projects/DO360/Apps/Module_EvComm.c

@@ -1292,16 +1292,36 @@ void UserIDResponse(int socket, struct PACKET_STRUCTURE *packet, unsigned char r
 void ChargingPermissionResponse(int socket, struct PACKET_STRUCTURE *packet, unsigned char result)
 {
 	struct PACKET_STRUCTURE sendBuffer;
+	bool _NormalStop = true;
 
 	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.Header.len = 9;
 	sendBuffer.Payload.reg = _Reg_Charging_Permission;
 	sendBuffer.Payload.data[0] = result == _DAS_Wait ? _R_NG : _R_OK;
 	sendBuffer.Payload.data[1] = result == _DAS_Allowed ? _PS_Permitted : _PS_NotPermitted;
 
+	if(result == _DAS_NotAllowed)
+	{
+	    if(strcmp((char *)chargingInfo[packet->Header.id - 1]->ConnectorAlarmCode, "") != EQUAL)
+	    {
+	        memcpy((char *)&sendBuffer.Payload.data[2], (char *)chargingInfo[packet->Header.id - 1]->ConnectorAlarmCode, 6);
+	        _NormalStop = false;
+	    }
+	    else if(strcmp((char *)chargingInfo[packet->Header.id - 1]->EvConnAlarmCode, "") != EQUAL)
+	    {
+	        memcpy((char *)&sendBuffer.Payload.data[2], (char *)chargingInfo[packet->Header.id - 1]->EvConnAlarmCode, 6);
+	        _NormalStop = false;
+	    }
+	}
+
+	if(_NormalStop)
+	{
+	    memcpy((char *)&sendBuffer.Payload.data[2], "000000", 6);
+	}
+
 	SendPacket(socket, &sendBuffer);
 }
 
@@ -2725,6 +2745,21 @@ void ParkingBillResponse(int socket, struct PACKET_STRUCTURE *packet, unsigned c
     SendPacket(socket, &sendBuffer);
 }
 
+void WriteOcmfInfoResponse(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 = 2;
+    sendBuffer.Payload.reg = _Reg_OCMF_Info;
+    sendBuffer.Payload.data[0] = result;
+
+    SendPacket(socket, &sendBuffer);
+}
+
 BOOL FindConnectorID(unsigned char dispenserIndex, unsigned char id)
 {
 	BOOL find = false;
@@ -2804,6 +2839,8 @@ void ConnectorPhysicalLimitBindingHandler(unsigned char connectorIndex, unsigned
             //ShmSysConfigAndInfo->SysInfo.ConnectorInfo[connectorIndex].RemoteMaxPhysicalVoltage = CCS_MAX_PHYSICAL_VOLTAGE;
             //ShmSysConfigAndInfo->SysInfo.ConnectorInfo[connectorIndex].RemoteMaxPhysicalCurrent = CCS_LIQUID_V_F_MAX_CURRENT;
             // Derating Mode
+            ShmSysConfigAndInfo->SysInfo.ConnectorInfo[connectorIndex].RemoteMaxPhysicalVoltage = CCS_MAX_PHYSICAL_VOLTAGE;
+            ShmSysConfigAndInfo->SysInfo.ConnectorInfo[connectorIndex].RemoteMaxPhysicalCurrent = CCS_LIQUID_V_F_MAX_CURRENT;
             ShmSysConfigAndInfo->SysInfo.ConnectorInfo[connectorIndex].GeneralChargingData.deratingByConnOtp.isNeedDerating = YES;
             ShmSysConfigAndInfo->SysInfo.ConnectorInfo[connectorIndex].GeneralChargingData.deratingByConnOtp.deratingIndex = 0;
             ShmSysConfigAndInfo->SysInfo.ConnectorInfo[connectorIndex].GeneralChargingData.deratingByConnOtp.deratingTargetCurrent[0] = CCS_LIQUID_V_F_MAX_CURRENT;
@@ -3347,6 +3384,11 @@ BOOL ConnectorStateHandler(struct PACKET_STRUCTURE *packet, unsigned char dispen
                                 chargingInfo[packet->Header.id - 1]->ReservationId = -1;
                                 LOG_INFO("*********** Connector %d Clean ReservationId ***********\n", packet->Header.id);
                             }
+                            else if(chargingInfo[packet->Header.id - 1]->SystemStatus == S_AUTHORIZING)
+                            {
+                                LOG_INFO("*********** Connector %d Normal Stop ***********\n", packet->Header.id);
+                                ShmSysConfigAndInfo->SysInfo.ConnectorInfo[packet->Header.id - 1].Parameter.bits.NormalStopRequest = true;
+                            }
                         }
                         else if(chargingInfo[packet->Header.id - 1]->SystemStatus == S_AUTHORIZING)
                         {
@@ -4383,6 +4425,72 @@ unsigned char ReadParkingBillHandler(struct PACKET_STRUCTURE *packet, int dispen
     return false;
 }
 
+unsigned char WriteOcmfInfoHandler(struct PACKET_STRUCTURE *packet, int dispenserIndex)
+{
+    BOOL find = FindConnectorID(dispenserIndex, packet->Header.id);
+    int gun = 0;
+    unsigned int ocfmCrc = 0;
+    char txId[37], publicKey[201];
+    char fileName[256];
+    unsigned int _calCrc32 = 0;
+
+    if(find)
+    {
+        gun = packet->Header.id - 1;
+
+        if(ShmChargerInfo->OcmfInfo.GunOcmf[gun].OcmfFlag.bits.OcmfReceived)
+        {
+            LOG_INFO("Gun %d last OCMF info is still handling", packet->Header.id);
+            return false;
+        }
+
+        memset(txId, 0x00, sizeof(txId));
+        memcpy(txId, &packet->Payload.data[0], sizeof(txId) - 1);
+
+        ocfmCrc = (packet->Payload.data[36] << 24) +
+                  (packet->Payload.data[37] << 16) +
+                  (packet->Payload.data[38] << 8) +
+                  (packet->Payload.data[39]);
+
+        memset(publicKey, 0x00, sizeof(publicKey));
+        memcpy(publicKey, &packet->Payload.data[40], sizeof(publicKey) - 1);
+
+        sprintf(fileName, "/mnt/Gun_%d_%s_OCMF", packet->Header.id, txId);
+
+        if(access(fileName, F_OK) == 0)
+        {
+            _calCrc32 = getFileCrc32(fileName);
+
+            if(_calCrc32 == ocfmCrc)
+            {
+                memset(ShmChargerInfo->OcmfInfo.GunOcmf[gun].OcmfTxId, 0x00, sizeof(ShmChargerInfo->OcmfInfo.GunOcmf[gun].OcmfTxId));
+                memset(ShmChargerInfo->OcmfInfo.GunOcmf[gun].PublicKey, 0x00, sizeof(ShmChargerInfo->OcmfInfo.GunOcmf[gun].PublicKey));
+                memcpy(&ShmChargerInfo->OcmfInfo.GunOcmf[gun].OcmfTxId, txId, sizeof(ShmChargerInfo->OcmfInfo.GunOcmf[gun].OcmfTxId));
+                memcpy(&ShmChargerInfo->OcmfInfo.GunOcmf[gun].PublicKey, publicKey, sizeof(ShmChargerInfo->OcmfInfo.GunOcmf[gun].PublicKey));
+                LOG_INFO("Gun %d OCMF info [%s] received, crc is 0x%X", packet->Header.id, fileName, _calCrc32);
+                ShmChargerInfo->OcmfInfo.GunOcmf[gun].OcmfFlag.bits.OcmfReceived = true;
+                return true;
+            }
+            else
+            {
+                LOG_INFO("Gun %d OCMF info received, but crc not match, crc: 0x%8X != 0x%8X", packet->Header.id, ocfmCrc, _calCrc32);
+                char cmdBuf[256] = {0};
+                sprintf(cmdBuf, "rm -f %s", fileName);
+                system(cmdBuf);
+
+                return false;
+            }
+        }
+        else
+        {
+            LOG_INFO("Gun %d OCMF info received, but file[%s] not exist.", packet->Header.id, fileName);
+            return false;
+        }
+    }
+
+    return false;
+}
+
 void DisableConnector(unsigned char dispenserIndex)
 {
 	for(int i = 0; i < ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].ConnectorQuantity; i++)
@@ -4909,6 +5017,16 @@ void DispenserSocketProcess(int socketFd, struct sockaddr_in clientInfo, unsigne
                         }
                         ParkingBillResponse(socketFd, &receiveBuffer, ackResult);
                     }
+
+                    // Reg: 0x29 _Reg_OCMF_Info
+                    if(receiveBuffer.Header.op == _Header_Write && receiveBuffer.Payload.reg == _Reg_OCMF_Info)
+                    {
+                        if(WriteOcmfInfoHandler(&receiveBuffer, dispenserIndex))
+                        {
+                            ackResult = _R_OK;
+                        }
+                        WriteOcmfInfoResponse(socketFd, &receiveBuffer, ackResult);
+                    }
 				}
 
 				// clean timeout

+ 2 - 1
EVSE/Projects/DO360/Apps/Module_EvComm.h

@@ -108,7 +108,8 @@ enum PAYLOAD_REGISTER
     _Reg_ChargingBill               = 0x26,
     _Reg_ParkingStatus              = 0x27,
     _Reg_ParkingBill                = 0x28,
-    _Reg_None                       = 0x29,
+    _Reg_OCMF_Info                  = 0x29,
+    _Reg_None                       = 0x2A,
 };
 
 enum Response_Result

+ 36 - 24
EVSE/Projects/DO360/Apps/Module_EventLogging.c

@@ -30,6 +30,8 @@
 #include	"../../define.h"
 #include    "Common.h"
 
+#define LOG_EVENT(format, args...) StoreEventLogMsg("[%s:%4d][%s][Info] "format, (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__), __LINE__, __FUNCTION__, ##args)
+
 struct network_previous_status
 {
     int     rssiWifi;
@@ -53,36 +55,44 @@ struct network_previous_status  netPreviousStatus;
 sqlite3 *localDb;
 sqlite3 *networkDb;
 
-int DiffTimeb(struct timeb ST, struct timeb ET)
+int StoreEventLogMsg(const char *fmt, ...)
 {
-	//return milli-second
-	unsigned int StartTime,StopTime;
-
-	StartTime=(unsigned int)ST.time;
-	StopTime=(unsigned int)ET.time;
-	return (StopTime-StartTime)*1000+ET.millitm-ST.millitm;
-}
-
-//=================================
-// Common routine
-//=================================
-char* getTimeString(void)
-{
-	char *result=malloc(21);
-	time_t timep;
-	struct tm *p;
-	time(&timep);
-	p=gmtime(&timep);
-
-	sprintf(result, "[%04d-%02d-%02d %02d:%02d:%02d]", (1900+p->tm_year), (1+p->tm_mon), p->tm_mday, p->tm_hour, p->tm_hour, p->tm_sec);
-
-	return result;
+    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]%s_%s_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,
+        ShmSysConfigAndInfo->SysConfig.ModelName,
+        ShmSysConfigAndInfo->SysConfig.SerialNumber);
+    system(Buf);
+
+    return rc;
 }
 
 //==========================================
 // Init all share memory
 //==========================================
-int InitShareMemory()
+int InitShareMemory(void)
 {
 	int result = PASS;
 	int MeterSMId;
@@ -514,6 +524,8 @@ int main(void)
 	StatusCodeDisableMask.AlarmCode.AlarmEvents.bits.PsuPfcEepromFault = YES;
 	StatusCodeDisableMask.AlarmCode.AlarmEvents.bits.PsuCriticalPointOTP = YES;
 	StatusCodeDisableMask.AlarmCode.AlarmEvents.bits.PsuDcdcOverVoltage = YES;
+	StatusCodeDisableMask.AlarmCode.AlarmEvents.bits.PsuFault = YES;
+	StatusCodeDisableMask.AlarmCode.AlarmEvents.bits.PsuProtectionAlarm = YES;
 
 	// InfoEvents disable mask
 	StatusCodeDisableMask.InfoCode.InfoEvents.bits.InternetDisconnectViaEthernet = YES;

+ 113 - 2
EVSE/Projects/DO360/Apps/Module_PrimaryComm.c

@@ -33,8 +33,11 @@
 #include    "Config.h"
 #include    "Common.h"
 
-#define COMM_FAIL_COUNT         10
-#define STATE_CHANGE_COUNT      3
+#define COMM_FAIL_COUNT             10
+#define STATE_CHANGE_COUNT          3
+#define TILT_SENSOR_WAIT_TIME       1               // unit: 1s
+#define TILT_SENSOR_WAIT_RESPONSE   1               // unit: 1s
+#define TILT_SENSOR_WAIT_STOP       1               // unit: 1s
 
 typedef unsigned char 		byte;
 
@@ -487,6 +490,109 @@ int InitComPort()
 	return fd;
 }
 
+int preTiltSensorStep = _TILT_SENSOR_NONE;
+struct timespec _tiltSensor_time;
+
+void CheckTiltSensor(void)
+{
+    if(ShmPrimaryMcuData->InputDet.bits.AcContactorDetec)
+    {
+        int step = ShmChargerInfo->Control.CustomizedInfo.TiltSensorStep;
+
+        switch(step)
+        {
+            case _TILT_SENSOR_NONE:
+                if(preTiltSensorStep != step)
+                {
+                    preTiltSensorStep = step;
+                }
+                ShmChargerInfo->Control.CustomizedInfo.TiltSensorStep = _TILT_SENSOR_WAIT;
+                break;
+            case _TILT_SENSOR_WAIT:
+                if(preTiltSensorStep != step)
+                {
+                    preTiltSensorStep = step;
+                    GetClockTime(&_tiltSensor_time);
+                }
+                if((GetTimeoutValue(_tiltSensor_time) / uSEC_VAL) > TILT_SENSOR_WAIT_TIME)
+                {
+                    ShmChargerInfo->Control.CustomizedInfo.TiltSensorStep = _TILT_SENSOR_START;
+                }
+                break;
+            case _TILT_SENSOR_START:
+                if(preTiltSensorStep != step)
+                {
+                    preTiltSensorStep = step;
+                    LOG_INFO("Tilt sensor self test start!");
+                }
+                ShmPrimaryMcuData->OutputDrv.bits.SystemLed3Drv = true;
+                ShmPrimaryMcuData->OutputDrv.bits.SystemLed4Drv = true;
+                ShmChargerInfo->Control.CustomizedInfo.TiltSensorStep = _TILT_SENSOR_WAIT_RESPONSE;
+                break;
+            case _TILT_SENSOR_WAIT_RESPONSE:
+                if(preTiltSensorStep != step)
+                {
+                    preTiltSensorStep = step;
+                    GetClockTime(&_tiltSensor_time);
+                }
+                if((GetTimeoutValue(_tiltSensor_time) / uSEC_VAL) > TILT_SENSOR_WAIT_RESPONSE)
+                {
+                    ShmChargerInfo->Control.CustomizedInfo.TiltSensorStep = _TILT_SENSOR_OUTCOME;
+                }
+                break;
+            case _TILT_SENSOR_OUTCOME:
+                if(preTiltSensorStep != step)
+                {
+                    preTiltSensorStep = step;
+                    //LOG_INFO("Tilt sensor self test check");
+                }
+                LOG_INFO("Tilt sensor self test result [%s]", ShmPrimaryMcuData->InputDet.bits.DoorOpen ? "OK" : "NG");
+                ShmChargerInfo->Control.CustomizedInfo.TiltSensorFail = ShmPrimaryMcuData->InputDet.bits.DoorOpen ? NO : YES;
+                ShmChargerInfo->Control.CustomizedInfo.TiltSensorStep = _TILT_SENSOR_STOP;
+                break;
+            case _TILT_SENSOR_STOP:
+                if(preTiltSensorStep != step)
+                {
+                    preTiltSensorStep = step;
+                    //LOG_INFO("Tilt sensor self test stop!");
+                }
+                ShmPrimaryMcuData->OutputDrv.bits.SystemLed3Drv = false;
+                ShmPrimaryMcuData->OutputDrv.bits.SystemLed4Drv = false;
+                ShmChargerInfo->Control.CustomizedInfo.TiltSensorStep = _TILT_SENSOR_WAIT_STOP;
+                break;
+            case _TILT_SENSOR_WAIT_STOP:
+                if(preTiltSensorStep != step)
+                {
+                    preTiltSensorStep = step;
+                    GetClockTime(&_tiltSensor_time);
+                }
+                if((GetTimeoutValue(_tiltSensor_time) / uSEC_VAL) > TILT_SENSOR_WAIT_STOP)
+                {
+                    ShmChargerInfo->Control.CustomizedInfo.TiltSensorStep = _TILT_SENSOR_FINISH;
+                }
+                break;
+            case _TILT_SENSOR_FINISH:
+                if(preTiltSensorStep != step)
+                {
+                    preTiltSensorStep = step;
+                    LOG_INFO("Tilt sensor self test done!");
+                }
+                break;
+        }
+    }
+    else
+    {
+        if(ShmChargerInfo->Control.CustomizedInfo.TiltSensorStep != _TILT_SENSOR_NONE &&
+            ShmChargerInfo->Control.CustomizedInfo.TiltSensorStep != _TILT_SENSOR_FINISH)
+        {
+            ShmPrimaryMcuData->OutputDrv.bits.SystemLed3Drv = false;
+            ShmPrimaryMcuData->OutputDrv.bits.SystemLed4Drv = false;
+            LOG_INFO("Tilt sensor self test reset");
+        }
+        ShmChargerInfo->Control.CustomizedInfo.TiltSensorStep = _TILT_SENSOR_NONE;
+    }
+}
+
 int main(void)
 {
 	if(InitShareMemory() == FAIL)
@@ -556,6 +662,11 @@ int main(void)
                 GetInputGpioStatus();
                 //LOG_INFO("Input Status: %02X %02X", ShmPrimaryMcuData->InputDet.InputDetValue[1], ShmPrimaryMcuData->InputDet.InputDetValue[0]);
 
+                if(ShmChargerInfo->Control.CustomizedInfo.Flag.bits.TiltSensorEnable)
+                {
+                    CheckTiltSensor();
+                }
+
                 SetOutputGpio(ShmPrimaryMcuData->OutputDrv.OutputDrvValue[0]);
             }
 	    }

+ 321 - 56
EVSE/Projects/DO360/Apps/Module_PsuComm.c

@@ -85,8 +85,10 @@
 #define MAX_DIFF_POWER_TO_DERATING      5           // unit: 1kw
 #define MAX_DIFF_POWER_TO_EXTEND        3           // unit: 1kw
 #define MIN_DIFF_PHYSICAL_POWER         3           // unit: 1kw
+#define MIN_DIFF_CONFIG_POWER           3           // unit: 1kw
 #define PSU_DEBUG_MSG                   0
 #define ENABLE_SMOOTH_DERATING          1
+#define PSU_INDICATION_TIME             10          // unit: 1s
 
 struct SysConfigAndInfo			*ShmSysConfigAndInfo;
 struct StatusCodeData 			*ShmStatusCodeData;
@@ -146,6 +148,8 @@ unsigned char _VoltageResumeCnt[MAX_GROUP_QUANTITY];
 
 unsigned char _GunIndexOfPrioritySequence[MAX_GROUP_QUANTITY];
 PsuStatusInfo _LocalPsuStatus[MAX_PSU_MODULE_QUANTITY];
+bool _Psu_Indication_Enable[MAX_PSU_MODULE_QUANTITY];
+int _Psu_Indication_Count[MAX_PSU_MODULE_QUANTITY];
 
 int GetPsuModuleQuantity(unsigned char group);
 
@@ -508,6 +512,51 @@ void AbnormalStopAnalysis(byte gun_index, int errCode)
 	}
 }
 
+// return single psu alarm status: PsuStatusInfo
+unsigned int InfyPwrStateAnalysis(int psu_index, unsigned char state_0, unsigned char state_1, unsigned char state_2)
+{
+    bool _changed = false;
+    PsuStatusInfo _alarmStatus;
+
+    _alarmStatus.StatusVal = 0;
+
+    if(ShmPsuPosition->SingleInfyPwrState[psu_index].InfyPwrState.StateVal[0] != state_0 ||
+        (ShmPsuPosition->SingleInfyPwrState[psu_index].InfyPwrState.StateVal[1] & 0xFE) != (state_1 & 0xFE) ||
+        (ShmPsuPosition->SingleInfyPwrState[psu_index].InfyPwrState.StateVal[2] & 0x7F) != (state_2 & 0x7F))
+    {
+        _changed = true;
+    }
+
+    InfyPsuStateFlagInfo _infyState;
+
+    _infyState.StateVal[0] = state_0;
+    _infyState.StateVal[1] = state_1;
+    _infyState.StateVal[2] = state_2;
+
+    if(_infyState.bits.OutputShort ||
+       _infyState.bits.PsuFault ||
+       _infyState.bits.FanFault ||
+       _infyState.bits.PsuProtect ||
+       _infyState.bits.FanFault ||
+       _infyState.bits.OverTemperature ||
+       _infyState.bits.OutputOverVoltage ||
+       _infyState.bits.CanCommInterrupt ||
+       _infyState.bits.PsuIdRepetition ||
+       _infyState.bits.InputPhaseLost ||
+       _infyState.bits.InputUnderVoltage ||
+       _infyState.bits.InputOverVoltage)
+    {
+        _alarmStatus.bits.Fault = true;
+    }
+
+    ShmPsuPosition->SingleInfyPwrState[psu_index].InfyPwrStateFlag.bits.Changed = _changed;
+    ShmPsuPosition->SingleInfyPwrState[psu_index].InfyPwrState.StateVal[0] = state_0;
+    ShmPsuPosition->SingleInfyPwrState[psu_index].InfyPwrState.StateVal[1] = state_1;
+    ShmPsuPosition->SingleInfyPwrState[psu_index].InfyPwrState.StateVal[2] = state_2;
+
+    return _alarmStatus.StatusVal;
+}
+
 //=================================
 // Callback Function
 //=================================
@@ -664,7 +713,8 @@ void GetInfyPwrAlarmFlagCallback(byte address, byte state_2, byte state_1, byte
 {
     ShmChargerInfo->Control.CommInfo.PsuComm.RxCnt++;
 
-    if(ShmPsuData->Work_Step < Get_PSU_LOCATION)
+    if(ShmPsuData->Work_Step < Get_PSU_LOCATION || address >= ShmPsuData->SystemInitialPsuQuantity ||
+        !ShmPsuPosition->PsuLocationInit)
     {
         return;
     }
@@ -677,10 +727,11 @@ void GetInfyPwrAlarmFlagCallback(byte address, byte state_2, byte state_1, byte
         return;
     }
 
-    if(ShmPsuPosition->PsuLocationInit)
-    {
+    unsigned int _alarmStatus = 0;
 
-    }
+    _alarmStatus = InfyPwrStateAnalysis(address, state_0, state_1, state_2);
+
+    GetAlarmStatusCallback(address, _alarmStatus);
 }
 
 void GetPhPwrAlarmFlagCallback(byte address, unsigned int status, unsigned int alarm_1, unsigned int alarm_0)
@@ -997,6 +1048,25 @@ void GetPfcFwCallback(byte address, char *pfcSwVer)
 // no using -- GetInputVoltageCallback
 void GetInputVoltageCallback(byte address, unsigned short vol1, unsigned short vol2, unsigned short vol3)
 {
+    ShmChargerInfo->Control.CommInfo.PsuComm.RxCnt++;
+
+    if (ShmPsuData->Work_Step < GET_SYS_CAP || address >= ShmPsuData->SystemInitialPsuQuantity ||
+        !ShmPsuPosition->PsuLocationInit)
+    {
+        return;
+    }
+
+    int group = FindTargetGroup(address);
+    int gIndex = FindGroupIndex(address);
+
+    if(group < 0 || gIndex < 0)
+    {
+        return;
+    }
+
+    ShmPsuData->PsuGroup[group].PsuModule[gIndex].InputVoltageL1 = vol1;
+    ShmPsuData->PsuGroup[group].PsuModule[gIndex].InputVoltageL2 = vol2;
+    ShmPsuData->PsuGroup[group].PsuModule[gIndex].InputVoltageL3 = vol3;
 }
 // no using -- GetInputVoltageCallback End
 
@@ -1367,7 +1437,7 @@ void GetErrorRecordCallback(byte psu_index, byte count_down, byte *error_record)
         if(error_record[i] != 0)
         {
             err_cnt++;
-            if(ShmPsuPosition->SinglePsuError[psu_index].PsuError[i] != error_record[i] || _change)
+            if(ShmPsuPosition->SinglePhPsuError[psu_index].PsuError[i] != error_record[i] || _change)
             {
                 _change = true;
             }
@@ -1380,16 +1450,16 @@ void GetErrorRecordCallback(byte psu_index, byte count_down, byte *error_record)
 
     if(_change)
     {
-        memset(ShmPsuPosition->SinglePsuError[psu_index].PsuError, 0x00, sizeof(ShmPsuPosition->SinglePsuError[psu_index].PsuError));
-        memcpy(ShmPsuPosition->SinglePsuError[psu_index].PsuError, error_record, err_cnt);
+        memset(ShmPsuPosition->SinglePhPsuError[psu_index].PsuError, 0x00, sizeof(ShmPsuPosition->SinglePhPsuError[psu_index].PsuError));
+        memcpy(ShmPsuPosition->SinglePhPsuError[psu_index].PsuError, error_record, err_cnt);
     }
     else
     {
-        _change = ShmPsuPosition->SinglePsuError[psu_index].ErrorCount != err_cnt ? true : false;
+        _change = ShmPsuPosition->SinglePhPsuError[psu_index].ErrorCount != err_cnt ? true : false;
     }
 
-    ShmPsuPosition->SinglePsuError[psu_index].ErrorCount = err_cnt;
-    ShmPsuPosition->SinglePsuError[psu_index].ErrFlag.bits.Changed |= _change;
+    ShmPsuPosition->SinglePhPsuError[psu_index].ErrorCount = err_cnt;
+    ShmPsuPosition->SinglePhPsuError[psu_index].PhPwrStateFlag.bits.Changed |= _change;
 }
 
 //==========================================
@@ -1400,10 +1470,10 @@ void GetErrorRecordCallback(byte psu_index, byte count_down, byte *error_record)
 void GetOutputAndTempCallback(byte address, unsigned short outputVol_s,
 		unsigned short outputCur_s, unsigned short outputPower, unsigned char Temperature)
 {
-    ShmChargerInfo->Control.CommInfo.PsuComm.RxCnt++;
-
     return;
 
+    ShmChargerInfo->Control.CommInfo.PsuComm.RxCnt++;
+
     if (ShmPsuData->Work_Step < GET_SYS_CAP || address >= ShmPsuData->SystemInitialPsuQuantity ||
         !ShmPsuPosition->PsuLocationInit)
     {
@@ -1427,6 +1497,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)
 {
+    return;
+
     ShmChargerInfo->Control.CommInfo.PsuComm.RxCnt++;
 
     if (ShmPsuData->Work_Step < GET_SYS_CAP || address >= ShmPsuData->SystemInitialPsuQuantity ||
@@ -1460,6 +1532,8 @@ void GetModuleStatusCallback(byte address, unsigned char isErr, unsigned char st
 void GetModuleInputCallback(byte address, unsigned short inputR,
 		unsigned short inputS, unsigned short inputT)
 {
+    return;
+
     ShmChargerInfo->Control.CommInfo.PsuComm.RxCnt++;
 
     if (ShmPsuData->Work_Step < GET_SYS_CAP || address >= ShmPsuData->SystemInitialPsuQuantity ||
@@ -1605,8 +1679,12 @@ void InitialPsuData(void)
     ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuPfcEepromFault = NO;
     ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuCriticalPointOTP = NO;
     ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuDcdcOverVoltage = NO;
+    ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuFault = NO;
+    ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuProtectionAlarm = NO;
 
     memset(_LocalPsuStatus, 0x00, sizeof(_LocalPsuStatus));
+    memset(_Psu_Indication_Enable, 0x00, sizeof(_Psu_Indication_Enable));
+    memset(_Psu_Indication_Count, 0x00, sizeof(_Psu_Indication_Count));
     memset(&ShmChargerInfo->PsuGrouping.GroupPsuStatus_OR, 0x00, sizeof(ShmChargerInfo->PsuGrouping.GroupPsuStatus_OR));
     memset(&ShmChargerInfo->PsuGrouping.GroupPsuStatus_AND, 0x00, sizeof(ShmChargerInfo->PsuGrouping.GroupPsuStatus_AND));
 }
@@ -2760,15 +2838,33 @@ void UpdateGunLoading(unsigned char group)
 
         if(chargingInfo[group]->PresentChargingVoltage >= (PSU_MIN_VOL / 10))
         {
+            // unit: 1kW
+            float _diffPowerByCurrent = 0, _diffPowerByPower = 0, _presentTargerPower = 0;
+
+            _presentTargerPower = ((((float)ShmPsuGrouping->TotalGroupOutput[group].GTargetCurrent / 10) * chargingInfo[group]->PresentChargingVoltage) / 1000);
+
+            // DiffPower_Available
             ShmPsuGrouping->GroupCollection[group].DiffPower_Available = (((float)(chargingInfo[group]->AvailableChargingCurrent - ShmPsuGrouping->TotalGroupOutput[group].GTargetCurrent) / 10) * chargingInfo[group]->PresentChargingVoltage) / 1000;
-            ShmPsuGrouping->GroupCollection[group].DiffPower_Capability = (((float)(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[group].CapabilityCurrent - ShmPsuGrouping->TotalGroupOutput[group].GTargetCurrent) / 10) * chargingInfo[group]->PresentChargingVoltage) / 1000;
+
+            // DiffPower_Capability
+            _diffPowerByCurrent = (((float)(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[group].CapabilityCurrent - ShmPsuGrouping->TotalGroupOutput[group].GTargetCurrent) / 10) * chargingInfo[group]->PresentChargingVoltage) / 1000;
+            _diffPowerByPower = (ShmSysConfigAndInfo->SysInfo.ConnectorInfo[group].CapabilityPower / 10) - _presentTargerPower;
+            ShmPsuGrouping->GroupCollection[group].DiffPower_Capability = _diffPowerByPower < _diffPowerByCurrent ? _diffPowerByPower : _diffPowerByCurrent;
+
+            // DiffPower_PhysicalLimit
             ShmPsuGrouping->GroupCollection[group].DiffPower_PhysicalLimit = (((float)(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[group].RemoteMaxPhysicalCurrent - ShmPsuGrouping->TotalGroupOutput[group].GTargetCurrent) / 10) * chargingInfo[group]->PresentChargingVoltage) / 1000;
+
+            // DiffPower_ConfigLimit
+            _diffPowerByCurrent = (((float)(ShmChargerInfo->OutputLimit.GunLimitCurrent[group] - ShmPsuGrouping->TotalGroupOutput[group].GTargetCurrent) / 10) * chargingInfo[group]->PresentChargingVoltage) / 1000;
+            _diffPowerByPower = (ShmChargerInfo->OutputLimit.GunLimitPower[group] / 10) - _presentTargerPower;
+            ShmPsuGrouping->GroupCollection[group].DiffPower_ConfigLimit = _diffPowerByPower < _diffPowerByCurrent ? _diffPowerByPower : _diffPowerByCurrent;
         }
         else
         {
             ShmPsuGrouping->GroupCollection[group].DiffPower_Available = 0;
             ShmPsuGrouping->GroupCollection[group].DiffPower_Capability = 0;
             ShmPsuGrouping->GroupCollection[group].DiffPower_PhysicalLimit = 0;
+            ShmPsuGrouping->GroupCollection[group].DiffPower_ConfigLimit = 0;
         }
     }
     else
@@ -3654,8 +3750,10 @@ void CheckReleaseOrExtend(unsigned char master)
 #endif
             }
         }
-        else if(ShmPsuGrouping->GroupCollection[master].DiffPower_Capability <= MAX_DIFF_POWER_TO_EXTEND &&
-            ShmPsuGrouping->GroupCollection[master].DiffPower_PhysicalLimit >= MIN_DIFF_PHYSICAL_POWER)
+        else if(ShmPsuGrouping->GroupCollection[master].DiffPower_Available < MAX_DIFF_POWER_TO_EXTEND &&
+            ShmPsuGrouping->GroupCollection[master].DiffPower_Capability < MAX_DIFF_POWER_TO_EXTEND &&
+            ShmPsuGrouping->GroupCollection[master].DiffPower_PhysicalLimit >= MIN_DIFF_PHYSICAL_POWER &&
+            ShmPsuGrouping->GroupCollection[master].DiffPower_ConfigLimit >= MIN_DIFF_CONFIG_POWER)
         {
             time = GetTimeoutValue(_ExtendCapability_time[master]) / uSEC_VAL;
 
@@ -3667,9 +3765,10 @@ void CheckReleaseOrExtend(unsigned char master)
                 {
                     if(!ShmPsuGrouping->GroupCollection[master].GroupCtrl.bits.ExtendAvailable)
                     {
-                        LOG_INFO("Gun %d Extend Capability Available, DifPcap: %.1f kW, DifPphy: %.1f",
+                        LOG_INFO("Gun %d Extend Capability Available, DifPcap: %.1f kW, DiffConfig: %.1f kW, DifPphy: %.1f kW",
                             master + 1,
                             ShmPsuGrouping->GroupCollection[master].DiffPower_Capability,
+                            ShmPsuGrouping->GroupCollection[master].DiffPower_ConfigLimit,
                             ShmPsuGrouping->GroupCollection[master].DiffPower_PhysicalLimit);
                         GetClockTime(&_ExtendCapability_time[master]);
                     }
@@ -4996,6 +5095,11 @@ void TryCleanPsuAlarm(unsigned char group)
 
 void CheckPsuAlarmStatus(void)
 {
+    if(_isTriggerShutdown)
+    {
+        return;
+    }
+
     for(int i = 0; i < MAX_GROUP_QUANTITY; i++)
     {
         for(int j = 0; j < ShmPsuPosition->GroupLocationInfo[i].GroupPsuQuantity; j++)
@@ -5045,21 +5149,96 @@ void CheckPsuAlarmStatus(void)
     }
 }
 
-void ShowPsuErrRecord(int psu_index)
+void ShowInfyPsuErrState(int psu_index)
+{
+    LOG_INFO("Group[%d][%d] Psu[%2d] State2: [%02X], State1: [%02X], State0: [%02X]",
+        ShmPsuPosition->PsuAddressInfo[psu_index].GroupNo,
+        ShmPsuPosition->PsuAddressInfo[psu_index].GIndex,
+        psu_index,
+        ShmPsuPosition->SingleInfyPwrState[psu_index].InfyPwrState.StateVal[2],
+        ShmPsuPosition->SingleInfyPwrState[psu_index].InfyPwrState.StateVal[1],
+        ShmPsuPosition->SingleInfyPwrState[psu_index].InfyPwrState.StateVal[0]);
+}
+
+void InfyPwrStateSummary(void)
+{
+    InfyPsuStateFlagInfo _InfyPwrState;
+
+    memset(&_InfyPwrState, 0x00, sizeof(_InfyPwrState));
+
+    for(int i = 0; i < MAX_PSU_MODULE_QUANTITY; i++)
+    {
+        _InfyPwrState.StateVal[0] |= ShmPsuPosition->SingleInfyPwrState[i].InfyPwrState.StateVal[0];
+        _InfyPwrState.StateVal[1] |= ShmPsuPosition->SingleInfyPwrState[i].InfyPwrState.StateVal[1];
+        _InfyPwrState.StateVal[1] |= ShmPsuPosition->SingleInfyPwrState[i].InfyPwrState.StateVal[2];
+    }
+
+    // 012264
+    // DCDC short circuit
+    ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuOutputShortCircuit = _InfyPwrState.bits.OutputShort ? YES : NO;
+
+    // 012334
+    // PSU Failure Alarm
+    ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuFault = _InfyPwrState.bits.PsuFault ? YES : NO;
+
+    // 012268
+    // PSU Protection Alarm
+    ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuProtectionAlarm = _InfyPwrState.bits.PsuProtect ? YES : NO;
+
+    // 012269
+    // Fan faults
+    ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuFanFailureAlarm = _InfyPwrState.bits.FanFault ? YES : NO;
+
+    // 012226
+    // DCDC over temperature
+    ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuCriticalPointOTP = _InfyPwrState.bits.OverTemperature ? YES : NO;
+
+    // 012319
+    // DCDC output over voltage
+    ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuDcdcOverVoltage = _InfyPwrState.bits.OutputOverVoltage ? YES : NO;
+
+    // 012273
+    // Module unders power limiting status
+    ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuPowerLimitedState = _InfyPwrState.bits.PowerLimit ? YES : NO;
+
+    // 012263
+    // ID number repetition
+    ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuDuplicateID = _InfyPwrState.bits.PsuIdRepetition ? YES : NO;
+
+    // 012313
+    // Phase loss
+    ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuInputPhaseLoss = _InfyPwrState.bits.InputPhaseLost ? YES : NO;
+
+    // 012271
+    // Under voltage of any phase
+    ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuInputUVP = _InfyPwrState.bits.InputUnderVoltage ? YES : NO;
+
+    // 012270
+    // Over voltage of any phase
+    ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuInputOVP = _InfyPwrState.bits.InputOverVoltage ? YES : NO;
+}
+
+void ShowPhPsuErrRecord(int psu_index)
 {
-    if(ShmPsuPosition->SinglePsuError[psu_index].ErrorCount == 0)
+    if(ShmPsuPosition->SinglePhPsuError[psu_index].ErrorCount == 0)
     {
-        LOG_INFO("PSU Group[%d] Index[%d] Error Record Clear", ShmPsuPosition->PsuAddressInfo[psu_index].GroupNo, ShmPsuPosition->PsuAddressInfo[psu_index].GIndex);
+        LOG_INFO("Group[%d][%d] Psu[%2d] Error Record Clear",
+            ShmPsuPosition->PsuAddressInfo[psu_index].GroupNo,
+            ShmPsuPosition->PsuAddressInfo[psu_index].GIndex,
+            psu_index);
     }
     else
     {
         char strErrRecord[128];
         char strError[16];
-        sprintf(strErrRecord, "PSU Group[%d] Index[%d] Err:", ShmPsuPosition->PsuAddressInfo[psu_index].GroupNo, ShmPsuPosition->PsuAddressInfo[psu_index].GIndex);
+        sprintf(strErrRecord, "Group[%d][%d] Psu[%2d] Err:",
+            ShmPsuPosition->PsuAddressInfo[psu_index].GroupNo,
+            ShmPsuPosition->PsuAddressInfo[psu_index].GIndex,
+            psu_index);
 
-        for(int i = 0; i < ShmPsuPosition->SinglePsuError[psu_index].ErrorCount; i++)
+        for(int i = 0; i < ShmPsuPosition->SinglePhPsuError[psu_index].ErrorCount; i++)
         {
-            sprintf(strError, " E-%2d", ShmPsuPosition->SinglePsuError[psu_index].PsuError[i]);
+            sprintf(strError, " E-%2d", ShmPsuPosition->SinglePhPsuError[psu_index].PsuError[i]);
             strcat(strErrRecord, strError);
         }
         LOG_INFO("%s", strErrRecord);
@@ -5068,35 +5247,69 @@ void ShowPsuErrRecord(int psu_index)
 
 void CheckPsuErrRecord(void)
 {
+    if(_isTriggerShutdown)
+    {
+        return;
+    }
+
     for(int i = 0; i < MAX_GROUP_QUANTITY; i++)
     {
         for(int j = 0; j < ShmPsuPosition->GroupLocationInfo[i].GroupPsuQuantity; j++)
         {
             int psu_index = ShmPsuPosition->GroupLocationInfo[i].PsuIndex[j];
 
-            if(ShmPsuPosition->SinglePsuError[psu_index].ErrFlag.bits.Changed)
+            if(ShmChargerInfo->Control.LibCtrl.bits.InfyPwrLib)
             {
-                ShowPsuErrRecord(psu_index);
-                ShmPsuPosition->SinglePsuError[psu_index].ErrFlag.bits.Changed = false;
+                if(ShmPsuPosition->SingleInfyPwrState[psu_index].InfyPwrStateFlag.bits.Changed)
+                {
+                    ShowInfyPsuErrState(psu_index);
+                    InfyPwrStateSummary();
+                    ShmPsuPosition->SingleInfyPwrState[psu_index].InfyPwrStateFlag.bits.Changed = false;
+                }
+            }
+
+            if(ShmChargerInfo->Control.LibCtrl.bits.PhPwrLib)
+            {
+                if(ShmPsuPosition->SinglePhPsuError[psu_index].PhPwrStateFlag.bits.Changed)
+                {
+                    ShowPhPsuErrRecord(psu_index);
+                    ShmPsuPosition->SinglePhPsuError[psu_index].PhPwrStateFlag.bits.Changed = false;
+                }
             }
         }
     }
 }
 
-bool IsPsuGroupAnyAlarmFault(unsigned char group)
+bool IsPsuGroupAnyAlarm(unsigned char group)
+{
+    if((ShmChargerInfo->PsuGrouping.GroupPsuStatus_OR[group].StatusVal & PSU_STATUS_FLAG_ALARM) > 0)
+    {
+        return true;
+    }
+    return false;
+}
+
+bool IsPsuGroupAnyFault(unsigned char group)
+{
+    if((ShmChargerInfo->PsuGrouping.GroupPsuStatus_OR[group].StatusVal & PSU_STATUS_FLAG_FAULT) > 0)
+    {
+        return true;
+    }
+    return false;
+}
+
+bool IsPsuGroupAllAlarm(unsigned char group)
 {
-    if((ShmChargerInfo->PsuGrouping.GroupPsuStatus_OR[group].StatusVal & PSU_STATUS_FLAG_FAULT) ||
-        (ShmChargerInfo->PsuGrouping.GroupPsuStatus_OR[group].StatusVal & PSU_STATUS_FLAG_ALARM))
+    if((ShmChargerInfo->PsuGrouping.GroupPsuStatus_AND[group].StatusVal & PSU_STATUS_FLAG_ALARM) > 0)
     {
         return true;
     }
     return false;
 }
 
-bool IsPsuGroupAllAlarmFault(unsigned char group)
+bool IsPsuGroupAllFault(unsigned char group)
 {
-    if((ShmChargerInfo->PsuGrouping.GroupPsuStatus_AND[group].StatusVal & PSU_STATUS_FLAG_FAULT) ||
-        (ShmChargerInfo->PsuGrouping.GroupPsuStatus_AND[group].StatusVal & PSU_STATUS_FLAG_ALARM))
+    if((ShmChargerInfo->PsuGrouping.GroupPsuStatus_AND[group].StatusVal & PSU_STATUS_FLAG_FAULT) > 0)
     {
         return true;
     }
@@ -5145,6 +5358,7 @@ void PsuGroupControlProcess(void)
                     ShmPsuGrouping->TotalGroupOutput[group].GTargetVoltage = 0;
                     ShmPsuGrouping->TotalGroupOutput[group].GTargetCurrent = 0;
                     SetPsuGroupOutput(group);
+                    UpdatePsuGroupLoading(group);
                 }
 
                 if(isStartOutputSwitch[group])
@@ -5152,33 +5366,44 @@ void PsuGroupControlProcess(void)
                     SetPsuGroupPowerOnOff(group, _PSU_OFF);
                 }
 
-                if(IsPsuGroupAnyAlarmFault(group))
+                if(ShmChargerInfo->Control.LibCtrl.bits.PhPwrLib)
                 {
-                    time = GetTimeoutValue(_CleanPsuAlarm_time[group]) / uSEC_VAL;
-
-                    if(time >= PSU_CLEAN_ERR_INTERVAL)
+                    if(IsPsuGroupAnyAlarm(group))
                     {
-                        PSU_LOG("PSU Group[%d] Alarm or Fault Occur, Need Do Something", group);
-                        GetClockTime(&_CleanPsuAlarm_time[group]);
-                    }
-                }
-                else if(IsPsuGroupAnyLock(group))
-                {
-                    time = GetTimeoutValue(_CleanPsuAlarm_time[group]) / uSEC_VAL;
+                        time = GetTimeoutValue(_CleanPsuAlarm_time[group]) / uSEC_VAL;
 
-                    if(time >= PSU_CLEAN_ERR_INTERVAL)
+                        if(time >= PSU_CLEAN_ERR_INTERVAL)
+                        {
+                            PSU_LOG("PSU Group[%d] Alarm or Fault Occur, Need Do Something", group);
+                            GetClockTime(&_CleanPsuAlarm_time[group]);
+                        }
+                        // if module exist any alarm or fault, break here
+                        break;
+                    }
+                    else if(IsPsuGroupAnyLock(group))
                     {
-                        TryCleanPsuAlarm(group);
-                        GetClockTime(&_CleanPsuAlarm_time[group]);
+                        time = GetTimeoutValue(_CleanPsuAlarm_time[group]) / uSEC_VAL;
+
+                        if(time >= PSU_CLEAN_ERR_INTERVAL)
+                        {
+                            TryCleanPsuAlarm(group);
+                            GetClockTime(&_CleanPsuAlarm_time[group]);
+                        }
+                        // if module exist any lock, break here
+                        break;
                     }
                 }
-                else
+
+                if(ShmPsuGrouping->GroupCollection[group].GroupCtrl.RoleCtrl.IdleCtrlValue != 0)
                 {
-                    if(ShmPsuGrouping->GroupCollection[group].GroupCtrl.RoleCtrl.IdleCtrlValue != 0 &&
-                        ShmPsuData->PsuGroup[group].GroupPresentPsuQuantity > 0)
+                    if(ShmPsuData->PsuGroup[group].GroupPresentPsuQuantity > 0)
                     {
                         CheckChargingRequest(group);
                     }
+                    else
+                    {
+
+                    }
                 }
                 break;
 
@@ -5224,17 +5449,19 @@ void PsuGroupControlProcess(void)
                     }
                     ShmPsuGrouping->GroupCollection[group].GroupCtrl.bits.StopChargingRequest = true;
                 }
-                if(IsPsuGroupAllAlarmFault(group))
+                if((IsPsuGroupAllAlarm(group) || IsPsuGroupAllFault(group)) &&
+                    !_isTriggerShutdown &&
+                    !ShmPsuGrouping->GroupCollection[group].GroupCtrl.bits.StopChargingRequest)
                 {
-                    if(!ShmChargerInfo->GunError[group].ErrFlag.bits.PsuGroupAllAlarmFault)
+                    if(!ShmChargerInfo->GunError[group].ErrFlag.bits.PsuGroupNoResource)
                     {
-                        LOG_INFO("Gun %d PsuGroup All Alarm/Fault, Need Stop Charging", group + 1);
+                        LOG_INFO("Gun %d PsuGroup All Alarm/Fault >> No Resource, Need Stop Charging", group + 1);
                     }
                     if(strncmp(ShmChargerInfo->GunError[group].GunAlarmCode, "", 6) == EQUAL)
                     {
-                        strcpy(ShmChargerInfo->GunError[group].GunAlarmCode, "042268");
+                        strcpy(ShmChargerInfo->GunError[group].GunAlarmCode, "042279");
                     }
-                    ShmChargerInfo->GunError[group].ErrFlag.bits.PsuGroupAllAlarmFault = true;
+                    ShmChargerInfo->GunError[group].ErrFlag.bits.PsuGroupNoResource = true;
                 }
 
                 if(ShmPsuGrouping->GroupCollection[group].GroupCtrl.RoleCtrl.ExtendCapabilityCtrlValue == 0)
@@ -5323,7 +5550,7 @@ void PsuGroupControlProcess(void)
                 }
                 else
                 {
-                    if(IsPsuGroupAllAlarmFault(group))
+                    if(IsPsuGroupAllAlarm(group) || IsPsuGroupAllFault(group))
                     {
                         if(!ShmPsuGrouping->GroupCollection[group].GroupCtrl.bits.SlavePowerOffRequest)
                         {
@@ -5673,7 +5900,7 @@ void PsuGroupAvailableSimulation(void)
 
             if((master - 1) != i)
             {
-                chargingInfo[i]->AvailableChargingCurrent = 0;;
+                chargingInfo[i]->AvailableChargingCurrent = 0;
                 chargingInfo[i]->AvailableChargingPower = 0;
                 chargingInfo[i]->RealRatingPower = 0;
                 chargingInfo[i]->MaximumChargingVoltage = 0;
@@ -5908,6 +6135,42 @@ bool IsShutdownCompleted(void)
     return done;
 }
 
+void PsuIndication(void)
+{
+    if(ShmChargerInfo->Control.LibCtrl.bits.InfyPwrLib)
+    {
+        for(int i = 0; i < MAX_PSU_MODULE_QUANTITY; i++)
+        {
+            if(ShmPsuPosition->SingleInfyPwrState[i].InfyPwrStateFlag.bits.Indicated)
+            {
+                LedSingleOnOff(i, _PSU_ON);
+                LOG_INFO("Set Psu[%2d] Led Blinking", i);
+                _Psu_Indication_Enable[i] = true;
+                _Psu_Indication_Count[i] = PSU_INDICATION_TIME;
+                ShmPsuPosition->SingleInfyPwrState[i].InfyPwrStateFlag.bits.Indicated = false;
+            }
+            else
+            {
+                if(_Psu_Indication_Enable[i])
+                {
+                    _Psu_Indication_Count[i]--;
+
+                    if(_Psu_Indication_Count[i] == 0)
+                    {
+                        LedSingleOnOff(i, _PSU_OFF);
+                        LOG_INFO("Set Psu[%2d] Led Static", i);
+                        _Psu_Indication_Enable[i] = false;
+                    }
+                }
+            }
+        }
+    }
+    if(ShmChargerInfo->Control.LibCtrl.bits.PhPwrLib)
+    {
+
+    }
+}
+
 int main(void)
 {
     byte _TotalModuleCount = 0;
@@ -6377,13 +6640,15 @@ int main(void)
 				            GetModuleCount(i);
 				            GetModuleInputVol(i);
 
-                            if(IsPsuGroupAnyAlarmFault(i))
+                            if(IsPsuGroupAnyAlarm(i) || IsPsuGroupAnyFault(i))
                             {
                                 GetErrorRecord(i);
                             }
 				        }
 				    }
 
+				    PsuIndication();
+
                     for(int i = 0; i < MAX_GUN_QUANTITY; i++)
                     {
                         UpdateGunTotalPsuQuantity(i);

+ 514 - 70
EVSE/Projects/DO360/Apps/ReadCmdline.c

@@ -44,17 +44,19 @@
 typedef unsigned char			byte;
 #define	NO_DEFINE			    255
 
-#define OPTION_CNT              3
+#define OPTION_CNT              4
 #define STR_OPTION              '-'
 #define OPTION_REFLASH          0x00000001
 #define OPTION_LOOP             0x00000002
-#define OPTION_TIME             0x00000004
+#define OPTION_OUTPUT_FILE      0x00000004
+#define OPTION_TIME             0x00000008
 
 #define MAX_SUB_CMD_QUANTITY    16
 #define MAX_SUB_CMD_LENGTH      128
 
 #define STR_OPT_REFLASH         'f'
 #define STR_OPT_LOOP            'l'
+#define STR_OPT_OUTPUT_FILE     'o'
 #define STR_OPT_TIME            't'
 
 #define TTY_PATH                "/dev/tty"
@@ -356,8 +358,8 @@ int ParsingCmd(char *inputString, char *outputString)
 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};
+    char str_opt[OPTION_CNT] = {STR_OPT_REFLASH, STR_OPT_LOOP, STR_OPT_OUTPUT_FILE, STR_OPT_TIME};
+    unsigned int opt_value[OPTION_CNT] = {OPTION_REFLASH, OPTION_LOOP, OPTION_OUTPUT_FILE, OPTION_TIME};
 
     len = strlen(strCmd);
 
@@ -1947,47 +1949,181 @@ void SetTestControl(char *v1, char *v2)
     printf("\r\n");
 }
 
-// Gun  Role  Master  K1K2  GTVoltage  GTCurrent  StableCurrent  OutputLoading  GunLoading  DiffP_Ava  DiffP_Cap  DiffP_Lim
-//  1    00     00      0     0000 V    000.0 A       0000 A         XXX.XX       XXX.XX      XXX kw     XXX kW    XXX kW
-void ShowGroupingDemand(void)
+//                                                        Group     Gun                                    Available               Psu Group Control
+// Gun  Role  Master  K1K2   GTVol     GTCur  StableCur  Loading  Loading  DiffP_Ava  DiffP_Cap  DiffP_Lim  Partner  IdleCtrl Master   Stop  Derating  Extend   Slave
+//  1    00     00      0   0000 V   000.0 A    0000 A    XXX.XX   XXX.XX    XXX kw     XXX kW    XXX kW      XX      0xXXXX  0xXXXX  0xXXXX  0xXXXX   0xXXXX  0xXXXX
+
+//                                                        Group     Gun                                       DiffP   Available               Psu Group Control
+// Gun  Role  Master  K1K2   GTVol     GTCur  StableCur  Loading  Loading  DiffP_Ava  DiffP_Cap  DiffP_Lim  ConfigLim  Partner  IdleCtrl Master   Stop  Derating  Extend   Slave
+//  1    00     00      0   0000 V   000.0 A    0000 A    XXX.XX   XXX.XX    XXX kw     XXX kW    XXX kW      XXX kW     XX      0xXXXX  0xXXXX  0xXXXX  0xXXXX   0xXXXX  0xXXXX
+void ShowGroupingDemand(char *inputCmd, unsigned int opt)
 {
-    byte target = 0;
-    unsigned char k1k2 = 0;
+    bool keepRun = false;
+    bool reflash = false;
+    bool outputFile = false;
+    bool allRoleIdle = false;
+    bool fullInfo = false;
+    int totalCnt = 0;
 
-    printf("\r\n Gun  Role  Master  K1K2  GTVoltage  GTCurrent  StableCurrent  OutputLoading  GunLoading  DiffP_Ava  DiffP_Cap  DiffP_Lim");
+    totalCnt = GetSubCommand(inputCmd);
 
-    for(int i = 0; i < 4; i++)
+    if(totalCnt == 1)
     {
-        target = ShmPsuGrouping->Layout[i];
-        if(ShmChargerInfo->PsuGrouping.GroupCollection[target].TargetGroup != 0)
+        if(strcmp(&MultiSubCmd[0][0], "full") == 0)
         {
-            k1k2 = _chargingData[ShmChargerInfo->PsuGrouping.GroupCollection[target].TargetGroup - 1]->RelayK1K2Status;
+            fullInfo = true;
         }
-        else
+    }
+
+    int time = 0;
+    struct timespec _Loop_time;
+    char lineString[512];
+    char tempString[128];
+
+    if((opt & OPTION_REFLASH) || (opt & OPTION_LOOP) > 0)
+    {
+        keepRun = true;
+    }
+
+    if((opt & OPTION_OUTPUT_FILE) > 0)
+    {
+        outputFile = true;
+    }
+
+    byte target = 0;
+    unsigned char k1k2 = 0;
+
+    //printf("                                                        Group     Gun                                    Available               Psu Group Control\r\n");
+    //printf(" Gun  Role  Master  K1K2   GTVol     GTCur  StableCur  Loading  Loading  DiffP_Ava  DiffP_Cap  DiffP_Lim  Partner  IdleCtrl Master   Stop  Derating  Extend   Slave\r\n");
+    memset(lineString, 0x00, sizeof(lineString));
+    sprintf(lineString, "                                                        Group     Gun                                       DiffP");
+    if(fullInfo)
+    {
+        sprintf(tempString, "   Available               Psu Group Control");
+        strcat(lineString, tempString);
+    }
+    if(!outputFile)
+    {
+        printf("%s\r\n", lineString);
+    }
+    else
+    {
+        ReadCmd_INFO("%s", lineString);
+    }
+
+    sprintf(lineString, " Gun  Role  Master  K1K2   GTVol     GTCur  StableCur  Loading  Loading  DiffP_Ava  DiffP_Cap  DiffP_Lim  ConfigLim");
+    if(fullInfo)
+    {
+        sprintf(tempString, "  Partner  IdleCtrl Master   Stop  Derating  Extend   Slave");
+        strcat(lineString, tempString);
+    }
+    if(!outputFile)
+    {
+        printf("%s\r\n", lineString);
+    }
+    else
+    {
+        ReadCmd_INFO("%s", lineString);
+    }
+
+    do
+    {
+        time = GetTimeoutValue(_Loop_time) / mSEC_VAL;
+        if(time >= 1000)
         {
-            k1k2 = _chargingData[target]->RelayK1K2Status;
+            if(reflash)
+            {
+                ConsoleReflash(MAX_GROUP_QUANTITY, 1);
+            }
+
+            for(int i = 0; i < MAX_GROUP_QUANTITY; i++)
+            {
+                target = ShmPsuGrouping->Layout[i];
+                if(ShmChargerInfo->PsuGrouping.GroupCollection[target].TargetGroup != 0)
+                {
+                    k1k2 = _chargingData[ShmChargerInfo->PsuGrouping.GroupCollection[target].TargetGroup - 1]->RelayK1K2Status;
+                }
+                else
+                {
+                    k1k2 = _chargingData[target]->RelayK1K2Status;
+                }
+
+                memset(lineString, 0x00, sizeof(lineString));
+                sprintf(tempString, "  %d    %2d     %02X      %d   %4d V   %3d.%d A    %4d A    %3d.%02d",
+                    target + 1, ShmChargerInfo->PsuGrouping.GroupCollection[target].Role, ShmChargerInfo->PsuGrouping.GroupCollection[target].TargetGroup, k1k2,
+                    (ShmPsuGrouping->GroupOutput[target].GTargetVoltage / 10),
+                    (ShmPsuGrouping->GroupOutput[target].GTargetCurrent / 10),
+                    (ShmPsuGrouping->GroupOutput[target].GTargetCurrent % 10),
+                    (int)(_chargingData[target]->AvailableChargingCurrent / 10),
+                    (ShmPsuGrouping->GroupOutput[target].OutputLoading / 100),
+                    (ShmPsuGrouping->GroupOutput[target].OutputLoading % 100));
+                strcat(lineString, tempString);
+
+                //if(ShmChargerInfo->PsuGrouping.GroupCollection[target].TargetGroup == target + 1)
+                //{
+                    sprintf(tempString, "   %3d.%02d", (ShmChargerInfo->PsuGrouping.GroupCollection[target].GunLoading / 100), (ShmChargerInfo->PsuGrouping.GroupCollection[target].GunLoading % 100));
+                    strcat(lineString, tempString);
+
+
+                    sprintf(tempString, "    %3d kW     %3d kW    %3d kW      %3d kW",
+                        (int)ShmPsuGrouping->GroupCollection[target].DiffPower_Available,
+                        (int)ShmPsuGrouping->GroupCollection[target].DiffPower_Capability,
+                        (int)ShmPsuGrouping->GroupCollection[target].DiffPower_PhysicalLimit,
+                        (int)ShmPsuGrouping->GroupCollection[target].DiffPower_ConfigLimit);
+                    strcat(lineString, tempString);
+
+                    if(fullInfo)
+                    {
+                        int partner_quantity = GetPsuGroupAvailable(target);
+                        sprintf(tempString, "     %2d      0x%04X  0x%04X  0x%04X  0x%04X   0x%04X  0x%04X",
+                            partner_quantity,
+                            ShmPsuGrouping->GroupCollection[target].GroupCtrl.RoleCtrl.IdleCtrlValue,
+                            ShmPsuGrouping->GroupCollection[target].GroupCtrl.RoleCtrl.MasterCtrlValue,
+                            ShmPsuGrouping->GroupCollection[target].GroupCtrl.RoleCtrl.StopChargingCtrlValue,
+                            ShmPsuGrouping->GroupCollection[target].GroupCtrl.RoleCtrl.DeratingCtrlValue,
+                            ShmPsuGrouping->GroupCollection[target].GroupCtrl.RoleCtrl.ExtendCapabilityCtrlValue,
+                            ShmPsuGrouping->GroupCollection[target].GroupCtrl.RoleCtrl.SlaveCtrlValue);
+                        strcat(lineString, tempString);
+                    }
+                //}
+
+                if(!outputFile)
+                {
+                    printf("%s\r\n", lineString);
+                }
+                else
+                {
+                    if(!allRoleIdle)
+                    {
+                        ReadCmd_INFO("%s", lineString);
+                    }
+                }
+            }
+
+            allRoleIdle = true;
+            for(int i = 0; i < MAX_GROUP_QUANTITY; i++)
+            {
+                if(ShmChargerInfo->PsuGrouping.GroupCollection[i].Role != _GROLE_IDLE)
+                {
+                    allRoleIdle = false;
+                }
+            }
+
+            GetClockTime(&_Loop_time);
+            if((opt & OPTION_REFLASH) > 0 && !outputFile)
+            {
+                reflash = true;
+            }
         }
 
-        printf("\r\n  %d    %2d     %02X      %d     %4d V    %3d.%d A       %4d A         %3d.%02d",
-            target + 1, ShmChargerInfo->PsuGrouping.GroupCollection[target].Role, ShmChargerInfo->PsuGrouping.GroupCollection[target].TargetGroup, k1k2,
-            (ShmPsuGrouping->GroupOutput[target].GTargetVoltage / 10),
-            (ShmPsuGrouping->GroupOutput[target].GTargetCurrent / 10),
-            (ShmPsuGrouping->GroupOutput[target].GTargetCurrent % 10),
-            (int)(_chargingData[target]->AvailableChargingCurrent / 10),
-            (ShmPsuGrouping->GroupOutput[target].OutputLoading / 100),
-            (ShmPsuGrouping->GroupOutput[target].OutputLoading % 100));
-        if(ShmChargerInfo->PsuGrouping.GroupCollection[target].TargetGroup == target + 1)
+        if(keepRun)
         {
-            printf("       %3d.%02d", (ShmChargerInfo->PsuGrouping.GroupCollection[target].GunLoading / 100), (ShmChargerInfo->PsuGrouping.GroupCollection[target].GunLoading % 100));
-
-            printf("      %3d kW     %3d kW    %3d kW",
-                (int)ShmPsuGrouping->GroupCollection[target].DiffPower_Available,
-                (int)ShmPsuGrouping->GroupCollection[target].DiffPower_Capability,
-                (int)ShmPsuGrouping->GroupCollection[target].DiffPower_PhysicalLimit);
+            keepRun = IsLoopStopCmd() ? false : true;
+            usleep(10000);
         }
-    }
+    }while(keepRun);
 
-    printf("\r\n\r\n");
+    printf("\r\n");
 }
 
 // v1: gun
@@ -3673,7 +3809,15 @@ void EvCommMsgDebug(char *inputCmd, unsigned int opt)
 
     bool find = false;
     int reg = 0, enable = 0;
-    reg = atoi(&MultiSubCmd[0][0]);
+
+    if(strcmp(&MultiSubCmd[0][0], "0x") == EQUAL && strlen(&MultiSubCmd[0][0]) > 2)
+    {
+        reg = (int)strtol(&MultiSubCmd[0][0], NULL, 16);
+    }
+    else
+    {
+        reg = atoi(&MultiSubCmd[0][0]);
+    }
     enable = atoi(&MultiSubCmd[1][0]);
 
     if(enable > 1 || enable < 0)
@@ -4785,7 +4929,7 @@ void RelayCmd(char *inputCmd, unsigned int opt)
     memset(subMain, 0x00, sizeof(subMain));
     memset(subSub, 0x00, sizeof(subSub));
 
-    if(MainAndSubCommandParsing(inputCmd, subMain, subSub) >= 2)
+    if(MainAndSubCommandParsing(inputCmd, subMain, subSub) == 2)
     {
         if(strcmp(subMain, "abnormal") == EQUAL)
         {
@@ -5236,6 +5380,194 @@ void ShowOccupancy(char *inputCmd, unsigned int opt)
     printf("\r\n");
 }
 
+void SetCustomizedFlag(int shift, bool enable)
+{
+    if(enable)
+    {
+        ShmChargerInfo->Control.CustomizedInfo.Flag.CtrlValue |= (1 << shift);
+    }
+    else
+    {
+        ShmChargerInfo->Control.CustomizedInfo.Flag.CtrlValue &= ~(1 << shift);
+    }
+}
+
+// super customized standby [enable/disable]
+// super customized tccstandby [enable/disable]
+// super customized standbyfast [enable/disable]
+// super customized freestandby [enable/disable]
+// super customized tilt [enable/disable]
+void SetCustomizedCmd(char *inputCmd)
+{
+    int totalCnt = 0, maxPara = 0;
+
+    maxPara = 2;
+    totalCnt = GetSubCommand(inputCmd);
+
+    if(totalCnt != maxPara)
+    {
+        printf("Input cmd fail ------  super [customized] [disstandby | tccstandby | standbyfast | cstandby | tilt] [enable | disable]\r\n\r\n");
+        return;
+    }
+
+    int maxCustomized = 5;
+    int shift = 0;
+    bool enable = false, find = false;;
+
+    enable = strcmp(&MultiSubCmd[1][0], "enable") == EQUAL ? true : false;
+
+
+    char *str_customized[] = {"disstandby", "tccstandby", "standbyfast", "freestandby", "tilt"};
+
+    for(int i = 0; i < maxCustomized; i++)
+    {
+        if(strcmp(&MultiSubCmd[0][0], str_customized[i]) == EQUAL)
+        {
+            shift = i;
+            find = true;
+            break;
+        }
+    }
+
+    if(find)
+    {
+        SetCustomizedFlag(shift, enable);
+        printf("\r\n");
+        printf("%s %s customized flag\r\n\r\n", enable ? "Enable" : "Disable", str_customized[shift]);
+
+        return;
+    }
+
+    printf("\r\n");
+    printf("Input cmd fail ------  super [customized] [disstandby | tccstandby | standbyfast | cstandby | tilt] [enable | disable]\r\n\r\n");
+}
+
+void TiltSensorTrigger(void)
+{
+    ShmChargerInfo->Control.CustomizedInfo.TiltSensorStep = _TILT_SENSOR_NONE;
+    printf("\r\n");
+    printf("Reset tilt sensor step\r\n\r\n");
+}
+
+void TiltSensorCmd(char *inputCmd)
+{
+    char subMain[MAX_SUB_CMD_LENGTH];
+    char subSub[MAX_SUB_CMD_LENGTH];
+
+    memset(subMain, 0x00, sizeof(subMain));
+    memset(subSub, 0x00, sizeof(subSub));
+
+    if(MainAndSubCommandParsing(inputCmd, subMain, subSub) == 1)
+    {
+        if(strcmp(subMain, "test") == 0)
+        {
+            TiltSensorTrigger();
+            return;
+        }
+    }
+    printf("\r\n");
+    printf("Input cmd fail ------  super [tilt] [test]\r\n\r\n");
+}
+
+void SetStandbyTime(int time)
+{
+    if(time != 0)
+    {
+        ShmChargerInfo->Control.CustomizedInfo.StandbyTime = time;
+        printf("\r\n");
+        printf("Set standby time [%d] (s)\r\n\r\n", ShmChargerInfo->Control.CustomizedInfo.StandbyTime);
+    }
+    else
+    {
+        printf("\r\n");
+        printf("Unavailable value, standby time [%d] (s)\r\n\r\n", ShmChargerInfo->Control.CustomizedInfo.StandbyTime);
+    }
+}
+
+void StandbyTimeCmd(char *inputCmd)
+{
+    char subMain[MAX_SUB_CMD_LENGTH];
+    char subSub[MAX_SUB_CMD_LENGTH];
+
+    memset(subMain, 0x00, sizeof(subMain));
+    memset(subSub, 0x00, sizeof(subSub));
+
+    if(MainAndSubCommandParsing(inputCmd, subMain, subSub) == 1)
+    {
+        int _time = atoi(subMain);
+
+        SetStandbyTime(_time);
+        return;
+    }
+    printf("\r\n");
+    printf("Input cmd fail ------  super [standby] [value(seconds)]\r\n\r\n");
+}
+
+void DiagnosticsEnable(void)
+{
+    ShmChargerInfo->Control.Diagnostics.DiagnosticsType = DIAGNOSTICS_TYPE_ALL;
+    printf("\r\n");
+    printf("Dispenser Diagnostics Enable\r\n\r\n");
+}
+
+void DiagnosticsCmd(char *inputCmd)
+{
+    char subMain[MAX_SUB_CMD_LENGTH];
+    char subSub[MAX_SUB_CMD_LENGTH];
+
+    memset(subMain, 0x00, sizeof(subMain));
+    memset(subSub, 0x00, sizeof(subSub));
+
+    if(MainAndSubCommandParsing(inputCmd, subMain, subSub) == 1)
+    {
+        if(strcmp(subMain, "enable") == 0)
+        {
+            DiagnosticsEnable();
+            return;
+        }
+    }
+    printf("\r\n");
+    printf("Input cmd fail ------  super [diagnostics] [enable]\r\n\r\n");
+}
+
+void SuperMode(char *inputCmd, unsigned int opt)
+{
+    char subMain[MAX_SUB_CMD_LENGTH];
+    char subSub[MAX_SUB_CMD_LENGTH];
+
+    memset(subMain, 0x00, sizeof(subMain));
+    memset(subSub, 0x00, sizeof(subSub));
+
+    if(MainAndSubCommandParsing(inputCmd, subMain, subSub) >= 1)
+    {
+        if(strcmp(subMain, "customized") == 0)
+        {
+            SetCustomizedCmd(subSub);
+            return;
+        }
+
+        if(strcmp(subMain, "tilt") == 0)
+        {
+            TiltSensorCmd(subSub);
+            return;
+        }
+
+        if(strcmp(subMain, "standby") == 0)
+        {
+            StandbyTimeCmd(subSub);
+            return;
+        }
+
+        if(strcmp(subMain, "diagnostics") == 0)
+        {
+            DiagnosticsCmd(subSub);
+            return;
+        }
+    }
+    printf("\r\n");
+    printf("Input cmd fail ------  super [customized | tilt | standby | diagnostics] [...]\r\n\r\n");
+}
+
 int ShowPsuCount(void)
 {
     int line = 0;
@@ -5322,18 +5654,22 @@ int ShowPsuGroupInfo(int group)
 {
     if(ShmPsuData->PsuGroup[group].GroupPresentPsuQuantity > 0)
     {
-        printf("  G-%d    %2d  %4d.%d V  %4d.%d A  %4d kW   %4d A  %4d kW",
+        printf("  G-%d    %2d  %4d.%d V  %4d.%d A  %4d kW",
             group + 1,
             ShmPsuPosition->GroupLocationInfo[group].GroupPsuQuantity,
             (ShmPsuData->PsuGroup[group].GroupPresentOutputVoltage / 10),
             (ShmPsuData->PsuGroup[group].GroupPresentOutputVoltage % 10),
             (ShmPsuData->PsuGroup[group].GroupPresentOutputCurrent / 10),
             (ShmPsuData->PsuGroup[group].GroupPresentOutputCurrent % 10),
-            (ShmPsuData->PsuGroup[group].GroupPresentOutputPower / 10),
+            (ShmPsuData->PsuGroup[group].GroupPresentOutputPower / 10));
+
+        printf("   %4d V   %4d A   %4d A  %4d kW",
+            (ShmPsuGrouping->GroupOutput[group].GTargetVoltage / 10),
+            (ShmPsuGrouping->GroupOutput[group].GTargetCurrent / 10),
             (ShmPsuData->PsuGroup[group].GroupAvailableCurrent / 10),
             (ShmPsuData->PsuGroup[group].GroupAvailablePower / 10));
 
-        printf("                                                   |   %d%d%d%d  |   %d%d%d%d\r\n",
+        printf("                               |   %d%d%d%d  |   %d%d%d%d\r\n",
             ShmChargerInfo->PsuGrouping.GroupPsuStatus_OR[group].bits.Lock,
             ShmChargerInfo->PsuGrouping.GroupPsuStatus_OR[group].bits.Alarm,
             ShmChargerInfo->PsuGrouping.GroupPsuStatus_OR[group].bits.Fault,
@@ -5358,7 +5694,7 @@ int ShowSinglePsuInfo(int psu_index)
     group = ShmPsuPosition->PsuAddressInfo[psu_index].GroupNo;
     gIndex = ShmPsuPosition->PsuAddressInfo[psu_index].GIndex;
 
-    printf("  %2d     %2d  %4d.%d V  %4d.%d A  %4d kW   %4d A  %4d kW",
+    printf("  %2d     %2d  %4d.%d V  %4d.%d A  %4d kW                     %4d A  %4d kW",
         gIndex + 1,
         psu_index,
         (ShmPsuData->PsuGroup[group].PsuModule[gIndex].PresentOutputVoltage / 10),
@@ -5369,42 +5705,40 @@ int ShowSinglePsuInfo(int psu_index)
         (ShmPsuData->PsuGroup[group].PsuModule[gIndex].IAvailableCurrent / 10),
         (ShmPsuData->PsuGroup[group].PsuModule[gIndex].AvailablePower / 10));
 
-    int CriticalTemp1 = 0, CriticalTemp2 = 0, CriticalTemp3 = 0, InletTemp = 0, OutletTemp = 0, InletTemp_1 = 0, InletTemp_2 = 0;
-    CriticalTemp1 = (int)ShmPsuData->PsuGroup[group].PsuModule[gIndex].CriticalTemp1 - 60;
-    CriticalTemp2 = (int)ShmPsuData->PsuGroup[group].PsuModule[gIndex].CriticalTemp2 - 60;
-    CriticalTemp3 = (int)ShmPsuData->PsuGroup[group].PsuModule[gIndex].CriticalTemp3 - 60;
-    InletTemp = (int)ShmPsuData->PsuGroup[group].PsuModule[gIndex].InletTemp - 60;
-    OutletTemp = (int)ShmPsuData->PsuGroup[group].PsuModule[gIndex].OutletTemp - 60;
-    InletTemp_1 = (int)ShmPsuData->PsuGroup[group].PsuModule[gIndex].InletTemp_1 - 60;
-    InletTemp_2 = (int)ShmPsuData->PsuGroup[group].PsuModule[gIndex].InletTemp_2 - 60;
-
-    printf("   %4d    %4d / %4d  %4d / %4d   %4d / %4d",
-        CriticalTemp1, InletTemp, OutletTemp, InletTemp_1, InletTemp_2, CriticalTemp2, CriticalTemp3);
+    printf("   %3d.%d V   %3d.%d V   %3d.%d V",
+        (ShmPsuData->PsuGroup[group].PsuModule[gIndex].InputVoltageL1 / 10),
+        (ShmPsuData->PsuGroup[group].PsuModule[gIndex].InputVoltageL1 % 10),
+        (ShmPsuData->PsuGroup[group].PsuModule[gIndex].InputVoltageL2 / 10),
+        (ShmPsuData->PsuGroup[group].PsuModule[gIndex].InputVoltageL2 % 10),
+        (ShmPsuData->PsuGroup[group].PsuModule[gIndex].InputVoltageL3 / 10),
+        (ShmPsuData->PsuGroup[group].PsuModule[gIndex].InputVoltageL3 % 10));
 
-    printf("  |   %d%d%d%d\r\n",
+    printf(" |   %d%d%d%d",
         ShmPsuPosition->SinglePsuStatus[psu_index].bits.Lock,
         ShmPsuPosition->SinglePsuStatus[psu_index].bits.Alarm,
         ShmPsuPosition->SinglePsuStatus[psu_index].bits.Fault,
         ShmPsuPosition->SinglePsuStatus[psu_index].bits.Output);
 
+    printf("\r\n");
+
     return 1;
 }
 
-// Group  Psu   Out_Vol   Out_Cur  Out_Pow  Ava_Cur  Ava_Pow  Ambient   Liq_In_Out  DD_In 1 & 2  DD_Out 1 & 2   OR_LAFO  AND_LAFO
-//  G-X     4  XXXX.X V  XXXX.X A  XXXX kW   XXXX A  XXXX kW                                                   |   XXXX  |   XXXX
+// Group  Psu   Out_Vol   Out_Cur  Out_Pow  TargetV  TargetC  Ava_Cur  Ava_Pow  Ambient   Liq_In_Out  DD_In 1 & 2  DD_Out 1 & 2   OR_LAFO  AND_LAFO  InVol L1  InVol L2  InVol L3
+//  G-X     4  XXXX.X V  XXXX.X A  XXXX kW   XXXX V   XXXX A   XXXX A  XXXX kW                                                   |   XXXX  |   XXXX
 //  G-X     0     N/A        N/A      N/A      N/A      N/A
-//   X      0  XXXX.X V  XXXX.X A  XXXX kW   XXXX A  XXXX kW   XXXX    XXXX / XXXX  XXXX / XXXX   XXXX / XXXX  |   XXXX  |   XXXX
+//   X      0  XXXX.X V  XXXX.X A  XXXX kW   XXXX A  XXXX kW   XXXX    XXXX / XXXX  XXXX / XXXX   XXXX / XXXX  |   XXXX  |   XXXX   XXX.X V   XXX.X V   XXX.X V
 
-// Group  Out_Vol   Out_Cur  Out_Pow  Ava_Cur  Ava_Pow     Version  Ambient   Liq_In_Out  DD_In 1 & 2  DD_Out 1 & 2   OR_LAFO  AND_LAFO
-//  G-X  XXXX.X V  XXXX.X A  XXXX kW   XXXX A  XXXX kW,  Total: XX                                                   |   XXXX  |   XXXX
-//  G-X    N/A        N/A      N/A      N/A      N/A
-//   X   XXXX.X V  XXXX.X A  XXXX kW   XXXX A  XXXX kW  XXXXXXXXXX   XXXX    XXXX / XXXX  XXXX / XXXX   XXXX / XXXX  |   XXXX  |   XXXX
+// Group  Psu   Out_Vol   Out_Cur  Out_Pow  TargetV  TargetC  Ava_Cur  Ava_Pow  InVol L1  InVol L2  InVol L3  OR_LAFO  AND_LAFO
+//  G-X     4  XXXX.X V  XXXX.X A  XXXX kW   XXXX V   XXXX A   XXXX A  XXXX kW                               |   XXXX  |   XXXX
+//  G-X     0     N/A        N/A      N/A      N/A      N/A      N/A      N/A
+//   X      0  XXXX.X V  XXXX.X A  XXXX kW                     XXXX A  XXXX kW   XXX.X V   XXX.X V   XXX.X V |   XXXX  |   XXXX
 int ShowPsuInfo(void)
 {
-    int line = 2;
-    printf("                                                                      PFC  &  DD\r\n");
-    printf(" Group  Psu   Out_Vol   Out_Cur  Out_Pow  Ava_Cur  Ava_Pow  Ambient   Liq_In_Out  DD_In 1 & 2  DD_Out 1 & 2   OR_LAFO  AND_LAFO\r\n");
+    int line = 1;
 
+    //printf(" Group  Psu   Out_Vol   Out_Cur  Out_Pow  Ava_Cur  Ava_Pow  InVol L1  InVol L2  InVol L3  OR_LAFO  AND_LAFO\r\n");
+    printf(" Group  Psu   Out_Vol   Out_Cur  Out_Pow  TargetV  TargetC  Ava_Cur  Ava_Pow  InVol L1  InVol L2  InVol L3  OR_LAFO  AND_LAFO\r\n");
     for(int i = 0; i < CONNECTOR_QUANTITY; i++)
     {
         line += ShowPsuGroupInfo(i);
@@ -5420,6 +5754,70 @@ int ShowPsuInfo(void)
     return line;
 }
 
+int ShowSinglePsuTemperature(int psu_index)
+{
+    int group = 0, gIndex = 0;
+
+    group = ShmPsuPosition->PsuAddressInfo[psu_index].GroupNo;
+    gIndex = ShmPsuPosition->PsuAddressInfo[psu_index].GIndex;
+
+    int CriticalTemp1 = 0, CriticalTemp2 = 0, CriticalTemp3 = 0, InletTemp = 0, OutletTemp = 0, InletTemp_1 = 0, InletTemp_2 = 0;
+    CriticalTemp1 = (int)ShmPsuData->PsuGroup[group].PsuModule[gIndex].CriticalTemp1 - 60;
+    CriticalTemp2 = (int)ShmPsuData->PsuGroup[group].PsuModule[gIndex].CriticalTemp2 - 60;
+    CriticalTemp3 = (int)ShmPsuData->PsuGroup[group].PsuModule[gIndex].CriticalTemp3 - 60;
+    InletTemp = (int)ShmPsuData->PsuGroup[group].PsuModule[gIndex].InletTemp - 60;
+    OutletTemp = (int)ShmPsuData->PsuGroup[group].PsuModule[gIndex].OutletTemp - 60;
+    InletTemp_1 = (int)ShmPsuData->PsuGroup[group].PsuModule[gIndex].InletTemp_1 - 60;
+    InletTemp_2 = (int)ShmPsuData->PsuGroup[group].PsuModule[gIndex].InletTemp_2 - 60;
+
+    printf("   %d    %2d   %4d  %4d / %4d  %4d / %4d   %4d / %4d\r\n",
+        group, psu_index, CriticalTemp1, InletTemp, OutletTemp, InletTemp_1, InletTemp_2, CriticalTemp2, CriticalTemp3);
+
+    return 1;
+}
+
+//              PFC  &  DD
+// Group Psu   Ambi   Liq_In_Out  DD_In 1 & 2  DD_Out 1 & 2
+//   X    XX   XXXX  XXXX / XXXX  XXXX / XXXX   XXXX / XXXX
+int ShowPsuTemperature(void)
+{
+    int line = 2;
+    printf("                    PFC  &  DD\r\n");
+    printf(" Group Psu   Ambi   Liq_In_Out  DD_In 1 & 2  DD_Out 1 & 2\r\n");
+    for(int i = 0; i < MAX_GROUP_QUANTITY; i++)
+    {
+        if(ShmPsuData->PsuGroup[i].GroupPresentPsuQuantity > 0)
+        {
+            for(int j = 0; j < ShmPsuData->PsuGroup[i].GroupPresentPsuQuantity; j++)
+            {
+                int psu_index = ShmPsuPosition->GroupLocationInfo[i].PsuIndex[j];
+                line += ShowSinglePsuTemperature(psu_index);
+            }
+        }
+    }
+
+    return line;
+}
+
+void SetPsuIndication(int psuIndex)
+{
+    if(psuIndex >= MAX_PSU_MODULE_QUANTITY)
+    {
+        printf("psu index(%d) over range(%d)\r\n", psuIndex, MAX_PSU_MODULE_QUANTITY);
+        return;
+    }
+
+    if(ShmChargerInfo->Control.LibCtrl.bits.InfyPwrLib)
+    {
+        ShmPsuPosition->SingleInfyPwrState[psuIndex].InfyPwrStateFlag.bits.Indicated = true;
+        printf("Set Psu[%2d] Led Blinking\r\n", psuIndex);
+    }
+    if(ShmChargerInfo->Control.LibCtrl.bits.PhPwrLib)
+    {
+        printf("PhPwer not support this function\r\n");
+    }
+}
+
 void PsuCmd(char *inputCmd, unsigned int opt)
 {
     bool keepRun = false;
@@ -5438,9 +5836,9 @@ void PsuCmd(char *inputCmd, unsigned int opt)
     maxPara = 1;
     totalCnt = GetSubCommand(inputCmd);
 
-    if(totalCnt != maxPara)
+    if(totalCnt < maxPara)
     {
-        printf("Input cmd fail ------  psu [count | ver | cap | input | output | info]\r\n\r\n");
+        printf("Input cmd fail ------  psu [count | ver | cap | input | output | info | temp | indi]\r\n\r\n");
         return;
     }
 
@@ -5459,6 +5857,10 @@ void PsuCmd(char *inputCmd, unsigned int opt)
             {
                 reflashLine = ShowPsuInfo();
             }
+            else if(strcmp(&MultiSubCmd[0][0], "temp") == EQUAL)
+            {
+                reflashLine = ShowPsuTemperature();
+            }
             else if(strcmp(&MultiSubCmd[0][0], "count") == EQUAL)
             {
                 reflashLine = ShowPsuCount();
@@ -5479,9 +5881,24 @@ void PsuCmd(char *inputCmd, unsigned int opt)
             {
                 reflashLine = ShowPsuOutput();
             }
+            else if(strcmp(&MultiSubCmd[0][0], "indi") == EQUAL)
+            {
+                int psuIndex = 0;
+
+                if(totalCnt == 2)
+                {
+                    psuIndex = atoi(&MultiSubCmd[1][0]);
+                    SetPsuIndication(psuIndex);
+                }
+                else
+                {
+                    printf("Input cmd parsing fail ------  psu [indi] [index]\r\n");
+                }
+                keepRun = false;
+            }
             else
             {
-                printf("Input cmd parsing fail ------  psu [count | ver | cap | input | output | info]\r\n");
+                printf("Input cmd parsing fail ------  psu [count | ver | cap | input | output | info | temp | indi]\r\n");
                 keepRun = false;
             }
 
@@ -5502,7 +5919,7 @@ void PsuCmd(char *inputCmd, unsigned int opt)
     printf("\r\n");
 }
 
-int main(void)
+int main(int argc, char *argv[])
 {
     char newString[32][MAX_SUB_CMD_LENGTH];
     char inputString[MAX_SUB_CMD_LENGTH], normalCmd[MAX_SUB_CMD_LENGTH];
@@ -5537,12 +5954,30 @@ int main(void)
         memset(&newString[i], 0x00, 32);
     }
 
+    memset(inputString, 0x00, sizeof(inputString));
+    memset(normalCmd, 0x00, sizeof(normalCmd));
+
+    if(argc > 1)
+    {
+        for(int i = 0; i < argc - 1; i++)
+        {
+            strcat(inputString, argv[i + 1]);
+            if(i + 1 < argc - 1)
+            {
+                strcat(inputString, " ");
+            }
+        }
+    }
+
 	for(;;)
 	{
-        memset(inputString, 0x00, sizeof(inputString));
-        memset(normalCmd, 0x00, sizeof(normalCmd));
+	    if(argc == 1)
+	    {
+            memset(inputString, 0x00, sizeof(inputString));
+            memset(normalCmd, 0x00, sizeof(normalCmd));
+            get_char(inputString);
+	    }
 
-        get_char(inputString);
         cmdCnt = InputStringNormalize(inputString, normalCmd, &option);
         if(cmdCnt > 0)
         {
@@ -5772,9 +6207,9 @@ int main(void)
                 continue;
             }
         }
-        else if(strcmp(newString[0], "gdmd") == 0)
+        else if(strcmp(mainCmd, "gdmd") == 0)
         {
-            ShowGroupingDemand();
+            ShowGroupingDemand(subCmd, option);
         }
         else if(strcmp(mainCmd, "gunchg") == 0)
         {
@@ -5905,12 +6340,21 @@ int main(void)
         else if(strcmp(mainCmd, "occupancy") == 0)
         {
             ShowOccupancy(subCmd, option);
+        }
+        else if(strcmp(mainCmd, "super") == 0)
+        {
+            SuperMode(subCmd, option);
         }
 		else
 		{
 			printf ("%s\n", msg);
 		}
 		usleep(100000);
+
+        if(argc > 1)
+        {
+            break;
+        }
 	}
 
 	return 0;

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 632 - 40
EVSE/Projects/DO360/Apps/main.c


Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно