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

2022-04-27 / Wendell

Actions
1. [add] add shell customer code and logic
2. [add] disable dispenser when force charging via web api
3. [add] ctep function, default price, user price, receipt, consumption
4. [add] authorize id type, freevend idtag, evccid prefix
5. [add] add system id packet dispenser
6. [mod] modify qr code logic
7. [mod] improve reservation function

Files
1. As follow commit history

Image version : V2.01.XX.XXXX.XX
Wendell 2 жил өмнө
parent
commit
575c7b4cd5

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

@@ -7,6 +7,7 @@
 
 #include <stdlib.h>
 #include <stdio.h>
+#include <stdbool.h>
 #include <string.h>
 #include <stdarg.h>
 #include <time.h>
@@ -117,6 +118,32 @@ int StoreAuthLogMsg(const char *fmt, ...)
     return rc;
 }
 
+int StoreEvCommMsg(const char *fmt, ...)
+{
+    char Buf[4096+256];
+    char buffer[4096];
+    va_list args;
+    struct timeb  SeqEndTime;
+    struct tm *tm;
+
+    va_start(args, fmt);
+    int rc = vsnprintf(buffer, sizeof(buffer), fmt, args);
+    va_end(args);
+
+    memset(Buf,0,sizeof(Buf));
+    ftime(&SeqEndTime);
+    SeqEndTime.time = time(NULL);
+    tm=localtime(&SeqEndTime.time);
+
+    sprintf(Buf,"echo \'%04d-%02d-%02d %02d:%02d:%02d:%03d - %s\' >> /Storage/SystemLog/[%04d.%02d]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);
+    system(Buf);
+
+    return rc;
+}
+
 void GetClockTime(struct timespec *_now_time)
 {
     clock_gettime(CLOCK_MONOTONIC, _now_time);
@@ -209,3 +236,284 @@ int IsModelNameMatch_ForUpdate(char *model_1, char *model_2)
     }
     return NO;
 }
+
+int IsCabinetModelNameLegal(char *modelName)
+{
+    if(strlen(modelName) != MODELNAME_LENGTH || modelName[0] != 'D')
+    {
+        return false;
+    }
+
+    if(modelName[1] != 'O' && modelName[1] != 'B' && modelName[1] != 'K')
+    {
+        return false;
+    }
+
+    return true;
+}
+
+int IsSerialNumberLegal(char *sn)
+{
+    if(strlen(sn) != SERIAL_NUMBER_LENGTH)
+    {
+        return false;
+    }
+
+    return true;
+}
+
+int IsSystemIdLegal(char *systemId)
+{
+    if(strlen(systemId) > SYSTEM_ID_LENGTH)
+    {
+        return false;
+    }
+
+    return true;
+}
+
+char *strrpc(char *str, char *oldStr, char *newStr)
+{
+    char bstr[strlen(str)];
+    memset(bstr, 0x00, sizeof(bstr));
+
+    for(int i = 0; i < strlen(str); i++)
+    {
+        if(!strncmp(str+i, oldStr, strlen(oldStr)))
+        {
+            strcat(bstr, newStr);
+            i += strlen(oldStr) - 1;
+        }
+        else
+        {
+            strncat(bstr, str + i, 1);
+        }
+    }
+
+    strcpy(str,bstr);
+    return str;
+}
+
+// return the start position of the first occurrence
+int StringInStr(char *string, char *key)
+{
+    int startIndex = -1;
+    char *startPtr;
+
+    startPtr = strstr(string, key);
+    if(startPtr > 0)
+    {
+        startIndex = (int)startPtr - (int)string;
+    }
+
+    return startIndex;
+}
+
+int FindStringInStr(char *sourceString, char *key, char *findString)
+{
+    int len = 0;
+
+    char *findPtr = strstr(sourceString, key);
+    if(findPtr > 0)
+    {
+        len = StringInStr(findPtr, " ");
+
+        if(len > 0)
+        {
+            memcpy(findString, findPtr, len);
+            findString[len] = '\0';
+        }
+    }
+    return len;
+}
+
+// return quantity of number
+int Trim_String(char *string , int len)
+{
+    bool find = false;
+    int quantity = 0;
+
+    for(int i = 0 ; i < len; i++)
+    {
+        if(!(string[i] == '.' || (string[i] >= '0' && string[i] <= '9')))
+        {
+            if(find)
+            {
+                string[i] = ' ';
+            }
+            else
+            {
+                strncpy(&string[i], &string[i + 1], len - i);
+                i -= 1;
+                len -= 1;
+            }
+            find = false;
+        }
+        else
+        {
+            if(!find)
+            {
+                quantity++;
+            }
+            find = true;
+        }
+    }
+    string[len] = '\0';
+
+    return quantity;
+}
+
+int Split(char **array, char *strSource, const char *key)
+{
+    int quantity = 0;
+    char *ptrSave, *ptrToken;
+
+    ptrToken = strtok_r(strSource, key, &ptrSave);
+    while(ptrToken != NULL)
+    {
+        *array++ = ptrToken;
+        quantity++;
+        ptrToken = strtok_r(NULL, key, &ptrSave);
+    }
+
+    return quantity;
+}
+
+float PriceParsing(char *PriceString, char *ParseKey, char *SplitKey)
+{
+    char strSource[1024];
+    char *splitStringList[128];
+    int splitQuantity = 0;
+    float fee = 0;
+
+    memset(strSource, 0x00, sizeof(strSource));
+    strcpy(strSource, PriceString);
+
+    if(strlen(ParseKey) > 0)
+    {
+        splitQuantity = Split(splitStringList, strSource, SplitKey);
+
+        for(int i = 0; (i < splitQuantity && i < 128); i++)
+        {
+            if(strstr(splitStringList[i], ParseKey) > 0)
+            {
+                Trim_String(splitStringList[i], strlen(splitStringList[i]));
+                fee = atof(splitStringList[i]);
+                break;
+            }
+        }
+    }
+    else
+    {
+        Trim_String(PriceString, strlen(PriceString));
+        fee = atof(PriceString);
+    }
+
+    return fee;
+}
+
+// Shell Default & User Price Parsing
+// input: priceString
+// output: resultPrice
+char *ShellPriceParsing(char *priceString, char *resultPrice)
+{
+    char strSource[1024];
+
+    memset(strSource, 0x00, sizeof(strSource));
+    strcpy(strSource, priceString);
+
+    strcpy(strSource, strrpc(strSource,"\n", " "));
+    strcpy(resultPrice, strSource);
+    return resultPrice;
+}
+
+// Shell RunningCost Parsing
+float ShellRunningCostParsing(char *runningCostString)
+{
+    int splitCnt = 0;
+    float energy = 0, fee = 0;
+    int connector = 0;
+    char *splitStringList[128];
+    char strSource[1024];
+    int trimCnt = 0;
+
+    memset(strSource, 0x00, sizeof(strSource));
+    strcpy(strSource, runningCostString);
+    splitCnt = Split(splitStringList, strSource, "\n");
+
+    for(int i = 0; i < splitCnt; i++)
+    {
+        if(strstr(splitStringList[i], "Current Total") > 0)
+        {
+            trimCnt = Trim_String(splitStringList[i], strlen(splitStringList[i]));
+            if(trimCnt == 3)
+            {
+                sscanf(splitStringList[i], "%f %f %d", &energy, &fee, &connector);
+            }
+            break;
+        }
+    }
+
+    return fee;
+}
+
+// Shell FinalCost
+float ShellFinalCostParsing(char *finalCostString)
+{
+    int splitCnt = 0;
+    float fee = 0;
+    char *splitStringList[128];
+    char strSource[1024];
+
+    memset(strSource, 0x00, sizeof(strSource));
+    strcpy(strSource, finalCostString);
+    splitCnt = Split(splitStringList, strSource, "\n");
+
+    for(int i = 0; i < splitCnt; i++)
+    {
+        if(strstr(splitStringList[i], "Total") > 0)
+        {
+            for(int j = i + 1; j < splitCnt; j++)
+            {
+                if(strstr(splitStringList[j], "Cost:") > 0)
+                {
+                    Trim_String(splitStringList[j], strlen(splitStringList[j]));
+                    fee = atof(splitStringList[j]);
+                    break;
+                }
+            }
+            break;
+        }
+    }
+
+    return fee;
+}
+
+int GetShellReceiptInfo(char *finalCostString, char *receiptInfo)
+{
+    int splitCnt = 0;
+    int length = 0;
+    char *splitStringList[128];
+    char strSource[1024];
+
+    memset(strSource, 0x00, sizeof(strSource));
+    strcpy(strSource, finalCostString);
+    splitCnt = Split(splitStringList, strSource, "\n");
+
+    for(int i = 0; i < splitCnt; i++)
+    {
+        if(strstr(splitStringList[i], "Total") > 0)
+        {
+            for(int j = i + 1; j < splitCnt; j++)
+            {
+                if(strstr(splitStringList[j], "Receipt:") > 0)
+                {
+                    length = FindStringInStr(splitStringList[j], "http", receiptInfo);
+                }
+            }
+            break;
+        }
+    }
+
+    return length;
+}

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

@@ -24,6 +24,8 @@
 #define EQUAL                       0
 
 #define MODELNAME_LENGTH            14
+#define SERIAL_NUMBER_LENGTH        11
+#define SYSTEM_ID_LENGTH            64
 
 #define LOG_INFO(format, args...) StoreSysLogMsg("[%s:%4d][%s][Info] "format, (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__), __LINE__, __FUNCTION__, ##args)
 #define LOG_WARN(format, args...) StoreSysLogMsg("[%s:%4d][%s][Warn] "format, (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__), __LINE__, __FUNCTION__, ##args)
@@ -32,6 +34,7 @@
 #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 DB_FILE                     "/Storage/ChargeLog/localCgargingRecord.db"
 #define NETWORK_DB_FILE             "/Storage/EventLog/Eventlog.db"
@@ -40,6 +43,7 @@ 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, ...);
 void GetClockTime(struct timespec *_now_time);
 unsigned long GetTimeoutValue(struct timespec _start_time);
 unsigned long GetSecTimeoutValue(struct timespec _start_time);
@@ -47,5 +51,20 @@ int StatusCodeCompose(char *oriCode, char *newCode);
 void getNowDatetime(unsigned char *data);
 
 int IsModelNameMatch_ForUpdate(char *model_1, char *model_2);
+int IsCabinetModelNameLegal(char *modelName);
+int IsSerialNumberLegal(char *sn);
+int IsSystemIdLegal(char *systemId);
+
+char *strrpc(char *str, char *oldStr, char *newStr);
+int StringInStr(char *string , char *key);
+int FindStringInStr(char *sourceString, char *key, char *findString);
+int Trim_String(char *string , int len);
+int Split(char **array, char *strSource, const char *key);
+float PriceParsing(char *PriceString, char *ParseKey, char *SplitKey);
+
+char *ShellPriceParsing(char *priceString, char *resultPrice);
+float ShellRunningCostParsing(char *runningCostString);
+float ShellFinalCostParsing(char *finalCostString);
+int GetShellReceiptInfo(char *finalCostString, char *receiptInfo);
 
 #endif /* COMMON_H_ */

+ 89 - 5
EVSE/Projects/DO360/Apps/Config.h

@@ -351,7 +351,7 @@ enum _CUSTOMER_CODE
     _CUSTOMER_CODE_E4U          = 2,
     _CUSTOMER_CODE_UCar         = 3,
     _CUSTOMER_CODE_TCC          = 4,
-    _CUSTOMER_CODE_Oil          = 5,
+    _CUSTOMER_CODE_Shell        = 5,
 };
 
 #define STR_CABINET_ROLE_NONE       "Single"
@@ -385,7 +385,11 @@ typedef union
         unsigned int Wifi4gResetEnable:1;           // 0: wifi/4g reset io disable, 1: wifi/4g reset io enable
         unsigned int PsuInit:1;                     // 0: no effect,                1: psu is initialized
         unsigned int Enable6ParallelRelay:1;        // 0: no effect,                1: enable 6 parallel relay
-        unsigned int res:17;
+        unsigned int WriteFlashEnable:1;            // 0: no effect,                1: flash content has changed
+        unsigned int WriteFlashBusy:1;              // 0: no effect,                1: flash is writing
+        unsigned int WriteFlashImmediately:1;       // 0: no effect,                1: write flash immediately
+        unsigned int WriteFlashAndReset:1;          // 0: no effect,                1: write flash and soft reset
+        unsigned int res:13;
     }bits;
 }SystemControl;
 
@@ -416,6 +420,84 @@ typedef union
     }bits;
 }DebugControl;
 
+#define MAX_EVCOMM_DEBUG_LEN            4
+typedef union
+{
+    unsigned int DebugVal[MAX_EVCOMM_DEBUG_LEN];
+    struct
+    {
+        // DebugVal[0]
+        unsigned int Reg_All:1;
+        unsigned int Reg_ModelName:1;
+        unsigned int Reg_ConnectorID:1;
+        unsigned int Reg_PowerCabinetStatus:1;
+        unsigned int Reg_DispenserStatus:1;
+        unsigned int Reg_ChargingCapability:1;
+        unsigned int Reg_ChargingTarget:1;
+        unsigned int Reg_SoftwareUpdate:1;
+        unsigned int Reg_PlugInStatus:1;
+        unsigned int Reg_ConnectorState:1;
+        unsigned int Reg_UserID:1;
+        unsigned int Reg_Charging_Permission:1;
+        unsigned int Reg_MiscControl:1;
+        unsigned int Reg_DispenserCsuVersion:1;
+        unsigned int Reg_DispenserOtherVersion:1;
+        unsigned int Reg_ChargingInfo:1;
+        unsigned int Reg_QRCodeDate:1;
+        unsigned int Reg_WaitPlugIn:1;
+        unsigned int Reg_GroundFaultDetection:1;
+        unsigned int Reg_Cabinet_CSU_Version:1;
+        unsigned int Reg_Cabinet_Other_Version:1;
+        unsigned int Reg_PsuQuantity:1;
+        unsigned int Reg_PsuVersion:1;
+        unsigned int Reg_Reservation:1;
+        unsigned int Reg_Dispenser_Request:1;
+        unsigned int Reg_RemoteStartNoIDState:1;
+        unsigned int Reg_RefundAmount:1;
+        unsigned int Reg_PrepaymentInfo:1;
+        unsigned int Reg_PaymentFailReason:1;
+        unsigned int Reg_ConnectorQRCode:1;
+        unsigned int Reg_StationInfo:1;
+        unsigned int Reg_DeductResult:1;
+        // DebugVal[1]
+        unsigned int Reg_CabinetSystemID:1;
+        unsigned int Reg_DefaultPriceString:1;
+        unsigned int Reg_UserPriceString:1;
+        unsigned int Reg_Receipt:1;
+        unsigned int Reg_PowerConsumption:1;
+        unsigned int res:27;
+        // DebugVal[2]
+        unsigned int DebugVal5:32;
+        // DebugVal[3]
+        unsigned int DebugVal6:32;
+    }bits;
+}DebugEvCommMsgFlag;
+
+typedef union
+{
+    unsigned int DebugVal;
+    struct
+    {
+        // DebugVal[0]
+        unsigned int MsgId_None:1;
+        unsigned int MsgId_Gun_1:1;
+        unsigned int MsgId_Gun_2:1;
+        unsigned int MsgId_Gun_3:1;
+        unsigned int MsgId_Gun_4:1;
+        unsigned int MsgId_Gun_5:1;
+        unsigned int MsgId_Gun_6:1;
+        unsigned int MsgId_Gun_7:1;
+        unsigned int MsgId_Gun_8:1;
+        unsigned int res:23;
+    }bits;
+}DebugEvCommIdFlag;
+
+typedef struct
+{
+    DebugEvCommMsgFlag MsgFlag;
+    DebugEvCommIdFlag IdFlag;
+}EvCommCtrlInfo;
+
 typedef union
 {
     unsigned int CtrlValue;
@@ -600,6 +682,7 @@ typedef struct
     UpdateControl   UpdateCtrl;
     TestControl     TestCtrl;
     DebugControl    DebugCtrl;
+    EvCommCtrlInfo  EvCommCtrl;
     PrimaryControl  PrimaryCtrl;
     RelayControl    RelayCtrl;
     FanControl      FanCtrl;
@@ -1131,9 +1214,10 @@ enum DeductResult
 
 typedef struct
 {
-    char DefaultPriceString[512];                   // default price string
-    char UserPriceString[MAX_GUN_QUANTITY][512];    // connector user price string
-    char ReceiptUrl[MAX_GUN_QUANTITY][512];         // connector receipt url
+    char DefaultPriceString[512];                       // default price string
+    char DispenserPriceString[MAX_GUN_QUANTITY][512];   // dispenser user price string
+    char UserPriceString[MAX_GUN_QUANTITY][512];        // connector user price string
+    char ReceiptUrl[MAX_GUN_QUANTITY][512];             // connector receipt url
 }PriceReceiptInfoData;
 
 typedef enum

+ 2 - 2
EVSE/Projects/DO360/Apps/Makefile

@@ -97,8 +97,8 @@ PsuCommTask:
 	
 ReadCmdlineTask:
 	rm -f ReadCmdline; 
-	$(CC) -D $(Project) -includeConfig.h -O0 -g3 -Wall -c -fmessage-length=0 -o ReadCmdline.o ReadCmdline.c
-	$(CC) -o ReadCmdline ReadCmdline.o Common.o -lrt
+	$(CC) -D $(Project) -includeConfig.h -include../../../Modularization/Module_RatedCurrent.h -O0 -g3 -Wall -c -fmessage-length=0 -o ReadCmdline.o ReadCmdline.c
+	$(CC) -o ReadCmdline ReadCmdline.o Common.o ../../../Modularization/libModule_RatedCurrent.a -lrt -lm
 	cp -f ReadCmdline ../Images/root
 
 UnsafetyOutputTool:

+ 118 - 13
EVSE/Projects/DO360/Apps/Module_Authorize.c

@@ -47,7 +47,7 @@
 #define AUTHORIZE_INTERVAL              100000          // unit: 1us
 #define AUTHORIZE_WAIT_OCPP_TIMEOUT     30              // unit: 1s
 #define SYS_AUTHORIZE_COMP_TIMEOUT      1               // unit: 1s
-#define AUTH_TIME_OFFSET_TIME           3               // unit: 1s
+#define AUTH_TIME_OFFSET_TIME           6               // unit: 1s
 #define AUTO_START_CHARGING             "AutoStartCharging"
 #define DEFAULT_SN                      "NeedSetupSN"
 
@@ -61,6 +61,8 @@ struct timespec                     _SysAuth_Time;
 struct timespec                     _GunAuth_Time[GENERAL_GUN_QUANTITY];
 struct timespec                     _DispenserAuth_Time[GENERAL_GUN_QUANTITY];
 
+bool _isAutoStart = false;
+unsigned char _idType = _Type_ISO14443;
 unsigned char _preSysAuthStatus = 0;
 unsigned char _preGunAuthStatus[GENERAL_GUN_QUANTITY];
 unsigned char _preDispenserAuthStatus[GENERAL_GUN_QUANTITY];
@@ -254,6 +256,33 @@ bool Is_Ocpp_Authorize_Status(char *status)
     return false;
 }
 
+//===============================================
+// Ocpp >Authorize.idToken.type
+//===============================================
+void Set_Ocpp_AuthorizeIdType(unsigned char type)
+{
+    char *str_IdType[] = {
+        STR_ID_TYPE_CENTRAL,
+        STR_ID_TYPE_EMAID,
+        STR_ID_TYPE_ISO14443,
+        STR_ID_TYPE_ISO15693,
+        STR_ID_TYPE_KEYCODE,
+        STR_ID_TYPE_LOCAL,
+        STR_ID_TYPE_MAC_ADDRESS,
+        STR_ID_TYPE_NO_AUTHORIZATION};
+
+    if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16)
+    {
+
+    }
+    if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20)
+    {
+        strncpy((char *)ShmOCPP20Data->Authorize.idToken.type, str_IdType[type], sizeof(ShmOCPP20Data->Authorize.idToken.type));
+        ShmOCPP20Data->Authorize.idToken.type[sizeof(ShmOCPP20Data->Authorize.idToken.type) - 1] = '\0';
+    }
+}
+
+
 //===============================================
 // Ocpp Reserve Now
 //===============================================
@@ -282,15 +311,79 @@ bool Is_Ocpp_ReserveNowIdTag(uint8_t gun_index, char *authIdTag)
     return strcmp(ReserveIdTag, authIdTag) == EQUAL ? true : false;
 }
 
+//===============================================
+// Ocpp Freevend Idtag
+//===============================================
+bool Get_Ocpp_FreevendIdtag(char *idTag)
+{
+    if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16)
+    {
+        strcpy(idTag, (char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[FreeVendIdtag].ItemData);
+        return true;
+    }
+    if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20)
+    {
+        strcpy(idTag, (char *)ShmOCPP20Data->ControllerComponentVariable[ChargingStation_FreeVendIdtag].variableAttribute[0].value);
+        return true;
+    }
+    strcpy(idTag, "");
+    return false;
+}
+
+//===============================================
+// Ocpp EVCCID_PREFIX
+//===============================================
+void Get_Ocpp_EVCCID_Prefix(char *prefix)
+{
+    if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16)
+    {
+        strcpy(prefix, (char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[EVCCID_PREFIX].ItemData);
+        return;
+    }
+    if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20)
+    {
+        strcpy(prefix, "");
+        return;
+    }
+    strcpy(prefix, "");
+}
+
 void SetAuthorize(AuthorizingInfoData *AuthInfo, unsigned char type)
 {
+    if(AuthInfo->AuthIdType == _Type_MacAddress)
+    {
+        char prefix[501];
+        char evccid[501 + 32];
+        memset(prefix, 0x00, sizeof(prefix));
+        memset(evccid, 0x00, sizeof(evccid));
+
+        Get_Ocpp_EVCCID_Prefix(prefix);
+        sprintf(evccid, "%s%s", prefix, (char *)&AuthInfo->AuthId);
+        AUTH_INFO("*********** EVCCID [%s] ***********", evccid);
+    }
+    else if(strcmp((char *)&AuthInfo->AuthId, AUTO_START_CHARGING) == EQUAL)
+    {
+        Get_Ocpp_FreevendIdtag((char *)&AuthInfo->AuthId);
+        _isAutoStart = true;
+        AUTH_INFO("*********** FreevendId [%s] ***********", (char *)&AuthInfo->AuthId);
+    }
+
     memcpy(ShmSysConfigAndInfo->SysConfig.UserId, AuthInfo->AuthId, 32);
 
     AuthInfo->AuthStatus = _AuthorizeStatus_Busy;
     AuthInfo->AuthType = type;
+    if(type == _AuthType_RemoteStart)
+    {
+        AuthInfo->AuthIdType = _Type_Central;
+    }
+    else if(_isAutoStart)
+    {
+        AuthInfo->AuthIdType = _Type_NoAuthorization;
+    }
 
     ShmSysConfigAndInfo->SysInfo.AuthorizedTarget = AuthInfo->AuthTarget;
     ShmSysConfigAndInfo->SysInfo.AuthorizedType = type;
+    _idType = AuthInfo->AuthIdType;
 }
 
 void CheckAutoStartChargingToSNToOcpp(void)
@@ -411,16 +504,6 @@ unsigned char Chk_OfflinePolicy(char *idTag)
             }
         }
 
-        if(find == false)
-        {
-            if((ShmChargerInfo->AuthInfo.AuthMode.bits.AutoStartEnable || ShmSysConfigAndInfo->SysConfig.AuthorisationMode == AUTH_MODE_DISABLE) &&
-                strcmp((char *)ShmSysConfigAndInfo->SysConfig.UserId, AUTO_START_CHARGING) == EQUAL)
-            {
-                find = true;
-                AUTH_INFO("******** [Auto Start Charging] ********");
-            }
-        }
-
         AUTH_INFO("*********** Local Authorization %s ***********", find ? "OK" : "NG");
 
         if(find)
@@ -520,6 +603,8 @@ int main(void)
     }
 
     InitialConnector();
+    _isAutoStart = false;
+    _idType = _Type_ISO14443;
 
     while(1)
     {
@@ -535,6 +620,8 @@ int main(void)
                     _preSysAuthStatus = ShmSysConfigAndInfo->SysInfo.AuthorizedStatus;
                     _authResult = _AuthResult_None;
                     _autoSelection = false;
+                    _isAutoStart = false;
+                    _idType = _Type_ISO14443;
                 }
 
                 if(IsRemoteStartRequest(&_connector))
@@ -595,7 +682,24 @@ int main(void)
                     }
                     else
                     {
-                        _authResult = Chk_OfflinePolicy((char *)ShmSysConfigAndInfo->SysConfig.UserId);
+                        if(_isAutoStart)
+                        {
+                            if(ShmChargerInfo->AuthInfo.AuthMode.bits.AutoStartEnable ||
+                                ShmSysConfigAndInfo->SysConfig.AuthorisationMode == AUTH_MODE_DISABLE)
+                            {
+                                _authResult = _AuthResult_Valid;
+                                AUTH_INFO("******** [Auto Start Charging Enable] ********");
+                            }
+                            else
+                            {
+                                _authResult = _AuthResult_Invalid;
+                                AUTH_INFO("******** [Auto Start Charging Result Fail] ********");
+                            }
+                        }
+                        else
+                        {
+                            _authResult = Chk_OfflinePolicy((char *)ShmSysConfigAndInfo->SysConfig.UserId);
+                        }
                         ShmSysConfigAndInfo->SysInfo.AuthorizedStatus = _AuthorizeStatus_Done;
                         _keepRun = true;
                         break;
@@ -604,7 +708,8 @@ int main(void)
 
                 if(_needOcppAuthorize)
                 {
-                    CheckAutoStartChargingToSNToOcpp();
+                    //CheckAutoStartChargingToSNToOcpp();
+                    Set_Ocpp_AuthorizeIdType(_idType);
                     Set_Ocpp_AuthorizeReq();
                     AUTH_INFO("*********** Set OPCC AuthorizeReq ***********");
                     ShmSysConfigAndInfo->SysInfo.AuthorizedStatus = _AuthorizeStatus_Busy;

+ 437 - 41
EVSE/Projects/DO360/Apps/Module_EvComm.c

@@ -71,6 +71,72 @@ void ShowSocketData(struct PACKET_STRUCTURE *packet)
 	printf("\n");
 }
 
+void CheckEvRxCommMsg(struct PACKET_STRUCTURE *packet)
+{
+    if(ShmChargerInfo->Control.DebugCtrl.bits.MsgEvComm)
+    {
+        int regValCnt = 0, regBitCnt = 0;
+
+        regValCnt = packet->Payload.reg / 32;
+        regBitCnt = packet->Payload.reg % 32;
+
+        if(((ShmChargerInfo->Control.EvCommCtrl.MsgFlag.DebugVal[regValCnt] & (1 << regBitCnt)) || ShmChargerInfo->Control.EvCommCtrl.MsgFlag.bits.Reg_All) &&
+            ((ShmChargerInfo->Control.EvCommCtrl.IdFlag.DebugVal & (1 << packet->Header.id)) || ShmChargerInfo->Control.EvCommCtrl.IdFlag.DebugVal == 0))
+        {
+            int len = 0;
+            char msg[1024];
+
+            sprintf(msg, "Rx: SE: %02X, ID: %02X, OP: %d, Len: %d, Reg: %02X",
+                packet->Header.se, packet->Header.id, packet->Header.op, packet->Header.len, packet->Payload.reg);
+
+            if(packet->Header.len > 1)
+            {
+                len = strlen(msg);
+                sprintf(&msg[len], ", Data:");
+                for(int i = 0; i < packet->Header.len - 1; i++)
+                {
+                    len = strlen(msg);
+                    sprintf(&msg[len], " %02X", packet->Payload.data[i]);
+                }
+            }
+            EvMsg_INFO("%s", msg);
+        }
+    }
+}
+
+void CheckTvRxCommMsg(struct PACKET_STRUCTURE *packet)
+{
+    if(ShmChargerInfo->Control.DebugCtrl.bits.MsgEvComm)
+    {
+        int regValCnt = 0, regBitCnt = 0;
+
+        regValCnt = packet->Payload.reg / 32;
+        regBitCnt = packet->Payload.reg % 32;
+
+        if(((ShmChargerInfo->Control.EvCommCtrl.MsgFlag.DebugVal[regValCnt] & (1 << regBitCnt)) || ShmChargerInfo->Control.EvCommCtrl.MsgFlag.bits.Reg_All) &&
+            ((ShmChargerInfo->Control.EvCommCtrl.IdFlag.DebugVal & (1 << packet->Header.id)) || ShmChargerInfo->Control.EvCommCtrl.IdFlag.DebugVal == 0))
+        {
+            int len = 0;
+            char msg[1024];
+
+            sprintf(msg, "Tx: SE: %02X, ID: %02X, OP: %d, Len: %d, Reg: %02X",
+                packet->Header.se, packet->Header.id, packet->Header.op, packet->Header.len, packet->Payload.reg);
+
+            if(packet->Header.len > 1)
+            {
+                len = strlen(msg);
+                sprintf(&msg[len], ", Data:");
+                for(int i = 0; i < packet->Header.len - 1; i++)
+                {
+                    len = strlen(msg);
+                    sprintf(&msg[len], " %02X", packet->Payload.data[i]);
+                }
+            }
+            EvMsg_INFO("%s", msg);
+        }
+    }
+}
+
 //==========================================
 // Init all share memory
 //==========================================
@@ -833,6 +899,8 @@ void SendPacket(int socket, struct PACKET_STRUCTURE *packet)
 {
     //ShowSocketData(packet);
     send(socket, packet, packet->Header.len + 4, 0);
+
+    CheckTvRxCommMsg(packet);
 }
 
 void ModelNameResponse(int socket, struct PACKET_STRUCTURE *packet, unsigned char result)
@@ -1111,9 +1179,10 @@ void ChargingCapabilityResponse(int socket, struct PACKET_STRUCTURE *packet)
 	struct PACKET_STRUCTURE sendBuffer;
 	unsigned short voltage = 0, current = 0, power = 0;
 	unsigned char currency = 0;
-	float fPrice = 0, fCost = 0, fBalance = 0, fDiscount = 0;
+	float fPrice = 0, fCost = 0, fBalance = 0, fDiscount = 0, fEnergyCost = 0, fParkingFee = 0;
 	unsigned int lPrice = 0, lCost = 0, lBalance = 0, lDiscount = 0;
 	int transaction = 0;
+	int energyCost = 0, parkingFee = 0;
 
 	memset(&sendBuffer, 0x00, sizeof(sendBuffer));
 	voltage = ShmSysConfigAndInfo->SysInfo.ConnectorInfo[packet->Header.id - 1].GeneralChargingData.MaximumChargingVoltage;
@@ -1132,17 +1201,21 @@ void ChargingCapabilityResponse(int socket, struct PACKET_STRUCTURE *packet)
 	fBalance = ShmSysConfigAndInfo->SysInfo.ConnectorInfo[packet->Header.id - 1].AccountBalance;
 	transaction = ShmChargerInfo->UserTransaction[packet->Header.id - 1].TransactionId;
 	fDiscount = ShmSysConfigAndInfo->SysInfo.ConnectorInfo[packet->Header.id - 1].CostDiscount;
+    fEnergyCost = ShmSysConfigAndInfo->SysInfo.ConnectorInfo[packet->Header.id - 1].EnergyCost;
+    fParkingFee = ShmSysConfigAndInfo->SysInfo.ConnectorInfo[packet->Header.id - 1].ParkingFee;
 
 	lPrice = (unsigned int)(fPrice * 100);
 	lCost = (unsigned int)(fCost * 100);
 	lBalance = (int)(fBalance * 100);
 	lDiscount = (int)(fDiscount * 100);
+	energyCost = fEnergyCost >= 0 ? (int)(fEnergyCost * 100) : -1;
+	parkingFee = fParkingFee >= 0 ? (int)(fParkingFee * 100) : -1;
 
 	if((ConnectorCapability[packet->Header.id - 1].MaxOuputVoltage / 10) != (voltage / 10) ||
         (ConnectorCapability[packet->Header.id - 1].MaxOuputCurrent / 10) != (current / 10) ||
         (ConnectorCapability[packet->Header.id - 1].MaxOuputPower / 10) != (power / 10))
 	{
-        LOG_INFO("Connector %d Capability Voltage: %4d.%d V, Current: %3d.%d A, Power: %d kW", packet->Header.id,
+        LOG_INFO("Gun %d Capability Voltage: %4d.%d V, Current: %3d.%d A, Power: %d kW", packet->Header.id,
             (voltage / 10), (voltage % 10), (current / 10), (current % 10), (power / 10));
 	}
 
@@ -1155,7 +1228,7 @@ void ChargingCapabilityResponse(int socket, struct PACKET_STRUCTURE *packet)
 	    }
 	    else
 	    {
-	        LOG_INFO("Connector %d unknown currency: %d", packet->Header.id, (int)(currency));
+	        LOG_INFO("Gun %d unknown currency: %d", packet->Header.id, (int)(currency));
 	        memcpy(ConnectorCapability[packet->Header.id - 1].CurrencyString, "???", 3);
 	    }
 	}
@@ -1163,16 +1236,18 @@ void ChargingCapabilityResponse(int socket, struct PACKET_STRUCTURE *packet)
 	if(ConnectorCapability[packet->Header.id - 1].Currency != currency ||
         ConnectorCapability[packet->Header.id - 1].UserPrice != lPrice ||
         ConnectorCapability[packet->Header.id - 1].TotalCost != lCost ||
-        ConnectorCapability[packet->Header.id - 1].TransactionId != transaction)
+        ConnectorCapability[packet->Header.id - 1].TransactionId != transaction ||
+        ConnectorCapability[packet->Header.id - 1].EnergyCost != energyCost ||
+        ConnectorCapability[packet->Header.id - 1].ParkingFee != parkingFee)
 	{
-	    LOG_INFO("Connector %d TransactionId: %d UserPrice: %6.2f, Cost: %.2f [%s]",
-            packet->Header.id, transaction, fPrice, fCost, ConnectorCapability[packet->Header.id - 1].CurrencyString);
+	    LOG_INFO("Gun %d TxId: %d UserPrice: %6.2f, Cost: %.2f, EnergyCost: %.2f, ParkingFee: %.2f [%s]",
+            packet->Header.id, transaction, fPrice, fCost, fEnergyCost, fParkingFee, ConnectorCapability[packet->Header.id - 1].CurrencyString);
 	}
 
     if(ConnectorCapability[packet->Header.id - 1].AccountBalance != lBalance ||
         ConnectorCapability[packet->Header.id - 1].CostDiscount != lDiscount)
     {
-        LOG_INFO("Connector %d TransactionId: %d Account: %8.2f, Discount: %.2f [%s]",
+        LOG_INFO("Gun %d TxId: %d Account: %8.2f, Discount: %.2f [%s]",
             packet->Header.id, transaction, fBalance, fDiscount, ConnectorCapability[packet->Header.id - 1].CurrencyString);
     }
 
@@ -1185,6 +1260,8 @@ void ChargingCapabilityResponse(int socket, struct PACKET_STRUCTURE *packet)
 	ConnectorCapability[packet->Header.id - 1].AccountBalance = lBalance;
 	ConnectorCapability[packet->Header.id - 1].CostDiscount = lDiscount;
 	ConnectorCapability[packet->Header.id - 1].TransactionId = transaction;
+    ConnectorCapability[packet->Header.id - 1].EnergyCost = energyCost;
+    ConnectorCapability[packet->Header.id - 1].ParkingFee = parkingFee;
 
     ShmSysConfigAndInfo->SysInfo.ConnectorInfo[packet->Header.id - 1].CapabilityVoltage = voltage;
     ShmSysConfigAndInfo->SysInfo.ConnectorInfo[packet->Header.id - 1].CapabilityCurrent = current;
@@ -1193,7 +1270,7 @@ void ChargingCapabilityResponse(int socket, struct PACKET_STRUCTURE *packet)
 	sendBuffer.Header.se = packet->Header.se;
 	sendBuffer.Header.id = packet->Header.id;
 	sendBuffer.Header.op = _Header_Response;
-	sendBuffer.Header.len = 29;
+	sendBuffer.Header.len = 37;
 	sendBuffer.Payload.reg = _Reg_Charging_Capability;
 	sendBuffer.Payload.data[0] = _R_OK;
 	sendBuffer.Payload.data[1] = ((voltage >> 8) & 0xFF);
@@ -1223,6 +1300,14 @@ void ChargingCapabilityResponse(int socket, struct PACKET_STRUCTURE *packet)
     sendBuffer.Payload.data[25] = ((transaction >> 16) & 0xFF);
     sendBuffer.Payload.data[26] = ((transaction >> 8) & 0xFF);
     sendBuffer.Payload.data[27] = (transaction & 0xFF);
+    sendBuffer.Payload.data[28] = ((energyCost >> 24) & 0xFF);
+    sendBuffer.Payload.data[29] = ((energyCost >> 16) & 0xFF);
+    sendBuffer.Payload.data[30] = ((energyCost >> 8) & 0xFF);
+    sendBuffer.Payload.data[31] = (energyCost & 0xFF);
+    sendBuffer.Payload.data[32] = ((parkingFee >> 24) & 0xFF);
+    sendBuffer.Payload.data[33] = ((parkingFee >> 16) & 0xFF);
+    sendBuffer.Payload.data[34] = ((parkingFee >> 8) & 0xFF);
+    sendBuffer.Payload.data[35] = (parkingFee & 0xFF);
 
 	SendPacket(socket, &sendBuffer);
 }
@@ -1382,15 +1467,35 @@ void Clean_LcmPage_Req(int gun_index, int lcm_req)
     ShmChargerInfo->ConnectorPageReq[gun_index].CtrlValue &= ~lcm_req;
 }
 
+bool Is_DispenserForceChargingTriggerWebApi(int gun_index)
+{
+    int dispenserIndex = ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].ParentDispensetIndex;
+
+    for(int i = 0; i < ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].ConnectorQuantity; i++)
+    {
+        int gun = ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].ConnectorID[i] - 1;
+
+        if(ShmChargerInfo->Control.FCharging[gun].FCtrl.bits.EnableForceCharging && ShmChargerInfo->Control.FCharging[gun].FCtrl.bits.WebApiTrigger)
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
 // LOG_INFO("Cabinet >> Connector %d Availability [SelfTestFail]", packet->Header.id);
 // LOG_INFO("Cabinet >> Connector %d Availability [Disable]", packet->Header.id);
 // LOG_INFO("Cabinet >> Connector %d Availability [Inoperative]", packet->Header.id);
 // LOG_INFO("Cabinet >> Connector %d Availability [Enable]", packet->Header.id);
 // LOG_INFO("Cabinet >> Connector %d RemoteStart  [%d]", packet->Header.id, misc.Value);
 // LOG_INFO("Cabinet >> Connector %d Balance      [%d]", packet->Header.id, (misc.Value));
-// LOG_INFO("Cabinet >> Connector %d Reservation  [Enable]", packet->Header.id);
-// LOG_INFO("Cabinet >> Connector %d QR Code      [Enable]", packet->Header.id);
-// LOG_INFO("Cabinet >> Connector %d Final Cost   [Enable]", packet->Header.id);
+// LOG_INFO("Cabinet >> Connector %d Reservation  [Trigger]", packet->Header.id);
+// LOG_INFO("Cabinet >> Connector %d QR Code      [Trigger]", packet->Header.id);
+// LOG_INFO("Cabinet >> Connector %d Final Cost   [Trigger]", packet->Header.id);
+// LOG_INFO("Cabinet >> Connector %d Line Status  [%d]", packet->Header.id, misc.Value);
+// LOG_INFO("Cabinet >> Connector %d User Price   [Trigger]", packet->Header.id);
+// LOG_INFO("Cabinet >> Connector %d Receipt URL  [Trigger]", packet->Header.id);
 // LOG_INFO("Cabinet >> Dispenser %d PlugTimeout  [%d]", dispenserIndex + 1, misc.Value);
 // LOG_INFO("Cabinet >> Dispenser %d DefaultPrice [%d]", dispenserIndex + 1, misc.Value);
 // LOG_INFO("Cabinet >> Dispenser %d Currency     [%d]", dispenserIndex + 1, misc.Value);
@@ -1410,10 +1515,11 @@ void Clean_LcmPage_Req(int gun_index, int lcm_req)
 // LOG_INFO("Cabinet >> Dispenser %d EVCCID       [%s]", dispenserIndex + 1, misc.Value ? "Enable" : "Disable");
 // LOG_INFO("Cabinet >> Dispenser %d LEDIntensity [%s]", dispenserIndex + 1, strIntensity[misc.Value]);
 // LOG_INFO("Cabinet >> Dispenser %d LEDIntensity [%d]", dispenserIndex + 1, misc.Value);
-// LOG_INFO("Cabinet >> Dispenser %d Station Info [%s]", dispenserIndex + 1, misc.Value ? "Enable" : "Disable");
+// LOG_INFO("Cabinet >> Dispenser %d Station Info [Trigger]", dispenserIndex + 1);
 // LOG_INFO("Cabinet >> Dispenser %d Time Offset  [%s%02d:%02d]", dispenserIndex + 1, misc.Value >= 0 ? "+" : "-", (abs(misc.Value) / 60), (abs(misc.Value) % 60));
 // LOG_INFO("Cabinet >> Dispenser %d Time Offset  [+%d]", dispenserIndex + 1, misc.Value);
 // LOG_INFO("Cabinet >> Dispenser %d Time Offset  [%d]", dispenserIndex + 1, misc.Value);
+// LOG_INFO("Cabinet >> Dispenser %d DefaultPrice [Trigger]", dispenserIndex + 1);
 void MiscCmdRes(int socket, struct PACKET_STRUCTURE *packet, unsigned char dispenserIndex, unsigned char result)
 {
     char *strConnection[] = {STR_CONN_DISABLE, STR_CONN_CONNECTED, STR_CONN_DISCONNECTED};
@@ -1445,6 +1551,11 @@ void MiscCmdRes(int socket, struct PACKET_STRUCTURE *packet, unsigned char dispe
                 IsAvailable = false;
                 LOG_INFO("Cabinet >> Connector %d Availability [SelfTestFail]", packet->Header.id);
             }
+            else if(Is_DispenserForceChargingTriggerWebApi(packet->Header.id - 1))
+            {
+                IsAvailable = false;
+                LOG_INFO("Cabinet >> Connector %d Availability [Disable][ForceCharging]", packet->Header.id);
+            }
             else if(!ShmChargerInfo->Control.GunAvailable[packet->Header.id - 1])
             {
                 IsAvailable = false;
@@ -1512,7 +1623,7 @@ void MiscCmdRes(int socket, struct PACKET_STRUCTURE *packet, unsigned char dispe
             misc.Command = _MiscCmd_Reservation;
             misc.Value = true;
 
-            LOG_INFO("Cabinet >> Connector %d Reservation  [Enable]", packet->Header.id);
+            LOG_INFO("Cabinet >> Connector %d Reservation  [Trigger]", packet->Header.id);
             AddMiscCommand(&sendBuffer, &misc);
         }
 
@@ -1522,7 +1633,7 @@ void MiscCmdRes(int socket, struct PACKET_STRUCTURE *packet, unsigned char dispe
             misc.Command = _MiscCmd_QRCodeRequest;
             misc.Value = true;
 
-            LOG_INFO("Cabinet >> Connector %d QR Code      [Enable]", packet->Header.id);
+            LOG_INFO("Cabinet >> Connector %d QR Code      [Trigger]", packet->Header.id);
             AddMiscCommand(&sendBuffer, &misc);
         }
 
@@ -1532,7 +1643,7 @@ void MiscCmdRes(int socket, struct PACKET_STRUCTURE *packet, unsigned char dispe
             misc.Command = _MiscCmd_FinalCost;
             misc.Value = true;
 
-            LOG_INFO("Cabinet >> Connector %d Final Cost   [Enable]", packet->Header.id);
+            LOG_INFO("Cabinet >> Connector %d Final Cost   [Trigger]", packet->Header.id);
             AddMiscCommand(&sendBuffer, &misc);
         }
 
@@ -1546,6 +1657,26 @@ void MiscCmdRes(int socket, struct PACKET_STRUCTURE *packet, unsigned char dispe
             AddMiscCommand(&sendBuffer, &misc);
         }
 
+        if(Is_Connector_MiscCommand(packet->Header.id - 1, MISC_CONN_USER_PRICE_STRING))
+        {
+            Clean_Connector_MiscCommand(packet->Header.id - 1, MISC_CONN_USER_PRICE_STRING);
+            misc.Command = _MiscCmd_UserPriceString;
+            misc.Value = true;
+
+            LOG_INFO("Cabinet >> Connector %d User Price   [Trigger]", packet->Header.id);
+            AddMiscCommand(&sendBuffer, &misc);
+        }
+
+        if(Is_Connector_MiscCommand(packet->Header.id - 1, MISC_CONN_RECEIPT))
+        {
+            Clean_Connector_MiscCommand(packet->Header.id - 1, MISC_CONN_RECEIPT);
+            misc.Command = _MiscCmd_Receipt;
+            misc.Value = true;
+
+            LOG_INFO("Cabinet >> Connector %d Receipt URL  [Trigger]", packet->Header.id);
+            AddMiscCommand(&sendBuffer, &misc);
+        }
+
         // announce misc command to first connector of the dispenser
         if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].ConnectorID[0] == packet->Header.id)
         {
@@ -1705,7 +1836,7 @@ void MiscCmdRes(int socket, struct PACKET_STRUCTURE *packet, unsigned char dispe
                 misc.Command = _MiscCmd_EVCCIDEnable;
 
                 if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].ModelName[0] == 'D' &&
-                    ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].ModelName[0] == 'X')
+                    ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].ModelName[1] == 'X')
                 {
                     misc.Value = ShmChargerInfo->CabinetMiscValue.AuthModeConfig > 0 ? 0 : 1;
                 }
@@ -1741,7 +1872,7 @@ void MiscCmdRes(int socket, struct PACKET_STRUCTURE *packet, unsigned char dispe
                 misc.Command = _MiscCmd_StationInfo;
                 misc.Value = true;
 
-                LOG_INFO("Cabinet >> Dispenser %d Station Info [%s]", dispenserIndex + 1, misc.Value ? "Enable" : "Disable");
+                LOG_INFO("Cabinet >> Dispenser %d Station Info [Trigger]", dispenserIndex + 1);
                 AddMiscCommand(&sendBuffer, &misc);
             }
 
@@ -1755,6 +1886,16 @@ void MiscCmdRes(int socket, struct PACKET_STRUCTURE *packet, unsigned char dispe
                     dispenserIndex + 1, misc.Value >= 0 ? "+" : "-", (abs(misc.Value) / 60), (abs(misc.Value) % 60));
                 AddMiscCommand(&sendBuffer, &misc);
             }
+
+            if(Is_Dispenser_MiscCommand(dispenserIndex, MISC_DISP_DEFAULT_PRICE_STRING))
+            {
+                Clean_Dispenser_MiscCommand(dispenserIndex, MISC_DISP_DEFAULT_PRICE_STRING);
+                misc.Command = _MiscCmd_DefaultPriceString;
+                misc.Value = true;
+
+                LOG_INFO("Cabinet >> Dispenser %d DefaultPrice [Trigger]", dispenserIndex + 1);
+                AddMiscCommand(&sendBuffer, &misc);
+            }
         }
 
         if(Is_Dispenser_MiscCommand(dispenserIndex, MISC_DISP_CHANGE_LCM_INFO))
@@ -1870,7 +2011,8 @@ int GetChargerSystemId(char *id)
 
         case _QR_MODE_Default:
         default:
-            strcat((char *)id, (char *)ShmSysConfigAndInfo->SysConfig.SystemId);
+            strcat((char *)id, (char *)ShmSysConfigAndInfo->SysConfig.ModelName);
+            strcat((char *)id, (char *)ShmSysConfigAndInfo->SysConfig.SerialNumber);
             break;
     }
 
@@ -1879,7 +2021,7 @@ int GetChargerSystemId(char *id)
     return len;
 }
 
-void ChargerSystemIdResponse(int socket, struct PACKET_STRUCTURE *packet, unsigned char dispenserIndex, unsigned char result)
+void ChargerQrCodeDateResponse(int socket, struct PACKET_STRUCTURE *packet, unsigned char dispenserIndex, unsigned char result)
 {
     struct PACKET_STRUCTURE sendBuffer;
     char system_id[128];
@@ -1889,7 +2031,7 @@ void ChargerSystemIdResponse(int socket, struct PACKET_STRUCTURE *packet, unsign
     sendBuffer.Header.id = packet->Header.id;
     sendBuffer.Header.op = _Header_Response;
     sendBuffer.Header.len = 2;
-    sendBuffer.Payload.reg = _Reg_Charger_System_Id;
+    sendBuffer.Payload.reg = _Reg_QR_Code_Date;
     sendBuffer.Payload.data[0] = result;
     if(result == _R_OK)
     {
@@ -2291,6 +2433,108 @@ void DeductResultResponse(int socket, struct PACKET_STRUCTURE *packet, unsigned
     SendPacket(socket, &sendBuffer);
 }
 
+void CabinetSystemIDResponse(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_CabinetSystemID;
+    sendBuffer.Payload.data[0] = result;
+    if(result == _R_OK)
+    {
+        strcpy((char *)&sendBuffer.Payload.data[1], (char *)ShmSysConfigAndInfo->SysConfig.SystemId);
+        sendBuffer.Header.len += strlen((char *)ShmSysConfigAndInfo->SysConfig.SystemId);
+    }
+    SendPacket(socket, &sendBuffer);
+}
+
+void DefaultPriceStringResponse(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_DefaultPriceString;
+    sendBuffer.Payload.data[0] = result;
+    if(result == _R_OK)
+    {
+        strcpy((char *)&sendBuffer.Payload.data[1], &ShmChargerInfo->PriceAndReceiptInfo.DefaultPriceString[0]);
+        sendBuffer.Header.len += strlen(&ShmChargerInfo->PriceAndReceiptInfo.DefaultPriceString[0]);
+    }
+    SendPacket(socket, &sendBuffer);
+}
+
+void UserPriceStringResponse(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_UserPriceString;
+    sendBuffer.Payload.data[0] = result;
+    if(result == _R_OK)
+    {
+        strcpy((char *)&sendBuffer.Payload.data[1], &ShmChargerInfo->PriceAndReceiptInfo.UserPriceString[packet->Header.id - 1][0]);
+        sendBuffer.Header.len += strlen(&ShmChargerInfo->PriceAndReceiptInfo.UserPriceString[packet->Header.id - 1][0]);
+    }
+    SendPacket(socket, &sendBuffer);
+}
+
+void ReceiptResponse(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_Receipt;
+    sendBuffer.Payload.data[0] = result;
+    if(result == _R_OK)
+    {
+        strcpy((char *)&sendBuffer.Payload.data[1], &ShmChargerInfo->PriceAndReceiptInfo.ReceiptUrl[packet->Header.id - 1][0]);
+        sendBuffer.Header.len += strlen(&ShmChargerInfo->PriceAndReceiptInfo.ReceiptUrl[packet->Header.id - 1][0]);
+    }
+    SendPacket(socket, &sendBuffer);
+}
+
+void PowerConsumptionResponse(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_PowerConsumption;
+    sendBuffer.Payload.data[0] = result;
+    if(result == _R_OK)
+    {
+        for(int i = 0; i < GENERAL_GUN_QUANTITY; i++)
+        {
+            char *ptr = (char *)&chargingInfo[i]->PowerConsumption;
+            sendBuffer.Payload.data[1 + (i * 4) + 0] = *(ptr + 3);
+            sendBuffer.Payload.data[1 + (i * 4) + 1] = *(ptr + 2);
+            sendBuffer.Payload.data[1 + (i * 4) + 2] = *(ptr + 1);
+            sendBuffer.Payload.data[1 + (i * 4) + 3] = *ptr;
+            sendBuffer.Header.len += 4;
+        }
+    }
+    SendPacket(socket, &sendBuffer);
+}
+
 BOOL FindConnectorID(unsigned char dispenserIndex, unsigned char id)
 {
 	BOOL find = false;
@@ -2316,9 +2560,13 @@ void ConnectorPhysicalLimitBindingHandler(unsigned char connectorIndex, unsigned
     switch(physical)
     {
         case 'J':
+            ShmSysConfigAndInfo->SysInfo.ConnectorInfo[connectorIndex].RemoteMaxPhysicalVoltage = CHA_MAX_PHYSICAL_VOLTAGE;
+            ShmSysConfigAndInfo->SysInfo.ConnectorInfo[connectorIndex].RemoteMaxPhysicalCurrent = CHA_NATURAL_J_MAX_CURRENT;
+            break;
+
         case 'K':
             ShmSysConfigAndInfo->SysInfo.ConnectorInfo[connectorIndex].RemoteMaxPhysicalVoltage = CHA_MAX_PHYSICAL_VOLTAGE;
-            ShmSysConfigAndInfo->SysInfo.ConnectorInfo[connectorIndex].RemoteMaxPhysicalCurrent = CHA_NATURAL_MAX_CURRENT;
+            ShmSysConfigAndInfo->SysInfo.ConnectorInfo[connectorIndex].RemoteMaxPhysicalCurrent = CHA_NATURAL_K_MAX_CURRENT;
             break;
 
         case 'U':
@@ -2470,7 +2718,7 @@ BOOL CheckNewDispenserSequence(unsigned char index, unsigned char quantity)
         ShmSysConfigAndInfo->SysConfig.WiringInfo.DispenserSequence = index + 1;
         ShmSysConfigAndInfo->SysConfig.WiringInfo.MaxConnectorQuantity += quantity;
         ShmSysConfigAndInfo->SysConfig.WiringInfo.WiringSetting[index] = quantity;
-        ShmSysConfigAndInfo->SysInfo.CabinetSetting.bits.FlashConfigChanged = true;
+        ShmChargerInfo->Control.SysCtrl.bits.WriteFlashEnable = true;
 
         ShmSysConfigAndInfo->SysInfo.DispenserInfo.DispenserQuantity = ShmSysConfigAndInfo->SysConfig.WiringInfo.DispenserSequence;
         ShmSysConfigAndInfo->SysInfo.DispenserInfo.TotalConnectorQuantity = ShmSysConfigAndInfo->SysConfig.WiringInfo.MaxConnectorQuantity;
@@ -2796,6 +3044,14 @@ BOOL ConnectorStateHandler(struct PACKET_STRUCTURE *packet, unsigned char dispen
                             ShmSysConfigAndInfo->SysInfo.ConnectorInfo[packet->Header.id - 1].Parameter.bits.NormalStopRequest = true;
                         }
                     }
+                    if(ConnectionState == _CRS_Terminating && ShmSysConfigAndInfo->SysInfo.ConnectorInfo[packet->Header.id - 1].RemoteStatus == _CRS_Idle)
+                    {
+                        if(chargingInfo[packet->Header.id - 1]->SystemStatus == S_RESERVATION)
+                        {
+                            chargingInfo[packet->Header.id - 1]->ReservationId = -1;
+                            LOG_INFO("*********** Connector id %d Clean ReservationId ***********\n", packet->Header.id);
+                        }
+                    }
                     break;
 
                 case _CRS_Alarm:
@@ -2833,7 +3089,7 @@ BOOL ConnectorStateHandler(struct PACKET_STRUCTURE *packet, unsigned char dispen
 
 bool IsEnableForceCharging(byte dispenserIndex, byte connectorId)
 {
-    if(connectorId != AUTO_GUN_SELECTION)
+    if(connectorId != AUTO_GUN_SELECTION_ID)
     {
         return ShmChargerInfo->Control.FCharging[connectorId - 1].FCtrl.bits.EnableForceCharging ? true : false;
     }
@@ -2866,8 +3122,19 @@ unsigned char UserIDHandler(struct PACKET_STRUCTURE *packet, unsigned char dispe
 	AuthorizingInfoData *AuthInfo;
 	AuthorizingInfoData *preAuthInfo;
 	int length = 0;
-
-	if(find || packet->Header.id == AUTO_GUN_SELECTION)
+	int cardNumberLength = 0;
+	unsigned char idType = _Type_ISO14443;
+	char *str_IdType[] = {
+        STR_ID_TYPE_CENTRAL,
+        STR_ID_TYPE_EMAID,
+        STR_ID_TYPE_ISO14443,
+        STR_ID_TYPE_ISO15693,
+        STR_ID_TYPE_KEYCODE,
+        STR_ID_TYPE_LOCAL,
+        STR_ID_TYPE_MAC_ADDRESS,
+        STR_ID_TYPE_NO_AUTHORIZATION};
+
+	if(find || packet->Header.id == AUTO_GUN_SELECTION_ID)
 	{
         if(IsEnableForceCharging(dispenserIndex, packet->Header.id))
         {
@@ -2877,8 +3144,18 @@ unsigned char UserIDHandler(struct PACKET_STRUCTURE *packet, unsigned char dispe
 	    length = packet->Header.len - 1;
 	    memset(CardNumber, 0x00, sizeof(CardNumber));
 	    memcpy(CardNumber, packet->Payload.data, length);
+	    cardNumberLength = strlen((char *)&CardNumber);
+
+        if(length - cardNumberLength >= 2)
+        {
+            idType = packet->Payload.data[cardNumberLength + 1];
+            if(idType > _Type_NoAuthorization)
+            {
+                idType = _Type_ISO14443;
+            }
+        }
 
-	    if(packet->Header.id != AUTO_GUN_SELECTION)
+	    if(packet->Header.id != AUTO_GUN_SELECTION_ID)
 	    {
 	        //result = &ShmSysConfigAndInfo->SysInfo.ConnectorInfo[packet->Header.id - 1].AuthorizingResult;
 	        AuthInfo = &ShmSysConfigAndInfo->SysInfo.ConnectorInfo[packet->Header.id - 1].AuthInfo;
@@ -2913,17 +3190,20 @@ unsigned char UserIDHandler(struct PACKET_STRUCTURE *packet, unsigned char dispe
         {
             if(AuthInfo->AuthStatus == _AuthorizeStatus_Idle && AuthInfo->AuthRequest == NO)
             {
-                memcpy(AuthInfo->AuthId, CardNumber, sizeof(CardNumber));
+                strcpy((char *)&AuthInfo->AuthId, (char *)&CardNumber);
                 AuthInfo->AuthTarget = packet->Header.id;
                 AuthInfo->AuthRequest = YES;
+                AuthInfo->AuthIdType = idType;
 
-                if(AuthInfo->AuthTarget != AUTO_GUN_SELECTION)
+                if(AuthInfo->AuthTarget != AUTO_GUN_SELECTION_ID)
                 {
-                    LOG_INFO("Gun %d user id [%s] need authorize", packet->Header.id, CardNumber);
+                    LOG_INFO("Gun %d user id [%s] type [%s] need authorize",
+                        packet->Header.id, CardNumber, str_IdType[idType]);
                 }
                 else
                 {
-                    LOG_INFO("Dispenser %d user id [%s] need authorize", dispenserIndex + 1, CardNumber);
+                    LOG_INFO("Dispenser %d user id [%s] type [%s] need authorize",
+                        dispenserIndex + 1, CardNumber, str_IdType[idType]);
                 }
                 authorize = _DAS_Wait;
             }
@@ -3235,7 +3515,7 @@ unsigned char DispenserWriteChargingInfoHandler(struct PACKET_STRUCTURE *packet,
     return find;
 }
 
-unsigned char ReadChargerSystemIdHandler(struct PACKET_STRUCTURE *packet, unsigned char dispenserIndex)
+unsigned char ReadQrCodeAndDateHandler(struct PACKET_STRUCTURE *packet, unsigned char dispenserIndex)
 {
     BOOL find = TRUE;
 
@@ -3507,7 +3787,7 @@ unsigned char GetStationInfoHandler(struct PACKET_STRUCTURE *packet, int dispens
     }
     else
     {
-        if(packet->Header.id == 0xFF)
+        if(packet->Header.id == AUTO_GUN_SELECTION_ID)
         {
             find = true;
         }
@@ -3533,11 +3813,11 @@ unsigned char WriteDeductResultHandler(struct PACKET_STRUCTURE *packet, int disp
     memset(vemData, 0x00, sizeof(vemData));
     memset(cardNo, 0x00, sizeof(cardNo));
 
-    if(find || packet->Header.id == 0xFF)
+    if(find || packet->Header.id == AUTO_GUN_SELECTION_ID)
     {
         memset(&deduct, 0x00, sizeof(DeductResultInfoData));
 
-        deduct.ConnectorId = packet->Header.id != 0xFF ?
+        deduct.ConnectorId = packet->Header.id != AUTO_GUN_SELECTION_ID ?
             packet->Header.id : ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].ConnectorID[0];
         gun = packet->Header.id - 1;
         deduct.DeductResult = packet->Payload.data[0];
@@ -3566,7 +3846,7 @@ unsigned char WriteDeductResultHandler(struct PACKET_STRUCTURE *packet, int disp
 
         if(deduct.DeductResult == _Deduct_Fail || deduct.DeductResult == _Deduct_Pass)
         {
-            if(packet->Header.id != 0xFF)
+            if(packet->Header.id != AUTO_GUN_SELECTION_ID)
             {
                 if(deduct.TransactionId == ShmChargerInfo->DeductResultReq[gun].TransactionId)
                 {
@@ -3599,7 +3879,7 @@ unsigned char WriteDeductResultHandler(struct PACKET_STRUCTURE *packet, int disp
                     done = true;
                 }
                 LOG_INFO("Gun %d%s ReDeduct %s",
-                    gun + 1, packet->Header.id != 0xFF ? "" : "(Default)", done ? "Done" : "Wait");
+                    gun + 1, packet->Header.id != AUTO_GUN_SELECTION_ID ? "" : "(Default)", done ? "Done" : "Wait");
                 LOG_INFO("Gun %d ReDeduct TxId: [%d], Card: [%s], [%s], Amount: [%d.%02d], Donate: [%s], ApprovalNo: [%s], VemData: [%s]",
                         gun + 1,
                         deduct.TransactionId,
@@ -3614,7 +3894,7 @@ unsigned char WriteDeductResultHandler(struct PACKET_STRUCTURE *packet, int disp
         }
         else if(deduct.DeductResult == _Deduct_Cancel || deduct.DeductResult == _Deduct_PreAuth)
         {
-            if(packet->Header.id != 0xFF)
+            if(packet->Header.id != AUTO_GUN_SELECTION_ID)
             {
                 if(!ShmChargerInfo->ReaderStatus[gun].ReaderStatusReq)
                 {
@@ -3645,6 +3925,66 @@ unsigned char WriteDeductResultHandler(struct PACKET_STRUCTURE *packet, int disp
     return find;
 }
 
+unsigned char ReadCabinetSystemIDHandler(struct PACKET_STRUCTURE *packet, int dispenserIndex)
+{
+    BOOL find = FindConnectorID(dispenserIndex, packet->Header.id);
+
+    if(packet->Header.id == AUTO_GUN_SELECTION_ID)
+    {
+        find = true;
+    }
+
+    return find;
+}
+
+unsigned char ReadDefaultPriceStringHandler(struct PACKET_STRUCTURE *packet, int dispenserIndex)
+{
+    BOOL find = FindConnectorID(dispenserIndex, packet->Header.id);
+
+    if(packet->Header.id == AUTO_GUN_SELECTION_ID)
+    {
+        find = true;
+    }
+
+    return find;
+}
+
+unsigned char ReadUserPriceStringHandler(struct PACKET_STRUCTURE *packet, int dispenserIndex)
+{
+    BOOL find = FindConnectorID(dispenserIndex, packet->Header.id);
+
+    if(find)
+    {
+
+    }
+
+    return find;
+}
+
+unsigned char ReadReceiptHandler(struct PACKET_STRUCTURE *packet, int dispenserIndex)
+{
+    BOOL find = FindConnectorID(dispenserIndex, packet->Header.id);
+
+    if(find)
+    {
+
+    }
+
+    return find;
+}
+
+unsigned char ReadPowerConsumptionHandler(struct PACKET_STRUCTURE *packet, int dispenserIndex)
+{
+    BOOL find = FindConnectorID(dispenserIndex, packet->Header.id);
+
+    if(packet->Header.id == AUTO_GUN_SELECTION_ID)
+    {
+        find = true;
+    }
+
+    return find;
+}
+
 void DisableConnector(unsigned char dispenserIndex)
 {
 	for(int i = 0; i < ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].ConnectorQuantity; i++)
@@ -3674,6 +4014,7 @@ void DispenserSocketProcess(int socketFd, struct sockaddr_in clientInfo, unsigne
 			{
 				ackResult = _R_NG;
                 //ShowSocketData(&receiveBuffer);
+				CheckEvRxCommMsg(&receiveBuffer);
 
 				if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.ConnectionInfo[index].Status == _CNS_WaitModelName)
 				{
@@ -3772,6 +4113,11 @@ void DispenserSocketProcess(int socketFd, struct sockaddr_in clientInfo, unsigne
                                     Set_Dispenser_MiscCommand(dispenserIndex, MISC_DISP_STATION_INFO);
                                 }
 
+                                if(strlen(ShmChargerInfo->PriceAndReceiptInfo.DefaultPriceString) > 0)
+                                {
+                                    Set_Dispenser_MiscCommand(dispenserIndex, MISC_DISP_DEFAULT_PRICE_STRING);
+                                }
+
                                 for(int i = 0; i < ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].ConnectorQuantity; i++)
                                 {
                                     unsigned char gun = ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].ConnectorID[i] - 1;
@@ -3906,14 +4252,14 @@ void DispenserSocketProcess(int socketFd, struct sockaddr_in clientInfo, unsigne
                         WriteChargingInfoResponse(socketFd, &receiveBuffer, ackResult);
                     }
 
-                    // Reg: 0x10, Charger system id
-                    if(receiveBuffer.Header.op == _Header_Read && receiveBuffer.Payload.reg == _Reg_Charger_System_Id)
+                    // Reg: 0x10, QR Code And Date
+                    if(receiveBuffer.Header.op == _Header_Read && receiveBuffer.Payload.reg == _Reg_QR_Code_Date)
                     {
-                        if(ReadChargerSystemIdHandler(&receiveBuffer, dispenserIndex))
+                        if(ReadQrCodeAndDateHandler(&receiveBuffer, dispenserIndex))
                         {
                             ackResult = _R_OK;
                         }
-                        ChargerSystemIdResponse(socketFd, &receiveBuffer, dispenserIndex, ackResult);
+                        ChargerQrCodeDateResponse(socketFd, &receiveBuffer, dispenserIndex, ackResult);
                     }
 
                     // Reg: 0x11, Wait plug in
@@ -4068,6 +4414,56 @@ void DispenserSocketProcess(int socketFd, struct sockaddr_in clientInfo, unsigne
                         }
                         DeductResultResponse(socketFd, &receiveBuffer, ackResult);
                     }
+
+                    // Reg: 0x20, Read Cabinet System ID
+                    if(receiveBuffer.Header.op == _Header_Read && receiveBuffer.Payload.reg == _Reg_CabinetSystemID)
+                    {
+                        if(ReadCabinetSystemIDHandler(&receiveBuffer, dispenserIndex))
+                        {
+                            ackResult = _R_OK;
+                        }
+                        CabinetSystemIDResponse(socketFd, &receiveBuffer, ackResult);
+                    }
+
+                    // Reg: 0x21, Read Default Price String
+                    if(receiveBuffer.Header.op == _Header_Read && receiveBuffer.Payload.reg == _Reg_DefaultPriceString)
+                    {
+                        if(ReadDefaultPriceStringHandler(&receiveBuffer, dispenserIndex))
+                        {
+                            ackResult = _R_OK;
+                        }
+                        DefaultPriceStringResponse(socketFd, &receiveBuffer, ackResult);
+                    }
+
+                    // Reg: 0x22, Read User Price String
+                    if(receiveBuffer.Header.op == _Header_Read && receiveBuffer.Payload.reg == _Reg_UserPriceString)
+                    {
+                        if(ReadUserPriceStringHandler(&receiveBuffer, dispenserIndex))
+                        {
+                            ackResult = _R_OK;
+                        }
+                        UserPriceStringResponse(socketFd, &receiveBuffer, ackResult);
+                    }
+
+                    // Reg: 0x23, Read Receipt
+                    if(receiveBuffer.Header.op == _Header_Read && receiveBuffer.Payload.reg == _Reg_Receipt)
+                    {
+                        if(ReadReceiptHandler(&receiveBuffer, dispenserIndex))
+                        {
+                            ackResult = _R_OK;
+                        }
+                        ReceiptResponse(socketFd, &receiveBuffer, ackResult);
+                    }
+
+                    // Reg: 0x24, Read Power Consumption
+                    if(receiveBuffer.Header.op == _Header_Read && receiveBuffer.Payload.reg == _Reg_PowerConsumption)
+                    {
+                        if(ReadPowerConsumptionHandler(&receiveBuffer, dispenserIndex))
+                        {
+                            ackResult = _R_OK;
+                        }
+                        PowerConsumptionResponse(socketFd, &receiveBuffer, ackResult);
+                    }
 				}
 
 				// clean timeout

+ 14 - 3
EVSE/Projects/DO360/Apps/Module_EvComm.h

@@ -33,12 +33,13 @@
 #define CCS_NATURAL_REMA_MAX_CURRENT    3000
 
 #define CHA_MAX_PHYSICAL_VOLTAGE        5000
-#define CHA_NATURAL_MAX_CURRENT         2000
+#define CHA_NATURAL_K_MAX_CURRENT       2000
+#define CHA_NATURAL_J_MAX_CURRENT       1200
 
 #define GBT_MAX_PHYSICAL_VOLTAGE        7500
 #define GBT_NATURAL_MAX_CURRENT         2500
 
-#define AUTO_GUN_SELECTION              0xFF
+#define AUTO_GUN_SELECTION_ID           0xFF
 
 struct Message
 {
@@ -70,7 +71,7 @@ enum PAYLOAD_REGISTER
     _Reg_Report_Csu_Version         = 0x0D,
     _Reg_Report_Other_Version       = 0x0E,
     _Reg_Charging_Info              = 0x0F,
-    _Reg_Charger_System_Id          = 0x10,
+    _Reg_QR_Code_Date               = 0x10,
     _Reg_WaitPlugIn                 = 0x11,
     _Reg_GroundFaultDetection       = 0x12,
     _Reg_Get_Cabinet_CSU_Version    = 0x13,
@@ -86,6 +87,11 @@ enum PAYLOAD_REGISTER
     _Reg_ConnectorQRCode            = 0x1D,
     _Reg_StationInfo                = 0x1E,
     _Reg_DeductResult               = 0x1F,
+    _Reg_CabinetSystemID            = 0x20,
+    _Reg_DefaultPriceString         = 0x21,
+    _Reg_UserPriceString            = 0x22,
+    _Reg_Receipt                    = 0x23,
+    _Reg_PowerConsumption           = 0x24,
 };
 
 enum Response_Result
@@ -213,6 +219,9 @@ enum MiscCommand
     _MiscCmd_StationInfo        = 0x0109,
     _MiscCmd_FinalCost          = 0x010A,
     _MiscCmd_LineStatus         = 0x010B,
+    _MiscCmd_DefaultPriceString = 0x010C,
+    _MiscCmd_UserPriceString    = 0x010D,
+    _MiscCmd_Receipt            = 0x010E,
 };
 
 enum DispenserMisc_Request
@@ -233,6 +242,8 @@ typedef struct
     int            AccountBalance;          // unit = 0.01 dollar
     int            CostDiscount;            // unit = 0.01 dollar
     int            TransactionId;           // unit = 0.01 dollar
+    int            EnergyCost;              // unit = 0.01 dollar
+    int            ParkingFee;              // unit = 0.01 dollar
     char           CurrencyString[4];
 }ChargingCapabilityResponseInfo;
 

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


+ 324 - 77
EVSE/Projects/DO360/Apps/main.c

@@ -238,6 +238,8 @@ void Clean_Ocpp_RunningCost(int gun_index);
 void Get_Ocpp_FinalCost(int gun_index, char *cost);
 void Clean_Ocpp_FinalCost(int gun_index);
 void Get_Ocpp_TimeOffset(char *timeOffset);
+void Get_Ocpp_PreAuthAmount(char *amount);
+void Get_Ocpp_PowerSharingServerIP(char *ip);
 void Get_Ocpp_Refunding(char *Refunding);
 void Clean_Ocpp_Refunding(void);
 bool Is_Ocpp_LcdOverideReq(int *gun, int *page);
@@ -394,7 +396,7 @@ bool isModelNameMatch = true;
 //int rfidFd = -1;
 //char* rfidPortName = "/dev/ttyS2";
 #if ENABLE_PCBA_TEST == 0
-char* fwVersion = "V2.00.00.0000.00";
+char* fwVersion = "V2.01.00.0000.00";
 char* subVersion = "00";
 #else
 char* fwVersion = "PCBA.00.04";
@@ -2108,6 +2110,10 @@ void InitialCustomerCode(void)
     {
         ShmChargerInfo->Control.CustomerCode = _CUSTOMER_CODE_TCC;
     }
+    else if(ShmSysConfigAndInfo->SysConfig.ModelName[12] == 'O' && ShmSysConfigAndInfo->SysConfig.ModelName[13] == 'L')
+    {
+        ShmChargerInfo->Control.CustomerCode = _CUSTOMER_CODE_Shell;
+    }
     else
     {
         ShmChargerInfo->Control.CustomerCode = _CUSTOMER_CODE_Phihong;
@@ -3642,6 +3648,42 @@ void Get_Ocpp_TimeOffset(char *timeOffset)
     strcpy(timeOffset, "");
 }
 
+//===============================================
+// Ocpp PreAuthAmount
+//===============================================
+void Get_Ocpp_PreAuthAmount(char *amount)
+{
+    if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16)
+    {
+        strcpy(amount, (char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[PreAuthAmount].ItemData);
+        return;
+    }
+    if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20)
+    {
+        strcpy(amount, "");
+        return;
+    }
+    strcpy(amount, "");
+}
+
+//===============================================
+// Ocpp PowerSharingServerIP
+//===============================================
+void Get_Ocpp_PowerSharingServerIP(char *ip)
+{
+    if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16)
+    {
+        strcpy(ip, (char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[PowerSharingServerIP].ItemData);
+        return;
+    }
+    if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20)
+    {
+        strcpy(ip, "");
+        return;
+    }
+    strcpy(ip, "");
+}
+
 //===============================================
 // Ocpp Refunding
 //===============================================
@@ -4945,6 +4987,12 @@ void Clean_UserTransaction(int gunIndex)
     ShmChargerInfo->UserTransaction[gunIndex].AccountBalance = -65535;
 }
 
+void Clean_UserPriceAndReceipt(int gunIndex)
+{
+    memset((char *)&ShmChargerInfo->PriceAndReceiptInfo.UserPriceString[gunIndex][0], 0x00, sizeof(ShmChargerInfo->PriceAndReceiptInfo.UserPriceString[gunIndex]));
+    memset((char *)&ShmChargerInfo->PriceAndReceiptInfo.ReceiptUrl[gunIndex][0], 0x00, sizeof(ShmChargerInfo->PriceAndReceiptInfo.ReceiptUrl[gunIndex]));
+}
+
 //===============================================
 // Main process
 //===============================================
@@ -5022,6 +5070,9 @@ void DispenserAuthInitial(unsigned char dispenser)
     LOG_INFO("*********** Dispenser %d Authorizing Initial ***********", dispenser + 1);
 
     memset(&ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenser].AuthInfo, 0x00, sizeof(AuthorizingInfoData));
+
+    // clean dispenser price
+    memset((char *)&ShmChargerInfo->PriceAndReceiptInfo.DispenserPriceString[dispenser][0], 0x00, sizeof(ShmChargerInfo->PriceAndReceiptInfo.DispenserPriceString[dispenser]));
 }
 
 void GunAuthInitial(unsigned char connector)
@@ -5076,12 +5127,11 @@ void AuthorizeTimeoutProcess(void)
             }
 
             CompletedTime = ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].AuthInfo.AuthResult == _AuthResult_Valid ?
-                ShmChargerInfo->CabinetMiscValue.ConnectionTimeout : AUTHORIZE_COMPLETED_TIME;
+                (ShmChargerInfo->CabinetMiscValue.ConnectionTimeout + AUTHORIZE_COMPLETED_TIME) : AUTHORIZE_COMPLETED_TIME;
 
             if(GetTimeoutValue(_DispenserAuth_Time[index]) / uSEC_VAL >= CompletedTime)
             {
-                LOG_INFO("*********** Dispenser %d Authorizing Initial ***********", index + 1);
-                memset(&ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].AuthInfo, 0x00, sizeof(AuthorizingInfoData));
+                DispenserAuthInitial(index);
             }
         }
         _preDispenserAuthResult[index] = ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[index].AuthInfo.AuthResult;
@@ -5938,7 +5988,7 @@ void CheckFwUpdateFunction(void)
 	}
 }
 
-void ExecuteWriteWiringInfo(void)
+void ExecuteWriteFlash(void)
 {
     struct SysConfigData config;
 
@@ -5958,40 +6008,37 @@ void ExecuteWriteWiringInfo(void)
 }
 
 struct timespec _WiringInfo_time;
-int CheckWiringInfoUpdate(void)
+int CheckFlashUpdate(void)
 {
-    if(ShmSysConfigAndInfo->SysInfo.CabinetSetting.bits.FlashConfigChanged)
+    if(ShmChargerInfo->Control.SysCtrl.bits.WriteFlashEnable)
     {
-        ShmSysConfigAndInfo->SysInfo.CabinetSetting.bits.FlashConfigChanged = false;
+        ShmChargerInfo->Control.SysCtrl.bits.WriteFlashEnable = false;
         LOG_INFO("Flash Config Changed");
 
         GetClockTime(&_WiringInfo_time);
-        ShmSysConfigAndInfo->SysInfo.CabinetSetting.bits.EnableWriteFlash = true;
-    }
 
-    if(ShmSysConfigAndInfo->SysInfo.CabinetSetting.bits.EnableWriteFlash)
-    {
-        // 30s for reboot request timeout
+        // wait for 30s to write flash or write flash immediately
         if((GetTimeoutValue(_WiringInfo_time) / uSEC_VAL) >= WIRING_INFO_DELAY ||
-            ShmSysConfigAndInfo->SysInfo.CabinetSetting.bits.CleanWiringInfo)
+            ShmChargerInfo->Control.SysCtrl.bits.WriteFlashImmediately)
         {
-            ShmSysConfigAndInfo->SysInfo.CabinetSetting.bits.EnableWriteFlash = false;
-            LOG_INFO("Start Write To Flash");
+            LOG_INFO("Start Writing Flash");
 
             pid_t writePid = fork();
             if(writePid == 0)
             {
-                ExecuteWriteWiringInfo();
+                ShmChargerInfo->Control.SysCtrl.bits.WriteFlashBusy = true;
+                ExecuteWriteFlash();
+                ShmChargerInfo->Control.SysCtrl.bits.WriteFlashBusy = false;
 
-                if(ShmSysConfigAndInfo->SysInfo.CabinetSetting.bits.CleanWiringInfo)
+                if(ShmChargerInfo->Control.SysCtrl.bits.WriteFlashAndReset)
                 {
-                    ShmSysConfigAndInfo->SysInfo.CabinetSetting.bits.CleanWiringInfo = false;
+                    ShmChargerInfo->Control.SysCtrl.bits.WriteFlashAndReset = false;
                     ShmChargerInfo->Control.SysCtrl.bits.NeedSoftReset = true;
-                    LOG_INFO("Clean Wiring Info And Need Soft Reset");
+                    LOG_INFO("Write Flash OK And Need Soft Reset");
                 }
                 return NO;
             }
-            LOG_INFO("Clean Write Flahs Flag");
+            LOG_INFO("Write Flash Conpleted");
         }
     }
 
@@ -6180,7 +6227,6 @@ float PhTariffParsing(char *StringItem, char *TariffCode)
     return fee;
 }
 
-// the unit of return value: 0.01 dollar
 float DefaultPriceParsing(char *StringItem)
 {
     char *ptrSave, *ptrToken;
@@ -6249,8 +6295,11 @@ char MyDefaultPriceString[501];
 void DefaultPriceHandler(void)
 {
     char price[501];
+    char defaultPrice[512];
 
+    memset(defaultPrice, 0x00, sizeof(defaultPrice));
     Get_Ocpp_DefaultPrice((char *)price);
+
     if(strcmp(MyDefaultPriceString, (char *)price) != EQUAL)
     {
         BOOL trigger = FALSE;
@@ -6259,21 +6308,37 @@ void DefaultPriceHandler(void)
 
         if(ShmChargerInfo->Control.CustomerCode == _CUSTOMER_CODE_Audi)
         {
-            ConnectionFee = TariffParsing(price, "Connection Fee");
-            CurrentRate = TariffParsing(price, "Current Rate");
-            OccupancyFee = TariffParsing(price, "Occupancy Fee");
+            ConnectionFee = PriceParsing(price, "Connection Fee", _AUDI_PRICE_SPLIT_KEY);
+            CurrentRate = PriceParsing(price, "Current Rate", _AUDI_PRICE_SPLIT_KEY);
+            OccupancyFee = PriceParsing(price, "Occupancy Fee", _AUDI_PRICE_SPLIT_KEY);
+
+            LOG_INFO("******** Customer Audi Default Price *******");
+            LOG_INFO("**********  Connection Fee: %4.2f **********", ConnectionFee);
+            LOG_INFO("**********    Current Rate: %4.2f **********", CurrentRate);
+            LOG_INFO("**********   Occupancy Fee: %4.2f **********", OccupancyFee);
+        }
+        else if(ShmChargerInfo->Control.CustomerCode == _CUSTOMER_CODE_Shell)
+        {
+            ShellPriceParsing(price, defaultPrice);
+
+            LOG_INFO("******* Customer Shell Default Price *******");
+            LOG_INFO("*** Default Price: [%s]", defaultPrice);
         }
         else
         {
             CurrentRate = DefaultPriceParsing(price);
-        }
+            strcpy(defaultPrice, price);
 
-        LOG_INFO("********** Default Price: %s", price);
-        LOG_INFO("**********  Connection Fee: %4.2f **********", ConnectionFee);
-        LOG_INFO("**********    Current Rate: %4.2f **********", CurrentRate);
-        LOG_INFO("**********   Occupancy Fee: %4.2f **********", OccupancyFee);
+            LOG_INFO("********** Standard Default Price **********");
+            LOG_INFO("**********    Current Rate: %4.2f **********", CurrentRate);
+            LOG_INFO("*** Default Price: [%s]", defaultPrice);
+        }
 
         ShmChargerInfo->CabinetMiscValue.DefaultPrice = CurrentRate;
+        if(strlen(defaultPrice) > 0)
+        {
+            strcpy(ShmChargerInfo->PriceAndReceiptInfo.DefaultPriceString, defaultPrice);
+        }
 
         for(int i = 0; i < CONNECTOR_QUANTITY; i++)
         {
@@ -6290,6 +6355,15 @@ void DefaultPriceHandler(void)
                     trigger = TRUE;
                     Set_Dispenser_MiscCommand(i, MISC_DISP_CURRENCY);
                 }
+
+                if(strlen(defaultPrice) > 0)
+                {
+                    if(!Is_Dispenser_MiscCommand(i, MISC_DISP_DEFAULT_PRICE_STRING))
+                    {
+                        trigger = TRUE;
+                        Set_Dispenser_MiscCommand(i, MISC_DISP_DEFAULT_PRICE_STRING);
+                    }
+                }
             }
         }
 
@@ -6305,35 +6379,59 @@ void DefaultPriceHandler(void)
 void UserPriceHandler(void)
 {
     char UserId[32];
-    char preice[500];
+    char price[500];
+    char userPrice[512];
 
-    Get_Ocpp_UserPrice(UserId, preice);
+    memset(userPrice, 0x00, sizeof(userPrice));
+    Get_Ocpp_UserPrice(UserId, price);
 
-    if(strlen((char *)UserId) > 0 && strlen((char *)preice) > 0)
+    if(strlen((char *)UserId) > 0 && strlen((char *)price) > 0)
     {
         float ConnectionFee = 0, CurrentRate = 0, OccupancyFee = 0;
         float AccountBalance = 0;
 
         if(ShmChargerInfo->Control.CustomerCode == _CUSTOMER_CODE_Audi)
         {
-            ConnectionFee = TariffParsing((char *)preice, "Connection Fee");
-            CurrentRate = TariffParsing((char *)preice, "Current Rate");
-            OccupancyFee = TariffParsing((char *)preice, "Occupancy Fee");
-            AccountBalance = TariffParsing((char *)preice, "Account Balance");
+            ConnectionFee = PriceParsing((char *)price, "Connection Fee", _AUDI_PRICE_SPLIT_KEY);
+            CurrentRate = PriceParsing((char *)price, "Current Rate", _AUDI_PRICE_SPLIT_KEY);
+            OccupancyFee = PriceParsing((char *)price, "Occupancy Fee", _AUDI_PRICE_SPLIT_KEY);
+            AccountBalance = PriceParsing((char *)price, "Account Balance", _AUDI_PRICE_SPLIT_KEY);
+
+            LOG_INFO("********* Customer Audi User Price *********");
+            LOG_INFO("*********         User Id: [%s]", UserId);
+            LOG_INFO("*********  Connection Fee: [%7.2f]", ConnectionFee);
+            LOG_INFO("*********    Current Rate: [%7.2f]", CurrentRate);
+            LOG_INFO("*********   Occupancy Fee: [%7.2f]", OccupancyFee);
+            LOG_INFO("********* Account Balance: [%7.2f]", AccountBalance);
         }
-        else
+        else if(ShmChargerInfo->Control.CustomerCode == _CUSTOMER_CODE_Shell)
         {
-            CurrentRate = PhTariffParsing((char *)preice, "chargineFee");
-            OccupancyFee = PhTariffParsing((char *)preice, "parkingFee");
+            ShellPriceParsing(price, userPrice);
+
+            LOG_INFO("******** Customer Shell User Price *********");
+            LOG_INFO("********    User Id: [%s]", UserId);
+            LOG_INFO("******** User Price: [%s]", userPrice);
         }
+        else
+        {
+            CurrentRate = PriceParsing((char *)price, "chargineFee", _PHIHONG_PRICE_SPLIT_KEY);
+            OccupancyFee = PriceParsing((char *)price, "parkingFee", _PHIHONG_PRICE_SPLIT_KEY);
+            strcpy(userPrice, price);
 
+            LOG_INFO("*********** Standard User Price ************");
+            LOG_INFO("***********       User Id: [%s]", UserId);
+            LOG_INFO("***********  Current Rate: [%7.2f]", CurrentRate);
+            LOG_INFO("*********** Occupancy Fee: [%7.2f]", OccupancyFee);
+            LOG_INFO("***********    User Price: [%s]", userPrice);
+        }
+#if 0
         LOG_INFO("********** User Id: %s **********", UserId);
-        LOG_INFO("********** User Price: %s", preice);
+        LOG_INFO("********** User Price: %s", price);
         LOG_INFO("**********  Connection Fee: %7.2f **********", ConnectionFee);
         LOG_INFO("**********    Current Rate: %7.2f **********", CurrentRate);
         LOG_INFO("**********   Occupancy Fee: %7.2f **********", OccupancyFee);
         LOG_INFO("********** Account Balance: %7.2f **********", AccountBalance);
-
+#endif
         for(int i = 0; i < CONNECTOR_QUANTITY; i++)
         {
             if(strcmp((char *)ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].GeneralChargingData.StartUserId, UserId) == EQUAL)
@@ -6348,6 +6446,12 @@ void UserPriceHandler(void)
                 ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].UserPrice = CurrentRate;
                 ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].AccountBalance = AccountBalance;
 
+                if(strlen(userPrice) > 0)
+                {
+                    strcpy((char *)&ShmChargerInfo->PriceAndReceiptInfo.UserPriceString[i][0], userPrice);
+                    Set_Connector_MiscCommand(i, MISC_CONN_USER_PRICE_STRING);
+                }
+
                 if(chargingInfo[i]->SystemStatus == S_AUTHORIZING)
                 {
                     AnnounceAccountBalance(i, AccountBalance);
@@ -6355,6 +6459,20 @@ void UserPriceHandler(void)
             }
         }
 
+        for(int i = 0; i < CONNECTOR_QUANTITY; i++)
+        {
+            if(ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].AuthInfo.AuthResult == _AuthResult_Valid)
+            {
+                if(strcmp((char *)ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[i].AuthInfo.AuthId, UserId) == EQUAL)
+                {
+                    if(strlen(userPrice) > 0)
+                    {
+                        strcpy((char *)&ShmChargerInfo->PriceAndReceiptInfo.DispenserPriceString[i][0], userPrice);
+                    }
+                }
+            }
+        }
+
         Clean_Ocpp_UserPrice();
     }
 }
@@ -6362,8 +6480,10 @@ void UserPriceHandler(void)
 void RunningFinalCostHandler(void)
 {
     char strCost[256];
-    float ConnectionFee = 0, SessionFee = 0, OccupancyFee = 0, TotalCost = 0, CostDiscount = 0;
+    float ConnectionFee = 0, SessionFee = 0, OccupancyFee = 0, TotalCost = 0, CostDiscount = 0, EnergyCost = 0;
     float AccountBalance = 0;
+    char receiptString[512];
+    int receiptLength = 0;
 
     for(int i = 0; i < CONNECTOR_QUANTITY; i++)
     {
@@ -6375,23 +6495,45 @@ void RunningFinalCostHandler(void)
             {
                 ConnectionFee = 0;
                 SessionFee = 0;
-                OccupancyFee = 0;
+                OccupancyFee = -1;
                 TotalCost = 0;
                 AccountBalance = 0;
                 CostDiscount = 0;
+                EnergyCost = -1;
 
                 if(ShmChargerInfo->Control.CustomerCode == _CUSTOMER_CODE_Audi)
                 {
-                    ConnectionFee = TariffParsing((char *)strCost, "Connection Fee");
-                    SessionFee = TariffParsing((char *)strCost, "Session Fee");
-                    OccupancyFee = TariffParsing((char *)strCost, "Occupancy Fee");
-                    TotalCost = TariffParsing((char *)strCost, "Total Cost");
-                    AccountBalance = TariffParsing((char *)strCost, "Account Balance");
+                    ConnectionFee = PriceParsing((char *)strCost, "Connection Fee", _AUDI_PRICE_SPLIT_KEY);
+                    SessionFee = PriceParsing((char *)strCost, "Session Fee", _AUDI_PRICE_SPLIT_KEY);
+                    OccupancyFee = PriceParsing((char *)strCost, "Occupancy Fee", _AUDI_PRICE_SPLIT_KEY);
+                    TotalCost = PriceParsing((char *)strCost, "Total Cost", _AUDI_PRICE_SPLIT_KEY);
+                    AccountBalance = PriceParsing((char *)strCost, "Account Balance", _AUDI_PRICE_SPLIT_KEY);
+
+                    LOG_INFO("******** Customer Audi Gun %d Running Cost ********", (i + 1));
+                    LOG_INFO("********  Connection Fee: [%7.2f]", ConnectionFee);
+                    LOG_INFO("********     Session Fee: [%7.2f]", SessionFee);
+                    LOG_INFO("********   Occupancy Fee: [%7.2f]", OccupancyFee);
+                    LOG_INFO("********      Total Cost: [%7.2f]", TotalCost);
+                    LOG_INFO("******** Account Balance: [%7.2f]", AccountBalance);
+                }
+                else if(ShmChargerInfo->Control.CustomerCode == _CUSTOMER_CODE_Shell)
+                {
+                    TotalCost = ShellRunningCostParsing(strCost);
+
+                    LOG_INFO("******** Customer Shell Gun %d Running Cost *******", (i + 1));
+                    LOG_INFO("******** Gun %d Running Cost", (i + 1));
+                    LOG_INFO("******** Total Cost: [%7.2f]", TotalCost);
                 }
                 else
                 {
-                    TotalCost = PhTariffParsing((char *)strCost, "chargingFee");
-                    OccupancyFee = PhTariffParsing((char *)strCost, "parkingFee");
+                    EnergyCost = PriceParsing((char *)strCost, "chargingFee", _PHIHONG_PRICE_SPLIT_KEY);
+                    TotalCost = EnergyCost;
+                    OccupancyFee = PriceParsing((char *)strCost, "parkingFee", _PHIHONG_PRICE_SPLIT_KEY);
+
+                    LOG_INFO("********** Standard Gun %d Running Cost ***********", (i + 1));
+                    LOG_INFO("**********   Energy Cost: [%7.2f]", EnergyCost);
+                    LOG_INFO("********** Occupancy Fee: [%7.2f]", OccupancyFee);
+                    LOG_INFO("**********    Total Cost: [%7.2f]", TotalCost);
                 }
 #if 0
                 LOG_INFO("********** Connector Id: %d Running Cost **********", (i + 1));
@@ -6410,6 +6552,8 @@ void RunningFinalCostHandler(void)
 #endif
                 ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].TotalCost = TotalCost;
                 ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].AccountBalance = AccountBalance;
+                ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].EnergyCost = EnergyCost;
+                ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].ParkingFee = OccupancyFee;
 
                 Clean_Ocpp_RunningCost(i);
             }
@@ -6419,34 +6563,67 @@ void RunningFinalCostHandler(void)
             {
                 ConnectionFee = 0;
                 SessionFee = 0;
-                OccupancyFee = 0;
+                OccupancyFee = -1;
                 TotalCost = 0;
                 AccountBalance = 0;
                 CostDiscount = 0;
+                EnergyCost = -1;
+                memset(receiptString, 0x00, sizeof(receiptString));
 
                 if(ShmChargerInfo->Control.CustomerCode == _CUSTOMER_CODE_Audi)
                 {
-                    ConnectionFee = TariffParsing((char *)strCost, "Connection Fee");
-                    SessionFee = TariffParsing((char *)strCost, "Session Fee");
-                    OccupancyFee = TariffParsing((char *)strCost, "Occupancy Fee");
-                    TotalCost = TariffParsing((char *)strCost, "Total Cost");
-                    AccountBalance = TariffParsing((char *)strCost, "Account Balance");
+                    ConnectionFee = PriceParsing((char *)strCost, "Connection Fee", _AUDI_PRICE_SPLIT_KEY);
+                    SessionFee = PriceParsing((char *)strCost, "Session Fee", _AUDI_PRICE_SPLIT_KEY);
+                    OccupancyFee = PriceParsing((char *)strCost, "Occupancy Fee", _AUDI_PRICE_SPLIT_KEY);
+                    TotalCost = PriceParsing((char *)strCost, "Total Cost", _AUDI_PRICE_SPLIT_KEY);
+                    AccountBalance = PriceParsing((char *)strCost, "Account Balance", _AUDI_PRICE_SPLIT_KEY);
+
+                    LOG_INFO("********* Customer Audi Gun %d Final Cost *********", (i + 1));
+                    LOG_INFO("*********  Connection Fee: [%7.2f]", ConnectionFee);
+                    LOG_INFO("*********     Session Fee: [%7.2f]", SessionFee);
+                    LOG_INFO("*********   Occupancy Fee: [%7.2f]", OccupancyFee);
+                    LOG_INFO("*********      Total Cost: [%7.2f]", TotalCost);
+                    LOG_INFO("********* Account Balance: [%7.2f]", AccountBalance);
                 }
-                else
+                else if(ShmChargerInfo->Control.CustomerCode == _CUSTOMER_CODE_Shell)
                 {
-                    TotalCost = PhTariffParsing((char *)strCost, "chargingFee");
-                    OccupancyFee = PhTariffParsing((char *)strCost, "parkingFee");
-                    AccountBalance = PhTariffParsing((char *)strCost, "accountBalance");
-                    CostDiscount = PhTariffParsing((char *)strCost, "couponPoint");
+                    TotalCost = ShellFinalCostParsing(strCost);
+                    receiptLength = GetShellReceiptInfo(strCost, receiptString);
+
+                    LOG_INFO("********* Customer Shell Gun %d Final Cost ********", (i + 1));
+                    LOG_INFO("********* Total Cost: [%7.2f]", TotalCost);
+                    LOG_INFO("*********    Receipt: [%s]", receiptString);
                 }
+                else
+                {
+                    TotalCost = PriceParsing((char *)strCost, "chargingFee", _PHIHONG_PRICE_SPLIT_KEY);
+                    OccupancyFee = PriceParsing((char *)strCost, "parkingFee", _PHIHONG_PRICE_SPLIT_KEY);
+                    AccountBalance = PriceParsing((char *)strCost, "accountBalance", _PHIHONG_PRICE_SPLIT_KEY);
+                    CostDiscount = PriceParsing((char *)strCost, "couponPoint", _PHIHONG_PRICE_SPLIT_KEY);
+
+                    if(strlen((char *)&ShmSysConfigAndInfo->SysConfig.OcppReceiptrURL) > 0)
+                    {
+                        sprintf(receiptString, "%s%d",
+                            (char *)&ShmSysConfigAndInfo->SysConfig.OcppReceiptrURL[0],
+                            ShmChargerInfo->UserTransaction[i].TransactionId);
+                        receiptLength = strlen(receiptString);
+                    }
 
+                    LOG_INFO("*********** Standard Gun %d Final Cost ************", (i + 1));
+                    LOG_INFO("***********   Occupancy Fee: [%7.2f]", OccupancyFee);
+                    LOG_INFO("***********      Total Cost: [%7.2f]", TotalCost);
+                    LOG_INFO("*********** Account Balance: [%7.2f]", AccountBalance);
+                    LOG_INFO("***********    Coupon Point: [%7.2f]", CostDiscount);
+                    LOG_INFO("***********         Receipt: [%s]", receiptString);
+                }
+#if 0
                 LOG_INFO("********** Connector Id: %d Final Cost **********", (i + 1));
                 LOG_INFO("**********  Connection Fee: %7.2f **********", ConnectionFee);
                 LOG_INFO("**********     Session Fee: %7.2f **********", SessionFee);
                 LOG_INFO("**********   Occupancy Fee: %7.2f **********", OccupancyFee);
                 LOG_INFO("**********      Total Cost: %7.2f **********", TotalCost);
                 LOG_INFO("********** Account Balance: %7.2f **********", AccountBalance);
-#if 0
+
                 if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].TotalCost != TotalCost ||
                     ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].AccountBalance != AccountBalance ||
                     ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].CostDiscount != CostDiscount)
@@ -6458,8 +6635,16 @@ void RunningFinalCostHandler(void)
                 ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].TotalCost = TotalCost;
                 ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].AccountBalance = AccountBalance;
                 ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].CostDiscount = CostDiscount;
+                ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].EnergyCost = EnergyCost;
+                ShmSysConfigAndInfo->SysInfo.ConnectorInfo[i].ParkingFee = OccupancyFee;
                 Set_Connector_MiscCommand(i, MISC_CONN_FINAL_COST);
 
+                if(receiptLength > 0)
+                {
+                    strcpy((char *)&ShmChargerInfo->PriceAndReceiptInfo.ReceiptUrl[i][0], receiptString);
+                    Set_Connector_MiscCommand(i, MISC_CONN_RECEIPT);
+                }
+
                 Clean_Ocpp_FinalCost(i);
             }
         }
@@ -7107,7 +7292,9 @@ void ChkOcppStatus(byte gunIndex)
                     LOG_INFO("Gun %d OCPP StopOnInvalidId", gunIndex + 1);
                 }
             }
-            LOG_INFO("Gun %d OCPP Start Transaction Accepted, TransactionId [%s]", gunIndex + 1, acceptId);
+            LOG_INFO("Gun %d Transaction [%s] Not Accepted, %s",
+                gunIndex + 1, acceptId,
+                chargingInfo[gunIndex]->ChargingStopFlag.bits.InvalidIdStop > 0 ? "And Stop Charging" : "But StopOnInvalidId is Disable");
         }
 
         Clean_Ocpp_StartTransactionConf(gunIndex);
@@ -8090,8 +8277,16 @@ void TheEndCharging(byte gun_index)
 {
     chargingInfo[gun_index]->isRemoteStart = NO;
 
-    //StopGunInfoTimeoutDet(gun_index);
-    //StartGunInfoTimeoutDet(gun_index, Timeout_EvseCompleteDet);
+    if(strlen((char *)&ShmSysConfigAndInfo->SysConfig.OcppReceiptrURL) > 0 && ShmChargerInfo->UserTransaction[gun_index].TransactionId > 0)
+    {
+        char receiptString[512];
+        sprintf(receiptString, "%s%d",
+            (char *)&ShmSysConfigAndInfo->SysConfig.OcppReceiptrURL[0], ShmChargerInfo->UserTransaction[gun_index].TransactionId);
+        strcpy((char *)&ShmChargerInfo->PriceAndReceiptInfo.ReceiptUrl[gun_index][0], receiptString);
+        Set_Connector_MiscCommand(gun_index, MISC_CONN_RECEIPT);
+        LOG_INFO("Gun %d ReceiptrURL: [%s]", gun_index + 1, receiptString);
+    }
+
     ChangeStartOrStopDateTime(NO, gun_index);
     DB_Insert_Record(localDb, gun_index);
 }
@@ -8582,6 +8777,15 @@ void ChkConnectorAction(void)
     }
 }
 
+void Update_DispenserAvailability(int dispenserIndex)
+{
+    for(int i = 0; i < ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].ConnectorQuantity; i++)
+    {
+        int gun = ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[dispenserIndex].ConnectorID[i] - 1;
+        Set_Connector_MiscCommand(gun, MISC_CONN_AVAILABILITY);
+    }
+}
+
 int main(void)
 {
     unsigned long time = 0;
@@ -8700,7 +8904,7 @@ int main(void)
         for(int _index=0; _index< ShmSysConfigAndInfo->SysConfig.TotalConnectorCount;_index++)
         {
             chargingInfo[_index]->PowerConsumption = DB_Get_PowerConsumption(localDb, _index);
-            LOG_INFO("Gun %d Consumption Initial: [%.1f kWh]", _index + 1, chargingInfo[_index]->PowerConsumption);
+            LOG_INFO("Gun %d Consumption Initial: [%.4f kWh]", _index + 1, chargingInfo[_index]->PowerConsumption);
         }
 
 		DB_Reboot_Record(localDb);
@@ -8736,7 +8940,7 @@ int main(void)
 			CheckFwUpdateFunction();
 		}
 
-        if(CheckWiringInfoUpdate() != YES)
+        if(CheckFlashUpdate() != YES)
         {
             // return fork process
             return 0;
@@ -8857,9 +9061,11 @@ int main(void)
                     {
                         LOG_INFO("==================    S_RESERVATION (%x)     ================== \n", gun_index + 1);
 
+                        char expiryDate[128];
+                        Get_Ocpp_ReserveNowExpiryDate(gun_index, expiryDate);
                         Get_Ocpp_ReserveNowIdTag(gun_index, &ShmChargerInfo->Control.ResevedIdTag[gun_index][0]);
                         Set_Connector_MiscCommand(gun_index, MISC_CONN_RESERVATION);
-                        LOG_INFO("****** Reservation IdTag: [%s] ******", &ShmChargerInfo->Control.ResevedIdTag[gun_index][0]);
+                        LOG_INFO("****** Reservation IdTag: [%s], Expiry: [%s]", &ShmChargerInfo->Control.ResevedIdTag[gun_index][0], expiryDate);
                         GetClockTime(&_SystemStatus_Time[gun_index]);
                     }
 
@@ -8876,13 +9082,15 @@ int main(void)
                     if(Is_Ocpp_ReserveNowExpired(gun_index))
                     {
                         chargingInfo[gun_index]->ReservationId = -1;
-                        LOG_INFO("Gun %d reservation time's up...", gun_index + 1);
+                        LOG_INFO("Gun %d reservation is expired...", gun_index + 1);
                         setChargerMode(gun_index, MODE_IDLE);
                     }
                     else
                     {
                         if(IsConnectorAuthorizeSuccess(gun_index))
                         {
+                            chargingInfo[gun_index]->ReservationId = -1;
+
                             if(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].AuthInfo.AuthType == _AuthType_RemoteStart)
                             {
                                 LOG_INFO("Gun %d remote start reserve charging", gun_index + 1);
@@ -8896,21 +9104,37 @@ int main(void)
                         }
                         else if(IsAutoGunSelectionAuthorizeSuccess(gun_index))
                         {
-                            SetAcContactor(ON);
+                            _dispenser = ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].ParentDispensetIndex;
 
-                            if(chargingInfo[gun_index]->ConnectorPlugIn &&
-                                ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].RemoteStatus == _CRS_Preparing)
+                            if(Is_Ocpp_ReserveNowIdTag(gun_index, (char *)ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[_dispenser].AuthInfo.AuthId))
                             {
-                                _dispenser = ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].ParentDispensetIndex;
-                                if(Is_Ocpp_ReserveNowIdTag(gun_index, (char *)ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[_dispenser].AuthInfo.AuthId))
+                                chargingInfo[gun_index]->ReservationId = -1;
+                                SetAcContactor(ON);
+
+                                if(chargingInfo[gun_index]->ConnectorPlugIn &&
+                                    ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].RemoteStatus == _CRS_Preparing)
                                 {
                                     strcpy((char *)chargingInfo[gun_index]->StartUserId, (char *)ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[_dispenser].AuthInfo.AuthId);
                                     LOG_INFO("Gun %d reserve Auto Selection, CardNumber = %s", gun_index + 1, chargingInfo[gun_index]->StartUserId);
-                                    DispenserAuthInitial(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].ParentDispensetIndex);
+
+                                    if(strlen((char *)&ShmChargerInfo->PriceAndReceiptInfo.DispenserPriceString[_dispenser][0]) > 0)
+                                    {
+                                        strcpy((char *)&ShmChargerInfo->PriceAndReceiptInfo.UserPriceString[gun_index], (char *)&ShmChargerInfo->PriceAndReceiptInfo.DispenserPriceString[_dispenser][0]);
+                                        Set_Connector_MiscCommand(gun_index, MISC_CONN_USER_PRICE_STRING);
+                                    }
+                                    DispenserAuthInitial(_dispenser);
                                     setChargerMode(gun_index, MODE_REASSIGN_CHECK);
                                 }
                             }
                         }
+                        else
+                        {
+                            if(chargingInfo[gun_index]->ReservationId == -1)
+                            {
+                                LOG_INFO("Gun %d reservation is clean", gun_index + 1);
+                                setChargerMode(gun_index, MODE_IDLE);
+                            }
+                        }
                     }
                     break;
 
@@ -8942,6 +9166,8 @@ int main(void)
                             ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].UserPrice = 0;
                             ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].TotalCost = 0;
                             ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].AccountBalance = -65535;
+                            ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].EnergyCost = -1;
+                            ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].ParkingFee = -1;
                             ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.AnnounceBalance = false;
                             ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].Parameter.bits.GetStartChargingSoc = false;
                             memset(&ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].AuthInfo, 0x00, sizeof(AuthorizingInfoData));
@@ -8974,6 +9200,7 @@ int main(void)
                             Clean_DeductInfo(gun_index);
                             Clean_Ocpp_TcciSerialNo(gun_index);
                             Clean_UserTransaction(gun_index);
+                            Clean_UserPriceAndReceipt(gun_index);
 
                             presentChargedEnergyClear(gun_index);
                             chargingInfo[gun_index]->PresentChargingPower = 0;
@@ -8984,6 +9211,13 @@ int main(void)
                             chargingInfo[gun_index]->ChargingProfilePower = -1;
                             chargingInfo[gun_index]->ChargingProfileCurrent = -1;
 
+                            if(ShmChargerInfo->Control.FCharging[gun_index].FCtrl.bits.WebApiTrigger)
+                            {
+                                ShmChargerInfo->Control.FCharging[gun_index].FCtrl.bits.EnableForceCharging = false;
+                                ShmChargerInfo->Control.FCharging[gun_index].FCtrl.bits.WebApiTrigger = false;
+                                // reset dispenser availability
+                                Update_DispenserAvailability(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].ParentDispensetIndex);
+                            }
                             // clean force charging info
                             memset(&ShmChargerInfo->Control.FCharging[gun_index], 0x00, sizeof(ForceCharging));
 
@@ -9093,6 +9327,11 @@ int main(void)
                                     _dispenser = ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].ParentDispensetIndex;
                                     strcpy((char *)chargingInfo[gun_index]->StartUserId, (char *)ShmSysConfigAndInfo->SysInfo.DispenserInfo.Dispenser[_dispenser].AuthInfo.AuthId);
                                     LOG_INFO("Gun %d Auto Selection, CardNumber = %s", gun_index + 1, chargingInfo[gun_index]->StartUserId);
+                                    if(strlen((char *)&ShmChargerInfo->PriceAndReceiptInfo.DispenserPriceString[_dispenser][0]) > 0)
+                                    {
+                                        strcpy((char *)&ShmChargerInfo->PriceAndReceiptInfo.UserPriceString[gun_index], (char *)&ShmChargerInfo->PriceAndReceiptInfo.DispenserPriceString[_dispenser][0]);
+                                        Set_Connector_MiscCommand(gun_index, MISC_CONN_USER_PRICE_STRING);
+                                    }
                                     DispenserAuthInitial(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].ParentDispensetIndex);
                                     setChargerMode(gun_index, MODE_REASSIGN_CHECK);
                                     continue;
@@ -9104,12 +9343,20 @@ int main(void)
                             {
                                 ShmChargerInfo->Control.FCharging[gun_index].FCtrl.bits.StartForceCharging = false;
                                 strcpy((char *)chargingInfo[gun_index]->StartUserId, "ChargingTest");
-                                LOG_INFO("Gun %d Start Force Charging", gun_index + 1);
+                                LOG_INFO("Gun %d Start Force Charging%s",
+                                    gun_index + 1,
+                                    ShmChargerInfo->Control.FCharging[gun_index].FCtrl.bits.WebApiTrigger > 0 ? ", Triggered by WebAPI" : "");
                                 if(ShmChargerInfo->Control.TestCtrl.bits.FChargingReleaseExtend)
                                 {
                                     ShmChargerInfo->Control.FCharging[gun_index].FCtrl.bits.EnableReleaseAndExtend = true;
                                     LOG_INFO("Gun %d Enable ReleaseAndExtend At Force Charging", gun_index + 1);
                                 }
+                                if(ShmChargerInfo->Control.FCharging[gun_index].FCtrl.bits.WebApiTrigger)
+                                {
+                                    LOG_INFO("Set Dispenser %d Inoperative",
+                                        ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].ParentDispensetIndex + 1);
+                                    Update_DispenserAvailability(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].ParentDispensetIndex);
+                                }
                                 setChargerMode(gun_index, MODE_REASSIGN_CHECK);
                                 continue;
                             }

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


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


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