Bläddra i källkod

2020.05.20 / TC Hsu

Actions: Merge D0.13 application code from model DS60.

         Include following:

         D0.10
         ---------------------------------------------------
         1. Porting ReadCmdline command.
         ===================================================

         D0.11
         ---------------------------------------------------
         1. Improve, add foolproof mechanism for RFID card scan feature.
         2. Bug fixed for fan speed setup error, modify fan speed control function,
            will not reference the fan speed feedback.
         3. Bug fixed for incomplete firmware version display in Web, When copy the
            firmware version from CAN data frame to share memory, modify the copy
            length from constant to the length of CAN data. Since the firmware version
            length of every sub-board may be different.
         4. Improve, add model name parsing function to dispatch PSU quantity.
         5. Improve, for smart charge feature, the new charging requirement will
            be paused until the ongoing charging process be stable.
         ===================================================

         D0.12
         ---------------------------------------------------
         1. Improve, for smart charge, add charging cancel feature when the charging
            process is waiting for PSU dispatch.
         2. Improve, Add dual CCS function support, but the precharge relay will not
            available for left side, instead, it will using the DC relay.
         3. Improve, for smart charge, add protection mechaism to current control
            function to prevent current drop when maximum charging feature.
         4. Improve, Add rating current setup feature for AC.
         ===================================================

         D0.13
         ---------------------------------------------------
         1. Bug fixed, resolve the freezing issue, for samrt charge, when one
            charging process stop, charging mode of the other one process will
            transfer form balance charging to maximum charging, if the translation
            still not completed, and the new charging requirement happend, the
            charging process will be freezed.
         2. Bug fixed, when charging start, before the available current obtained
            from PSU, the available current to EV board will using the defined
            maximum output current of PSU.
         3. Bug fixed, resolve the error code display fail issue for dual charger.

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

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

Files:

	modified:   Config.h
	modified:   FactoryConfig.c
	modified:   Module_EvComm.c
	modified:   Module_InternalComm.c
	modified:   Module_LcmControl.c
	modified:   Module_LcmControl.h
	modified:   Module_PsuComm.c
	modified:   Module_PsuComm.h
	modified:   ReadCmdline.c
	modified:   internalComm.c
	modified:   internalComm.h
	modified:   main.c
	new file:   web.sh
TC_Hsu 4 år sedan
förälder
incheckning
94d5daa34b

+ 17 - 0
EVSE/Projects/DM30/Apps/Config.h

@@ -70,11 +70,22 @@ enum _SYSTEM_STATUS
     S_NONE                              = 20,
 };
 
+enum _AC_SYSTEM_STATUS
+{
+    AC_SYS_NONE                         = 0,
+    AC_SYS_A                            = 1,
+    AC_SYS_B                            = 2,
+    AC_SYS_C                            = 3,
+    AC_SYS_D                            = 4,
+    AC_SYS_E                            = 5,
+};
+
 enum _GUN_TYPE
 {
     _Type_Chademo                       = 0,
     _Type_CCS_2                         = 1,
     _Type_GB                            = 2,
+    _Type_AC                            = 3,
 };
 
 enum _LCM_INDEX
@@ -149,4 +160,10 @@ enum _EXTRA_ERR_PROCESS
     _EXTRA_ERR_PROCESS_INOVP            = 2,
 };
 
+enum _CHARGER_TYPE
+{
+    _CHARGER_TYPE_IEC                   = 0,
+    _CHARGER_TYPE_UL                    = 1,
+};
+
 #endif /* CONFIG_H_ */

+ 3 - 2
EVSE/Projects/DM30/Apps/FactoryConfig.c

@@ -103,7 +103,7 @@ int main(int argc,char *argv[])
      */
     //********** System **********// udhcpc -i eth1 -s ./dhcp_script/eth1.script
     //
-    strcpy((char *)SysConfig.ModelName, "DWWU301U00W1PH");
+    strcpy((char *)SysConfig.ModelName, "DMYE301E00W2PH");
     strcpy((char *)SysConfig.SerialNumber, "");
 
     memset(SysConfig.SystemId, 0x00, sizeof(SysConfig.SystemId));
@@ -128,8 +128,9 @@ int main(int argc,char *argv[])
     SysConfig.isRFID = 1;
     //********** Charging **********//
     SysConfig.MaxChargingEnergy = 0;
-    SysConfig.MaxChargingCurrent = 65;      // 最大可輸出電流
+    SysConfig.MaxChargingCurrent = 60;      // 最大可輸出電流
     SysConfig.MaxChargingDuration = 0;
+    SysConfig.AcMaxChargingCurrent = 0;
     SysConfig.PhaseLossPolicy = 0;
     for(unsigned char i = 0; i < 10; i++)
         strcpy((char *)SysConfig.LocalWhiteCard, "");

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1919 - 232
EVSE/Projects/DM30/Apps/Module_EvComm.c


+ 531 - 177
EVSE/Projects/DM30/Apps/Module_InternalComm.c

@@ -39,6 +39,7 @@
 #define TEN_MINUTES         600
 #define ENV_TEMP_MIN        45
 #define ENV_TEMP_MAX        50
+#define DEFAULT_AC_INDEX    2
 
 struct SysConfigAndInfo         *ShmSysConfigAndInfo;
 struct StatusCodeData           *ShmStatusCodeData;
@@ -48,16 +49,19 @@ struct CHAdeMOData              *ShmCHAdeMOData;
 struct CcsData                  *ShmCcsData;
 struct PsuData                  *ShmPsuData;
 
-#define VIN_MAX_VOLTAGE     310 // 大於該值 : OVP
-#define VIN_MIN_VOLTAGE     150 // 小於該值 : UVP
+#define VIN_MAX_VOLTAGE_IEC     296 // 大於該值 : OVP
+#define VIN_MIN_VOLTAGE_IEC     166 // 小於該值 : UVP
+#define VIN_MAX_VOLTAGE_UL      305 // 大於該值 : OVP
+#define VIN_MIN_VOLTAGE_UL      215 // 小於該值 : UVP
+
 #define VIN_DROP_VOLTAGE    150 // 小於該值 : ac drop
 
-#define VOUT_MAX_VOLTAGE    750
+#define VOUT_MAX_VOLTAGE    995
 #define VOUT_MIN_VOLTAGE    150
 #define IOUT_MAX_CURRENT    50
 
 #define MAX_FAN_SPEED       13500
-#define MIN_FAN_SPEED       2800
+#define MIN_FAN_SPEED       3000
 #define NORMAL_FAN_SPEED    7000
 
 // GFD Status
@@ -77,8 +81,10 @@ struct PsuData                  *ShmPsuData;
 #define RELAY_WELDING_DET                   300
 
 byte gunCount;
+byte acgunCount;
 // 槍資訊
 struct ChargingInfoData *_chargingData[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
+struct ChargingInfoData *ac_chargingInfo[AC_QUANTITY];
 
 bool _isOutputNoneMatch[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
 struct timeval _checkOutputNoneMatchTimer[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
@@ -90,14 +96,20 @@ bool FindChargingInfoData(byte target, struct ChargingInfoData **chargingData);
 
 int Uart5Fd;
 char *relayRs485PortName = "/dev/ttyS5";
-unsigned short fanSpeedSmoothValue = 1000;
+unsigned short fanSpeedSmoothValue = 500;
 
 bool isStopChargingCount = false;
-bool isSystemBooting = false;
 struct timeval _close_ac_contactor;
 
 struct timeval _priority_time;
 
+struct timeval  _ac_charging_comp;
+struct timeval  _ac_preparing;
+struct timeb    _ac_startChargingTime;
+struct timeb    _ac_endChargingTime;
+
+unsigned short _setFanSpeed = 0;
+
 Ver ver;
 PresentInputVoltage inputVoltage;
 PresentOutputVoltage outputVoltage;
@@ -112,6 +124,37 @@ Relay outputRelay;
 Relay regRelay;
 Rtc rtc;
 
+Ac_Status acStatus;
+Ac_Led_Status ledStatus;
+Ac_Alarm_code acAlarmCode;
+Ac_Charging_energy acChargingEnergy;
+Ac_Charging_current acChargingCurrent;
+
+#define AC_OVP                      1
+#define AC_UVP                      2
+#define AC_OCP                      4
+#define AC_OTP                      8
+#define AC_GMI_FAULT                16
+#define AC_CP_ERROR                 32
+#define AC_AC_LEAKAGE               64
+#define AC_DC_LEAKAGE               128
+#define AC_SYSTEM_SELFTEST_FAULT    256
+#define AC_HANDSHAKE_TIMEOUT        512
+#define AC_EMC_STOP                 1024
+#define AC_RELAY_WELDING            2048
+#define AC_GF_MODULE_FAULT          4096
+#define AC_SHUTTER_FAULT            8192
+#define AC_LOCKER_FAULT             16384
+#define AC_POWER_DROP               32768
+#define AC_CIRCUIT_SHORT            65536
+#define AC_ROTARY_SWITCH_FAULT      131072
+#define AC_RELAY_DRIVE_FAULT        262144
+
+int _alarm_code[] = {AC_OVP, AC_UVP, AC_OCP, AC_OTP, AC_GMI_FAULT, AC_CP_ERROR, AC_AC_LEAKAGE
+        , AC_DC_LEAKAGE, AC_SYSTEM_SELFTEST_FAULT, AC_HANDSHAKE_TIMEOUT, AC_EMC_STOP, AC_RELAY_WELDING
+        , AC_GF_MODULE_FAULT, AC_SHUTTER_FAULT, AC_LOCKER_FAULT, AC_POWER_DROP, AC_CIRCUIT_SHORT
+        , AC_ROTARY_SWITCH_FAULT, AC_RELAY_DRIVE_FAULT};
+
 void PRINTF_FUNC(char *string, ...);
 
 int StoreLogMsg(const char *fmt, ...);
@@ -156,11 +199,11 @@ int StoreLogMsg(const char *fmt, ...)
 int DiffTimeb(struct timeb ST, struct timeb ET)
 {
     //return milli-second
-    unsigned int StartTime,StopTime;
+    unsigned int StartTime, StopTime;
 
-    StartTime=(unsigned int)ST.time;
-    StopTime=(unsigned int)ET.time;
-    return (StopTime-StartTime)*1000+ET.millitm-ST.millitm;
+    StartTime = (unsigned int) ST.time;
+    StopTime = (unsigned int) ET.time;
+    return (StopTime - StartTime);
 }
 
 unsigned short MaxValue(unsigned short value1, unsigned short value2)
@@ -223,6 +266,15 @@ void GetFwAndHwVersion_Relay()
     }
 }
 
+void GetFwVersion_AC()
+{
+    if (Query_FW_Ver(Uart5Fd, Addr.AcPlug, &ver) == PASS)
+    {
+        ac_chargingInfo[0]->SelfTest_Comp = YES;
+        strcpy((char *) ac_chargingInfo[0]->version, ver.Version_FW);
+    }
+}
+
 void SetRtcData_Relay()
 {
     struct timeb csuTime;
@@ -316,38 +368,77 @@ void GetPresentInputVol()
         ShmSysConfigAndInfo->SysInfo.InputVoltageT = ShmRelayModuleData->InputL3Volt = inputVoltage.L3N_L31;
 
         //********************************************************************************************************//
-        // VIN < 170
-        if (inputVoltage.L1N_L12 < VIN_MIN_VOLTAGE)
-            ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP = YES;
-        else
-            ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP = NO;
+        // Vin (UVP)
+        if (ShmSysConfigAndInfo->SysInfo.ChargerType == _CHARGER_TYPE_IEC)
+        {
+            if (inputVoltage.L1N_L12 < VIN_MIN_VOLTAGE_IEC)
+                ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP = YES;
+            else
+                ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP = NO;
 
-        if (inputVoltage.L2N_L23 < VIN_MIN_VOLTAGE)
-            ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP = YES;
-        else
-            ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP = NO;
+            if (inputVoltage.L2N_L23 < VIN_MIN_VOLTAGE_IEC)
+                ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP = YES;
+            else
+                ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP = NO;
 
-        if (inputVoltage.L3N_L31 < VIN_MIN_VOLTAGE)
-            ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP = YES;
-        else
-            ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP = NO;
+            if (inputVoltage.L3N_L31 < VIN_MIN_VOLTAGE_IEC)
+                ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP = YES;
+            else
+                ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP = NO;
+        }
+        else if (ShmSysConfigAndInfo->SysInfo.ChargerType == _CHARGER_TYPE_UL)
+        {
+            if (inputVoltage.L1N_L12 < VIN_MIN_VOLTAGE_UL)
+                ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP = YES;
+            else
+                ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP = NO;
+
+            if (inputVoltage.L2N_L23 < VIN_MIN_VOLTAGE_UL)
+                ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP = YES;
+            else
+                ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP = NO;
 
+            if (inputVoltage.L3N_L31 < VIN_MIN_VOLTAGE_UL)
+                ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP = YES;
+            else
+                ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP = NO;
+        }
         //********************************************************************************************************//
-        // VIN > 277
-        if (inputVoltage.L1N_L12 > VIN_MAX_VOLTAGE)
-            ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP = YES;
-        else
-            ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP = NO;
+        // Vin (OVP)
+        if (ShmSysConfigAndInfo->SysInfo.ChargerType == _CHARGER_TYPE_IEC)
+        {
+            if (inputVoltage.L1N_L12 > VIN_MAX_VOLTAGE_IEC)
+                ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP = YES;
+            else
+                ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP = NO;
 
-        if (inputVoltage.L2N_L23 > VIN_MAX_VOLTAGE)
-            ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP = YES;
-        else
-            ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP = NO;
+            if (inputVoltage.L2N_L23 > VIN_MAX_VOLTAGE_IEC)
+                ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP = YES;
+            else
+                ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP = NO;
 
-        if (inputVoltage.L3N_L31 > VIN_MAX_VOLTAGE)
-            ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP = YES;
-        else
-            ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP = NO;
+            if (inputVoltage.L3N_L31 > VIN_MAX_VOLTAGE_IEC)
+                ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP = YES;
+            else
+                ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP = NO;
+        }
+        else if (ShmSysConfigAndInfo->SysInfo.ChargerType == _CHARGER_TYPE_UL)
+        {
+            if (inputVoltage.L1N_L12 > VIN_MAX_VOLTAGE_UL)
+                ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP = YES;
+            else
+                ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP = NO;
+
+            if (inputVoltage.L2N_L23 > VIN_MAX_VOLTAGE_UL)
+                ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP = YES;
+            else
+                ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP = NO;
+
+            if (inputVoltage.L3N_L31 > VIN_MAX_VOLTAGE_UL)
+                ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP = YES;
+            else
+                ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP = NO;
+        }
     }
 }
 
@@ -449,11 +540,21 @@ void CheckK1K2RelayOutput(byte index)
 
             if(_chargingData[index]->Type == _Type_CCS_2)
             {
+                if (gunCount == 1)
+                {
                 if (regRelay.relay_event.bits.Gun1_N == YES && regRelay.relay_event.bits.CCS_Precharge == YES)
                     _chargingData[index]->RelayKPK2Status = YES;
                 else
                     _chargingData[index]->RelayKPK2Status = NO;
             }
+                else
+                {
+                    if (_chargingData[index]->SystemStatus == S_CCS_PRECHARGE_ST0)
+                        _chargingData[index]->RelayKPK2Status = YES;
+                    else
+                        _chargingData[index]->RelayKPK2Status = NO;
+                }
+            }
         }
         else if (_chargingData[index]->Evboard_id == 0x02)
         {
@@ -505,7 +606,7 @@ void GetGfdAdc()
     {
         for (int i = 0; i < gunCount; i++)
         {
-            if (_chargingData[i]->Type == 9)
+            if (_chargingData[i]->Type == 0x09 && !ShmSysConfigAndInfo->SysConfig.AlwaysGfdFlag)
             {
                 if ((_chargingData[i]->PresentChargingVoltage * 10) >= VOUT_MIN_VOLTAGE)
                     _chargingData[i]->GroundFaultStatus = GFD_PASS;
@@ -646,78 +747,22 @@ void GetAuxPower()
 void SetFanModuleSpeed()
 {
     // 調整風扇速度要漸進式 : 500 rpm/p
-    if (ShmFanModuleData->PresentFan1Speed != ShmFanModuleData->SetFan1Speed ||
-            ShmFanModuleData->PresentFan2Speed != ShmFanModuleData->SetFan2Speed ||
-            ShmFanModuleData->PresentFan3Speed != ShmFanModuleData->SetFan3Speed ||
-            ShmFanModuleData->PresentFan4Speed != ShmFanModuleData->SetFan4Speed)
-    {
-        //printf("ShmFanModuleData->SetFan1Speed = %d \n", ShmFanModuleData->SetFan1Speed);
-
-        FanSpeed _fanSpeed;
-
-        unsigned short speed = ShmFanModuleData->PresentFan1Speed + fanSpeedSmoothValue;
-        if (speed >= ShmFanModuleData->SetFan1Speed)
-            speed = ShmFanModuleData->SetFan1Speed;
-        _fanSpeed.speed[0] = speed;
-
-        speed = ShmFanModuleData->PresentFan2Speed + fanSpeedSmoothValue;
-        if (speed >= ShmFanModuleData->SetFan2Speed)
-            speed = ShmFanModuleData->SetFan2Speed;
-        _fanSpeed.speed[1] = speed;
-
-        speed = ShmFanModuleData->PresentFan3Speed + fanSpeedSmoothValue;
-        if (speed >= ShmFanModuleData->SetFan3Speed)
-            speed = ShmFanModuleData->SetFan3Speed;
-        _fanSpeed.speed[2] = speed;
+    FanSpeed _fanSpeed;
 
-        speed = ShmFanModuleData->PresentFan4Speed + fanSpeedSmoothValue;
-        if (speed >= ShmFanModuleData->SetFan4Speed)
-            speed = ShmFanModuleData->SetFan4Speed;
-        _fanSpeed.speed[3] = speed;
+    _setFanSpeed += fanSpeedSmoothValue;
 
-        if (Config_Fan_Speed(Uart5Fd, Addr.Fan, &_fanSpeed) == PASS)
-        {
-            //PRINTF_FUNC("successfully Fan\n");
-        }
-    }
-}
-
-void SetRelayModuleFanSpeed()
-{
-    // 調整風扇速度要漸進式 : 100 rpm/p
-    if (ShmFanModuleData->PresentFan1Speed != ShmFanModuleData->SetFan1Speed)
+    if (_setFanSpeed >= ShmFanModuleData->SetFan1Speed)
+        _setFanSpeed = ShmFanModuleData->SetFan1Speed;
     {
-        FanSpeed _fanSpeed;
-        unsigned short speed = 0;
-
-        if (ShmFanModuleData->SetFan1Speed > ShmFanModuleData->PresentFan1Speed)
-        {
-            speed = ShmFanModuleData->PresentFan1Speed + fanSpeedSmoothValue;
-            if (speed >= ShmFanModuleData->SetFan1Speed)
-                speed = ShmFanModuleData->SetFan1Speed;
-        }
-        else
-        {
-            speed = ShmFanModuleData->PresentFan1Speed - fanSpeedSmoothValue;
-            if (speed <= 0)
-                speed = ShmFanModuleData->SetFan1Speed;
-        }
-
-        _fanSpeed.speed[0] = speed & 0xff;
-        _fanSpeed.speed[1] = (speed >> 8) & 0xff;
-        ShmFanModuleData->PresentFan1Speed = speed;
-
-        Config_Fan_Speed(Uart5Fd, Addr.Relay, &_fanSpeed);
+        _fanSpeed.speed[0] = _setFanSpeed;
     }
-}
 
-void GetRelayModuleFanSpeed()
-{
-    PRINTF_FUNC("Get fan board speed \n");
-    if (Query_Fan_Speed(Uart5Fd, Addr.Relay, &fanSpeed) == PASS)
+    _fanSpeed.speed[1] = _setFanSpeed;
+    _fanSpeed.speed[2] = _setFanSpeed;
+    _fanSpeed.speed[3] = _setFanSpeed;
+    if (Config_Fan_Speed(Uart5Fd, Addr.Fan, &_fanSpeed) == PASS)
     {
-        ShmFanModuleData->PresentFan1Speed = fanSpeed.speed[0] + (fanSpeed.speed[1] >> 8);
-        PRINTF_FUNC("SystemFanRotaSpeed_1 = %d \n", fanSpeed.speed[0]);
+        //PRINTF_FUNC("successfully Fan\n");
     }
 }
 
@@ -735,7 +780,7 @@ void SetK1K2RelayStatus(byte index)
             else if (regRelay.relay_event.bits.Gun1_N == YES)
                 outputRelay.relay_event.bits.Gun1_N = NO;
 
-            if (_chargingData[index]->Type == _Type_CCS_2)
+            if (gunCount == 1 && _chargingData[index]->Type == _Type_CCS_2)
             {
                 if(regRelay.relay_event.bits.CCS_Precharge == YES)
                     outputRelay.relay_event.bits.CCS_Precharge = NO;
@@ -759,24 +804,25 @@ void SetK1K2RelayStatus(byte index)
             _chargingData[index]->SystemStatus <= S_CHARGING))
     {
         if (_chargingData[index]->RelayWeldingCheck == YES)
-    {
-        if (_chargingData[index]->Evboard_id == 0x01)
-        {
-            if(regRelay.relay_event.bits.Gun1_N == NO)
-                outputRelay.relay_event.bits.Gun1_N = YES;
-            else if (regRelay.relay_event.bits.Gun1_P == NO)
-                outputRelay.relay_event.bits.Gun1_P = YES;
-        }
-        else if (_chargingData[index]->Evboard_id == 0x02)
         {
-            if(regRelay.relay_event.bits.Gun2_N == NO)
-                outputRelay.relay_event.bits.Gun2_N = YES;
-            else if (regRelay.relay_event.bits.Gun2_P == NO)
-                outputRelay.relay_event.bits.Gun2_P = YES;
+            if (_chargingData[index]->Evboard_id == 0x01)
+            {
+                if(regRelay.relay_event.bits.Gun1_N == NO)
+                    outputRelay.relay_event.bits.Gun1_N = YES;
+                else if (regRelay.relay_event.bits.Gun1_P == NO)
+                    outputRelay.relay_event.bits.Gun1_P = YES;
+            }
+            else if (_chargingData[index]->Evboard_id == 0x02)
+            {
+                if(regRelay.relay_event.bits.Gun2_N == NO)
+                    outputRelay.relay_event.bits.Gun2_N = YES;
+                else if (regRelay.relay_event.bits.Gun2_P == NO)
+                    outputRelay.relay_event.bits.Gun2_P = YES;
+            }
         }
     }
-    }
-    else if ((_chargingData[index]->SystemStatus >= S_TERMINATING && _chargingData[index]->SystemStatus <= S_COMPLETE))
+    else if ((_chargingData[index]->SystemStatus >= S_TERMINATING &&
+            _chargingData[index]->SystemStatus <= S_COMPLETE))
     {
         if ((_chargingData[index]->PresentChargingCurrent * 10) <= SEFETY_SWITCH_RELAY_CUR)
         {
@@ -802,10 +848,13 @@ void SetK1K2RelayStatus(byte index)
         {
             if (_chargingData[index]->Type == _Type_CCS_2)
             {
-                if (regRelay.relay_event.bits.CCS_Precharge == NO)
-                    outputRelay.relay_event.bits.CCS_Precharge = YES;
-                else if (regRelay.relay_event.bits.CCS_Precharge == YES)
-                    outputRelay.relay_event.bits.Gun1_P = NO;
+                if (gunCount == 1)
+                {
+                    if (regRelay.relay_event.bits.CCS_Precharge == NO)
+                        outputRelay.relay_event.bits.CCS_Precharge = YES;
+                    else if (regRelay.relay_event.bits.CCS_Precharge == YES)
+                        outputRelay.relay_event.bits.Gun1_P = NO;
+                }
             }
         }
         else if (_chargingData[index]->Evboard_id == 0x02)
@@ -825,10 +874,13 @@ void SetK1K2RelayStatus(byte index)
         {
             if (_chargingData[index]->Type == _Type_CCS_2)
             {
-                if (regRelay.relay_event.bits.Gun1_P == NO)
-                    outputRelay.relay_event.bits.Gun1_P = YES;
-                else if(regRelay.relay_event.bits.Gun1_P == YES)
-                    outputRelay.relay_event.bits.CCS_Precharge = NO;
+                if (gunCount == 1)
+                {
+                    if (regRelay.relay_event.bits.Gun1_P == NO)
+                        outputRelay.relay_event.bits.Gun1_P = YES;
+                    else if(regRelay.relay_event.bits.Gun1_P == YES)
+                        outputRelay.relay_event.bits.CCS_Precharge = NO;
+                }
             }
         }
         else if (_chargingData[index]->Evboard_id == 0x02)
@@ -847,8 +899,8 @@ void SetK1K2RelayStatus(byte index)
 void CheckAcInputOvpStatus(byte index)
 {
     if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP == YES ||
-            ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP == YES ||
-            ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP == YES)
+        ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP == YES ||
+        ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP == YES)
     {
         _chargingData[index]->StopChargeFlag = YES;
     }
@@ -857,8 +909,8 @@ void CheckAcInputOvpStatus(byte index)
 void CheckPhaseLossStatus(byte index)
 {
     if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP == YES ||
-            ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP == YES ||
-            ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP == YES)
+        ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP == YES ||
+        ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP == YES)
     {
         _chargingData[index]->StopChargeFlag = YES;
     }
@@ -869,7 +921,7 @@ void SetParalleRelayStatus()
     if (gunCount >= 2 && ShmSysConfigAndInfo->SysInfo.IsAlternatvieConf == NO)
     {
         if (_chargingData[0]->SystemStatus == S_BOOTING || _chargingData[1]->SystemStatus == S_BOOTING ||
-                (_chargingData[0]->SystemStatus == S_IDLE && _chargingData[1]->SystemStatus == S_IDLE))
+            (_chargingData[0]->SystemStatus == S_IDLE && _chargingData[1]->SystemStatus == S_IDLE))
         {
             // 初始化~ 不搭橋接
             if (regRelay.relay_event.bits.Gun1_Parallel_P == YES)
@@ -880,7 +932,7 @@ void SetParalleRelayStatus()
         else
         {
             if (_chargingData[0]->IsReadyToCharging == YES ||
-                    _chargingData[1]->IsReadyToCharging == YES)
+                _chargingData[1]->IsReadyToCharging == YES)
             {
                 // ************需考慮在切換中 - 切開 relay 與搭回 relay 的時機點************
                 if (ShmSysConfigAndInfo->SysInfo.MainChargingMode == _MAIN_CHARGING_MODE_MAX)
@@ -926,6 +978,67 @@ void SetParalleRelayStatus()
     }
 }
 
+void CheckAlarmOccur()
+{
+    bool isErr = false;
+    for(byte count = 0; count < sizeof(_alarm_code)/sizeof(_alarm_code[0]); count++)
+    {
+        if (acAlarmCode.AcAlarmCode & _alarm_code[count])
+        {
+            isErr = true;
+            switch(_alarm_code[count])
+            {
+                case AC_OVP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcSystemInputOVP = YES; break;
+                case AC_UVP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcSystemInputUVP = YES; break;
+                case AC_OCP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemAcOutputOCP = YES; break;
+                case AC_OTP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemAmbientOTP = YES; break;
+                case AC_GMI_FAULT: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcGroundfaultFail = YES; break;
+                case AC_CP_ERROR: ShmStatusCodeData->InfoCode.InfoEvents.bits.PilotFault = YES; break;
+                case AC_AC_LEAKAGE: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.RcdTrip = YES; break;
+                case AC_DC_LEAKAGE: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.RcdTrip = YES; break;
+                case AC_SYSTEM_SELFTEST_FAULT: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.McuSelftestFail = YES; break;
+                case AC_HANDSHAKE_TIMEOUT: break;
+                case AC_EMC_STOP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.EmergencyStopTrip = YES; break;
+                case AC_RELAY_WELDING: ShmStatusCodeData->FaultCode.FaultEvents.bits.AcOutputRelayWelding = YES; break;
+                case AC_GF_MODULE_FAULT: ShmStatusCodeData->FaultCode.FaultEvents.bits.RcdSelfTestFail = YES; break;
+                case AC_SHUTTER_FAULT: break;
+                case AC_LOCKER_FAULT: ShmStatusCodeData->FaultCode.FaultEvents.bits.AcConnectorLockFail = YES; break;
+                case AC_POWER_DROP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputDrop = YES; break;
+                case AC_CIRCUIT_SHORT: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CircuitShort = YES; break;
+                case AC_ROTARY_SWITCH_FAULT: break;
+                case AC_RELAY_DRIVE_FAULT: ShmStatusCodeData->FaultCode.FaultEvents.bits.AcOutputRelayDrivingFault = YES; break;
+            }
+        }
+        else
+        {
+            switch(_alarm_code[count])
+            {
+                case AC_OVP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcSystemInputOVP = NO; break;
+                case AC_UVP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcSystemInputUVP = NO; break;
+                case AC_OCP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemAcOutputOCP = NO; break;
+                case AC_OTP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemAmbientOTP = NO; break;
+                case AC_GMI_FAULT: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcGroundfaultFail = NO; break;
+                case AC_CP_ERROR: ShmStatusCodeData->InfoCode.InfoEvents.bits.PilotFault = NO; break;
+                case AC_AC_LEAKAGE: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.RcdTrip = NO; break;
+                case AC_DC_LEAKAGE: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.RcdTrip = NO; break;
+                case AC_SYSTEM_SELFTEST_FAULT: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.McuSelftestFail = NO; break;
+                case AC_HANDSHAKE_TIMEOUT: break;
+                case AC_EMC_STOP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.EmergencyStopTrip = NO; break;
+                case AC_RELAY_WELDING: ShmStatusCodeData->FaultCode.FaultEvents.bits.AcOutputRelayWelding = NO; break;
+                case AC_GF_MODULE_FAULT: ShmStatusCodeData->FaultCode.FaultEvents.bits.RcdSelfTestFail = NO; break;
+                case AC_SHUTTER_FAULT: break;
+                case AC_LOCKER_FAULT: ShmStatusCodeData->FaultCode.FaultEvents.bits.AcConnectorLockFail = NO; break;
+                case AC_POWER_DROP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputDrop = NO; break;
+                case AC_CIRCUIT_SHORT: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CircuitShort = NO; break;
+                case AC_ROTARY_SWITCH_FAULT:  break;
+                case AC_RELAY_DRIVE_FAULT: ShmStatusCodeData->FaultCode.FaultEvents.bits.AcOutputRelayDrivingFault = NO; break;
+            }
+        }
+    }
+
+    ac_chargingInfo[0]->IsErrorOccur = isErr;
+}
+
 //==========================================
 // Init all share memory
 //==========================================
@@ -1120,6 +1233,17 @@ bool FindChargingInfoData(byte target, struct ChargingInfoData **chargingData)
     return false;
 }
 
+bool FindAcChargingInfoData(byte target, struct ChargingInfoData **acChargingData)
+{
+    if (target < AC_QUANTITY)
+    {
+        acChargingData[target] = &ShmSysConfigAndInfo->SysInfo.AcChargingData[target];
+        return true;
+    }
+
+    return false;
+}
+
 void Initialization()
 {
     bool isPass = false;
@@ -1142,6 +1266,25 @@ void Initialization()
             }
         }
     }
+
+    isPass = false;
+
+    if (acgunCount > 0)
+    {
+        while(!isPass)
+        {
+            isPass = true;
+            for (byte _index = 0; _index < acgunCount; _index++)
+            {
+                if (!FindAcChargingInfoData(_index, &ac_chargingInfo[0]))
+                {
+                    DEBUG_ERROR("EvComm : FindAcChargingInfoData false \n");
+                    isPass = false;
+                    break;
+                }
+            }
+        }
+    }
 }
 
 bool IsNoneMatchRelayStatus()
@@ -1197,7 +1340,7 @@ void MatchRelayStatus()
 void CheckRelayStatusByADC()
 {
     if (ShmRelayModuleData->Gun1FuseOutputVolt > 0 && ShmRelayModuleData->Gun1RelayOutputVolt > 0 &&
-            (ShmRelayModuleData->Gun1FuseOutputVolt == ShmRelayModuleData->Gun1RelayOutputVolt))
+        (ShmRelayModuleData->Gun1FuseOutputVolt == ShmRelayModuleData->Gun1RelayOutputVolt))
     {
         // Relay 前後電壓一致
         _chargingData[0]->RelayK1K2Status = 0x01;
@@ -1206,7 +1349,7 @@ void CheckRelayStatusByADC()
         _chargingData[0]->RelayK1K2Status = 0x00;
 
     if (ShmRelayModuleData->Gun2FuseOutputVolt > 0 && ShmRelayModuleData->Gun2RelayOutputVolt > 0 &&
-                (ShmRelayModuleData->Gun2FuseOutputVolt == ShmRelayModuleData->Gun2RelayOutputVolt))
+        (ShmRelayModuleData->Gun2FuseOutputVolt == ShmRelayModuleData->Gun2RelayOutputVolt))
     {
         // Relay 前後電壓一致
         _chargingData[1]->RelayK1K2Status = 0x01;
@@ -1238,13 +1381,14 @@ void CableCheckDetected(byte index)
     // Warning : Rgfd <= 150 歐/V 假設電壓為 500V 則~ Rgfd <= 75000 歐
     // Pre-Warning : 150 歐/V < Rgfd <= 500 歐/V 假設電壓為 500V 則 75000 歐 < Rgfd <= 250000
     // SO Normal : Rgfd > 500 歐/V 假設電壓為 500 V 則 Rgfd > 250000 歐
-    if (_chargingData[index]->Type >= _Type_Chademo && _chargingData[index]->Type <= _Type_GB)
+    if ((_chargingData[index]->Type >= _Type_Chademo && _chargingData[index]->Type <= _Type_GB) ||
+        (_chargingData[index]->Type == 0x09 && ShmSysConfigAndInfo->SysConfig.AlwaysGfdFlag))
     {
         if ((_chargingData[index]->SystemStatus >= S_PREPARING_FOR_EVSE && _chargingData[index]->SystemStatus <= S_CHARGING) ||
             (_chargingData[index]->SystemStatus >= S_CCS_PRECHARGE_ST0 && _chargingData[index]->SystemStatus <= S_CCS_PRECHARGE_ST1))
         {
             if (_chargingData[index]->SystemStatus == S_PREPARING_FOR_EVSE &&
-                    _chargingData[index]->RelayWeldingCheck == YES)
+                _chargingData[index]->RelayWeldingCheck == YES)
             {
                 SetGfdConfig(index, GFD_CABLECHK);
             }
@@ -1258,7 +1402,7 @@ void CableCheckDetected(byte index)
                 if (_chargingData[index]->Type == _Type_GB)
                     SetGfdConfig(index, GFD_IDLE);
                 else
-                SetGfdConfig(index, GFD_CHARGING);
+                    SetGfdConfig(index, GFD_CHARGING);
             }
         }
         else if(_chargingData[index]->SystemStatus == S_COMPLETE || _chargingData[index]->SystemStatus == S_PREPARNING
@@ -1275,9 +1419,9 @@ void CheckOutputPowerOverCarReq(byte index)
     float carV = _chargingData[index]->EvBatterytargetVoltage;
 
     if (_chargingData[index]->EvBatterytargetVoltage > 1500 &&
-            (_chargingData[index]->Type == _Type_Chademo ||
-                _chargingData[index]->Type == _Type_CCS_2 ||
-                _chargingData[index]->Type == _Type_GB))
+        (_chargingData[index]->Type == _Type_Chademo ||
+         _chargingData[index]->Type == _Type_CCS_2 ||
+         _chargingData[index]->Type == _Type_GB))
     {
         if (fireV >= (carV + (carV * 0.1)))
         {
@@ -1293,12 +1437,12 @@ void CheckOutputPowerOverCarReq(byte index)
 void CheckOutputVolNoneMatchFire(byte index)
 {
     if (_chargingData[index]->EvBatterytargetVoltage > 1500 &&
-            (_chargingData[index]->Type == _Type_Chademo ||
-                    _chargingData[index]->Type == _Type_CCS_2 ||
-                    _chargingData[index]->Type == _Type_GB))
+        (_chargingData[index]->Type == _Type_Chademo ||
+         _chargingData[index]->Type == _Type_CCS_2 ||
+         _chargingData[index]->Type == _Type_GB))
     {
         if (((_chargingData[index]->PresentChargingVoltage * 10) < _chargingData[index]->FireChargingVoltage - 300) ||
-                ((_chargingData[index]->PresentChargingVoltage * 10) > _chargingData[index]->FireChargingVoltage + 300))
+            ((_chargingData[index]->PresentChargingVoltage * 10) > _chargingData[index]->FireChargingVoltage + 300))
         {
             if (!_isOutputNoneMatch[index])
             {
@@ -1384,6 +1528,228 @@ void GetPsuTempForFanSpeed()
     }
 }
 
+void GetAcStatus()
+{
+    if (Query_AC_Status(Uart5Fd, Addr.AcPlug, &acStatus) == PASS)
+    {
+        ShmSysConfigAndInfo->SysConfig.AcRatingCurrent = acStatus.MaxCurrent;
+
+        if(ShmSysConfigAndInfo->SysConfig.AcMaxChargingCurrent == 0)
+            ShmSysConfigAndInfo->SysConfig.AcMaxChargingCurrent = ShmSysConfigAndInfo->SysConfig.AcRatingCurrent;
+
+    //              printf("CpStatus = %d \n", acStatus.CpStatus);
+    //              printf("CurLimit = %d \n", acStatus.CurLimit);
+    //              printf("PilotVol_P = %d \n", acStatus.PilotVol_P);
+    //              printf("PilotVol_N = %d \n", acStatus.PilotVol_N);
+    //              printf("LockStatus = %d \n", acStatus.LockStatus);
+    //              printf("RelayStatus = %d \n", acStatus.RelayStatus);
+    //              printf("ShutterStatus = %d \n", acStatus.ShutterStatus);
+    //              printf("MeterStatus = %d \n", acStatus.MeterStatus);
+    //              printf("PpStatus = %d \n", acStatus.PpStatus);
+    //              printf("MaxCurrent = %d \n", acStatus.MaxCurrent);
+    //              printf("RotateSwitchStatus = %d \n", acStatus.RelayStatus);
+    //              printf("============================== \n");
+    //
+    //              ac_chargingInfo[0]->SystemStatus = acStatus.CpStatus;
+    }
+}
+
+void GetAcAlarmCode()
+{
+    if (Query_AC_Alarm_Code(Uart5Fd, Addr.AcPlug, &acAlarmCode) == PASS)
+    {
+        CheckAlarmOccur();
+    }
+}
+
+unsigned char GetChargingEnergy()
+{
+    return Query_Charging_Energy(Uart5Fd, Addr.AcPlug, &acChargingEnergy);
+}
+
+unsigned char GetChargingCurrent()
+{
+    return Query_Charging_Current(Uart5Fd, Addr.AcPlug, &acChargingCurrent);
+}
+
+void ChangeLedStatus()
+{
+    if (ac_chargingInfo[0]->SystemStatus == S_IDLE)
+        ledStatus.ActionMode = 1;
+    else if (ac_chargingInfo[0]->SystemStatus == S_PREPARNING)
+        ledStatus.ActionMode = 3;
+    else if (ac_chargingInfo[0]->SystemStatus == S_CHARGING)
+        ledStatus.ActionMode = 4;
+
+    Config_LED_Status(Uart5Fd, Addr.AcPlug, &ledStatus);
+}
+
+void SetLegacyReq(byte _switch)
+{
+    Config_Legacy_Req(Uart5Fd, Addr.AcPlug, _switch);
+}
+
+void SetCpDuty(byte _value)
+{
+    Config_Ac_Duty(Uart5Fd, Addr.AcPlug, _value);
+}
+
+void ChangeToCsuMode()
+{
+    ac_chargingInfo[0]->IsModeChagned = Config_CSU_Mode(Uart5Fd, Addr.AcPlug);
+
+//  if (ac_chargingInfo[0]->IsModeChagned == PASS)
+//  {
+//      Config_Reset_MCU(Uart5Fd, Addr.AcPlug);
+//  }
+}
+
+void AcChargeTypeProcess()
+{
+    if (acgunCount > 0)
+    {
+        if (ac_chargingInfo[0]->SelfTest_Comp == NO)
+        {
+            ac_chargingInfo[0]->IsModeChagned = NO;
+            GetFwVersion_AC();
+        }
+        else if (ac_chargingInfo[0]->SelfTest_Comp == YES)
+        {
+            if (ac_chargingInfo[0]->IsModeChagned != PASS)
+            {
+                ChangeToCsuMode();
+                return;
+            }
+            GetAcStatus();
+            GetAcAlarmCode();
+
+            byte _status = S_NONE;
+            bool _isStatusChanged = false;
+
+            if (acStatus.CpStatus == AC_SYS_A || ac_chargingInfo[0]->IsErrorOccur)
+            {
+                if (ac_chargingInfo[0]->SystemStatus == S_CHARGING)
+                    _status = S_TERMINATING;
+                else if (ac_chargingInfo[0]->SystemStatus >= S_TERMINATING)
+                {
+                    if (GetTimeoutValue(_ac_charging_comp) >= 10000000)
+                        _status = S_IDLE;
+                }
+                else
+                    _status = S_IDLE;
+            }
+            else if (ac_chargingInfo[0]->SystemStatus >= S_PREPARNING &&
+                    ac_chargingInfo[0]->SystemStatus < S_CHARGING)
+            {
+                if (acStatus.CpStatus == AC_SYS_C && acStatus.RelayStatus == YES)
+                    _status = S_CHARGING;
+                else if (GetTimeoutValue(_ac_preparing) >= 30000000)
+                    _status = S_IDLE;
+            }
+            else if (acStatus.CpStatus == AC_SYS_B &&
+                     ac_chargingInfo[0]->IsAvailable &&
+                     !ac_chargingInfo[0]->IsErrorOccur &&
+                     (ShmSysConfigAndInfo->SysInfo.WaitForPlugit == YES ||
+                      ShmSysConfigAndInfo->SysConfig.AuthorisationMode == AUTH_MODE_DISABLE))
+            {
+                PRINTF_FUNC("** UserId = %s \n", ShmSysConfigAndInfo->SysConfig.UserId);
+                strcpy((char *)ac_chargingInfo[0]->StartUserId, (char *)ShmSysConfigAndInfo->SysConfig.UserId);
+                PRINTF_FUNC("** CardNumber = %s \n", ac_chargingInfo[0]->StartUserId);
+                strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+                ShmSysConfigAndInfo->SysInfo.WaitForPlugit = NO;
+                _status = S_PREPARNING;
+            }
+
+            //printf("_status = %d \n", _status);
+
+            if (_status != S_NONE && ac_chargingInfo[0]->SystemStatus != _status)
+            {
+                _isStatusChanged = true;
+                ac_chargingInfo[0]->SystemStatus = _status;
+            }
+
+            // 設定限制最大充電電流 >= 6 ~ <= 32
+            switch(ac_chargingInfo[0]->SystemStatus)
+            {
+                case S_IDLE:
+                {
+                    if (_isStatusChanged)
+                    {
+                        ac_chargingInfo[0]->PresentChargedEnergy = 0.0;
+                    }
+
+                    ChangeLedStatus();
+                }
+                    break;
+                case S_PREPARNING:
+                {
+                    if (_isStatusChanged)
+                    {
+                        ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_NONE;
+                        ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc = DEFAULT_AC_INDEX;
+                        gettimeofday(&_ac_preparing, NULL);
+                    }
+
+                    if (GetChargingEnergy() == PASS)
+                    {
+                        ac_chargingInfo[0]->PresentChargedEnergy = acChargingEnergy.Energy / 100;
+                    }
+
+                    SetLegacyReq(YES);
+                    ChangeLedStatus();
+                }
+                    break;
+                case S_CHARGING:
+                {
+                    if (_isStatusChanged)
+                    {
+                        ftime(&_ac_startChargingTime);
+                        ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc = DEFAULT_AC_INDEX;
+                    }
+
+                    if (GetChargingEnergy() == PASS)
+                        ac_chargingInfo[0]->PresentChargedEnergy = acChargingEnergy.Energy / 100;
+
+                    if (GetChargingCurrent() == PASS)
+                        ac_chargingInfo[0]->PresentChargingPower = (220 * (acChargingCurrent.OuputCurrentL1 / 10)) / 1000;
+
+                    ftime(&_ac_endChargingTime);
+                    ac_chargingInfo[0]->RemainChargingDuration = DiffTimeb(_ac_startChargingTime, _ac_endChargingTime);
+
+                    // 用以判斷是否有在輸出
+                    ac_chargingInfo[0]->IsCharging = acStatus.RelayStatus;
+
+                    SetCpDuty(ShmSysConfigAndInfo->SysConfig.AcMaxChargingCurrent);
+                    ChangeLedStatus();
+                }
+                    break;
+                case S_TERMINATING:
+                {
+                    if (_isStatusChanged)
+                    {
+                        gettimeofday(&_ac_charging_comp, NULL);
+                    }
+
+                    SetLegacyReq(NO);
+                    if (acStatus.RelayStatus == NO)
+                        ac_chargingInfo[0]->SystemStatus = S_COMPLETE;
+                }
+                    break;
+                case S_COMPLETE:
+                {
+                    if (_isStatusChanged)
+                    {
+                        gettimeofday(&_ac_charging_comp, NULL);
+                        ftime(&_ac_endChargingTime);
+                        ac_chargingInfo[0]->RemainChargingDuration = DiffTimeb(_ac_startChargingTime, _ac_endChargingTime);
+                    }
+                }
+                    break;
+            }
+        }
+    }
+}
+
 int main(void)
 {
     if(InitShareMemory() == FAIL)
@@ -1400,6 +1766,7 @@ int main(void)
     }
 
     gunCount = ShmSysConfigAndInfo->SysConfig.TotalConnectorCount;
+    acgunCount = ShmSysConfigAndInfo->SysConfig.AcConnectorCount;
     // Open Uart5 for RB
     Uart5Fd = InitComPort();
     Initialization();
@@ -1442,6 +1809,8 @@ int main(void)
             gettimeofday(&_priority_time, NULL);
         }
 
+        AcChargeTypeProcess();
+
         if (ShmRelayModuleData->SelfTest_Comp == YES)
         {
             // ==============優先權最高 10 ms ==============
@@ -1451,7 +1820,8 @@ int main(void)
             // 三相輸入電壓
             GetPresentInputVol();
 
-            // 讀取當前 relay 狀態
+            // 讀取當前 AC relay 狀態
+            regRelay.relay_event.bits.AC_Contactor = ShmSysConfigAndInfo->SysInfo.AcContactorStatus;
             //GetRelayOutputStatus();
 
             for (int i = 0; i < gunCount; i++)
@@ -1477,8 +1847,9 @@ int main(void)
                 }
 
                 if (_chargingData[i]->SystemStatus == S_BOOTING ||
-                    (_chargingData[i]->SystemStatus >= S_PREPARNING && _chargingData[i]->SystemStatus <= S_COMPLETE) ||
+                    (_chargingData[i]->SystemStatus >= S_REASSIGN_CHECK && _chargingData[i]->SystemStatus <= S_COMPLETE) ||
                     (_chargingData[i]->SystemStatus >= S_CCS_PRECHARGE_ST0 && _chargingData[i]->SystemStatus <= S_CCS_PRECHARGE_ST1) ||
+                    ShmSysConfigAndInfo->SysInfo.WaitForPlugit == YES ||
                     (ShmSysConfigAndInfo->SysInfo.PageIndex >= _LCM_AUTHORIZING && ShmSysConfigAndInfo->SysInfo.PageIndex <= _LCM_WAIT_FOR_PLUG))
                 {
                     _chargingData[i]->IsReadyToCharging = YES;
@@ -1511,12 +1882,6 @@ int main(void)
             // 橋接 relay
             SetParalleRelayStatus();
 
-            // 搭上 AC Contactor
-            if (isCharging)
-                outputRelay.relay_event.bits.AC_Contactor = YES;
-            else
-                outputRelay.relay_event.bits.AC_Contactor = NO;
-
             if (isCharging)
             {
                 isStopChargingCount = false;
@@ -1531,8 +1896,7 @@ int main(void)
                 }
                 else
                 {
-                    if (!isSystemBooting ||
-                        (outputRelay.relay_event.bits.AC_Contactor == YES && GetTimeoutValue(_close_ac_contactor) / 1000 >= (TEN_MINUTES * 1000)))
+                    if ((outputRelay.relay_event.bits.AC_Contactor == YES && GetTimeoutValue(_close_ac_contactor) / 1000 >= (TEN_MINUTES * 1000)))
                         outputRelay.relay_event.bits.AC_Contactor = NO;
                 }
             }
@@ -1541,8 +1905,7 @@ int main(void)
             if(IsNoneMatchRelayStatus())
             {
                 if (Config_Relay_Output(Uart5Fd, Addr.Relay, &outputRelay))
-            {
-                    regRelay.relay_event.bits.AC_Contactor = ShmSysConfigAndInfo->SysInfo.AcContactorStatus;
+                {
                     regRelay.relay_event.bits.CCS_Precharge = outputRelay.relay_event.bits.CCS_Precharge;
                     regRelay.relay_event.bits.Gun1_P = outputRelay.relay_event.bits.Gun1_P;
                     regRelay.relay_event.bits.Gun1_N = outputRelay.relay_event.bits.Gun1_N;
@@ -1571,19 +1934,16 @@ int main(void)
                 GetPsuTempForFanSpeed();
 
                 GetFanSpeed();
+                ShmSysConfigAndInfo->SysInfo.SystemFanRotaSpeed = _setFanSpeed;
+
                 gettimeofday(&_priority_time, NULL);
                 if (isCharging)
                 {
-                    if (ShmFanModuleData->PresentFan1Speed < MAX_FAN_SPEED ||
-                        ShmFanModuleData->PresentFan2Speed < MAX_FAN_SPEED ||
-                        ShmFanModuleData->PresentFan3Speed < MAX_FAN_SPEED ||
-                        ShmFanModuleData->PresentFan4Speed < MAX_FAN_SPEED)
-                    {
-                        ShmFanModuleData->SetFan1Speed = MAX_FAN_SPEED;
-                        ShmFanModuleData->SetFan2Speed = MAX_FAN_SPEED;
-                        ShmFanModuleData->SetFan3Speed = MAX_FAN_SPEED;
-                        ShmFanModuleData->SetFan4Speed = MAX_FAN_SPEED;
-                    }
+                    // 在還沒問到 PSU 溫度~ 還是要有個最小轉速
+                    ShmFanModuleData->SetFan1Speed = MIN_FAN_SPEED;
+                    ShmFanModuleData->SetFan2Speed = MIN_FAN_SPEED;
+                    ShmFanModuleData->SetFan3Speed = MIN_FAN_SPEED;
+                    ShmFanModuleData->SetFan4Speed = MIN_FAN_SPEED;
 
                     if (ShmFanModuleData->TestFanSpeed > 0)
                     {
@@ -1595,16 +1955,10 @@ int main(void)
                 }
                 else
                 {
-                    if (ShmFanModuleData->PresentFan1Speed > MIN_FAN_SPEED ||
-                        ShmFanModuleData->PresentFan2Speed > MIN_FAN_SPEED ||
-                        ShmFanModuleData->PresentFan3Speed > MIN_FAN_SPEED ||
-                        ShmFanModuleData->PresentFan4Speed > MIN_FAN_SPEED)
-                    {
-                        ShmFanModuleData->SetFan1Speed = MIN_FAN_SPEED;
-                        ShmFanModuleData->SetFan2Speed = MIN_FAN_SPEED;
-                        ShmFanModuleData->SetFan3Speed = MIN_FAN_SPEED;
-                        ShmFanModuleData->SetFan4Speed = MIN_FAN_SPEED;
-                    }
+                    ShmFanModuleData->SetFan1Speed = MIN_FAN_SPEED;
+                    ShmFanModuleData->SetFan2Speed = MIN_FAN_SPEED;
+                    ShmFanModuleData->SetFan3Speed = MIN_FAN_SPEED;
+                    ShmFanModuleData->SetFan4Speed = MIN_FAN_SPEED;
 
                     // 停止時,如溫度還是很高,則需要維持該轉速直到溫度降低
                     if (ShmFanModuleData->TestFanSpeed >= MAX_FAN_SPEED)

+ 196 - 11
EVSE/Projects/DM30/Apps/Module_LcmControl.c

@@ -471,6 +471,81 @@ bool FindChargingInfoData(byte target, struct ChargingInfoData **_chargingData)
     return false;
 }
 
+bool FindAcChargingInfoData(byte target, struct ChargingInfoData **acChargingData)
+{
+    if (target < AC_QUANTITY)
+    {
+        acChargingData[target] = &ShmSysConfigAndInfo->SysInfo.AcChargingData[target];
+        return true;
+    }
+
+    return false;
+}
+
+void ChangeAcBattMapAndValue(short page)
+{
+    if (page == _LCM_CHARGING)
+    {
+        if (isDiffStatus != _battery_display_ani)
+        {
+            isChangeBattMap = false;
+            isDiffStatus = _battery_display_ani;
+        }
+
+        if (ac_chargingInfo[0]->IsCharging && !isChangeBattMap)
+        {
+            isChangeBattMap = true;
+            if (ac_ani_battery_level == _BATTERY_LEVEL_FOR_MAP_LV5)
+            {
+                ChangeDisplay2Value(__batt_map, _battery_empty);
+                ac_ani_battery_level = _BATTERY_LEVEL_FOR_MAP_EMP;
+            }
+            else if (ac_ani_battery_level == _BATTERY_LEVEL_FOR_MAP_EMP)
+            {
+                ChangeDisplay2Value(__batt_map, _battery_cap_20);
+                ac_ani_battery_level = _BATTERY_LEVEL_FOR_MAP_LV1;
+            }
+            else if (ac_ani_battery_level == _BATTERY_LEVEL_FOR_MAP_LV1)
+            {
+                ChangeDisplay2Value(__batt_map, _battery_cap_40);
+                ac_ani_battery_level = _BATTERY_LEVEL_FOR_MAP_LV2;
+            }
+            else if (ac_ani_battery_level == _BATTERY_LEVEL_FOR_MAP_LV2)
+            {
+                ChangeDisplay2Value(__batt_map, _battery_cap_60);
+                ac_ani_battery_level = _BATTERY_LEVEL_FOR_MAP_LV3;
+            }
+            else if (ac_ani_battery_level == _BATTERY_LEVEL_FOR_MAP_LV3)
+            {
+                ChangeDisplay2Value(__batt_map, _battery_cap_80);
+                ac_ani_battery_level = _BATTERY_LEVEL_FOR_MAP_LV4;
+            }
+            else if (ac_ani_battery_level == _BATTERY_LEVEL_FOR_MAP_LV4)
+            {
+                ChangeDisplay2Value(__batt_map, _battery_cap_100);
+                ac_ani_battery_level = _BATTERY_LEVEL_FOR_MAP_LV5;
+            }
+        }
+    }
+    else if (page == _LCM_COMPLETE)
+    {
+        if (ac_ani_battery_level == _BATTERY_LEVEL_FOR_MAP_LV5)
+            ChangeDisplay2Value(__batt_map, _battery_soc_20);
+        else if (ac_ani_battery_level == _BATTERY_LEVEL_FOR_MAP_EMP)
+            ChangeDisplay2Value(__batt_map, _battery_soc_20);
+        else if (ac_ani_battery_level == _BATTERY_LEVEL_FOR_MAP_LV1)
+            ChangeDisplay2Value(__batt_map, _battery_soc_40);
+        else if (ac_ani_battery_level == _BATTERY_LEVEL_FOR_MAP_LV2)
+            ChangeDisplay2Value(__batt_map, _battery_soc_60);
+        else if (ac_ani_battery_level == _BATTERY_LEVEL_FOR_MAP_LV3)
+            ChangeDisplay2Value(__batt_map, _battery_soc_80);
+        else if (ac_ani_battery_level == _BATTERY_LEVEL_FOR_MAP_LV4)
+            ChangeDisplay2Value(__batt_map, _battery_soc_100);
+    }
+
+    ChangeDisplay2Value(__soc_value_charging, _disappear);
+}
+
 void ChangeBattMapAndValue(short page, int soc)
 {
 //  srand(time(NULL));
@@ -562,7 +637,7 @@ void ChangeChargingEnergyValue(float energy)
     byte value[10];
 
     memset(cmd, 0x00, sizeof(cmd));
-    if(energy > 0.05)
+    if (energy >= 0.05)
     {
         energy -= 0.05;
     }
@@ -765,7 +840,7 @@ void ProcessPageInfo()
         case _LCM_CHARGING:
         case _LCM_COMPLETE:
         {
-            if (_totalCount == 2)
+            if (_totalCount + acgunCount >= 2)
             {
                 ChangeDisplay2Value(__sel_gun_btn, _sel_gun_btn);
 
@@ -796,14 +871,91 @@ void ProcessPageInfo()
                 ChangeDisplay2Value(__sel_gun_btn, _disappear);
             }
 
-            // gun type and charging info
+            bool isShowAc = false;
+            if (acgunCount > 0)
+            {
+                if (ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc != NO_DEFINE)
+                {
+                    isShowAc = true;
+                    ChangeDisplay2Value(__gun_type_index + (2 * 2), _actype_light);
+
+                    if (_currentPage == _LCM_CHARGING)
+                    {
+                        ChangeAcBattMapAndValue(_LCM_CHARGING);
+                        if (ac_chargingInfo[0]->RemainChargingDuration >= 0)
+                            ChangeRemainTime(ac_chargingInfo[0]->RemainChargingDuration);
+                        else
+                            ChangeRemainTime(0);
+
+                        if (ac_chargingInfo[0]->PresentChargingPower >= 0.1)
+                            ChangeChargingPowerValue(ac_chargingInfo[0]->PresentChargingPower);
+                        else
+                            ChangeChargingPowerValue(0);
+
+                        if (ac_chargingInfo[0]->PresentChargedEnergy >= 0.1)
+                            ChangeChargingEnergyValue(ac_chargingInfo[0]->PresentChargedEnergy);
+                        else
+                            ChangeChargingEnergyValue(0);
+
+                        if (strcmp((char *)ac_chargingInfo[0]->StartUserId, "") == 0)
+                            ChangeDisplay2Value(__stop_method_btn, _stop_charging_btn);
+                        else
+                            ChangeDisplay2Value(__stop_method_btn, _stop_charging_btn_scan);
+                    }
+                    else if (_currentPage == _LCM_COMPLETE)
+                    {
+                        ChangeAcBattMapAndValue(_LCM_COMPLETE);
+                        if (ac_chargingInfo[0]->RemainChargingDuration >= 0)
+                            ChangeRemainTime(ac_chargingInfo[0]->RemainChargingDuration);
+                        else
+                            ChangeRemainTime(0);
+
+                        if (ac_chargingInfo[0]->PresentChargingPower >= 0.1)
+                            ChangeChargingPowerValue(ac_chargingInfo[0]->PresentChargingPower);
+                        else
+                            ChangeChargingPowerValue(0);
+
+                        if (ac_chargingInfo[0]->PresentChargedEnergy >= 0.1)
+                        {
+                            ChangeChargingEnergyValue(ac_chargingInfo[0]->PresentChargedEnergy);
+
+                            if (ShmSysConfigAndInfo->SysConfig.BillingData.isBilling &&
+                                    ac_chargingInfo[0]->ChargingFee >= 0)
+                            {
+                                ChangeChargingFeeValue(ac_chargingInfo[0]->ChargingFee);
+                            }
+                        }
+                        else
+                        {
+                            ChangeChargingEnergyValue(0);
+                            if (ShmSysConfigAndInfo->SysConfig.BillingData.isBilling)
+                                ChangeChargingFeeValue(0);
+                        }
+
+                        if(!ShmSysConfigAndInfo->SysConfig.BillingData.isBilling)
+                        {
+                            ChangeDisplay2Value(__charging_fee_map, _disappear);
+                            ChangeDisplay2Value(__charging_fee_tx, _disappear);
+                        }
+                        else
+                        {
+                            ChangeDisplay2Value(__charging_fee_map, _money_map);
+                        }
+                    }
+                }
+                else
+                    ChangeDisplay2Value(__gun_type_index + (2 * 2), _actype_dark);
+            }
+            else
+                ChangeDisplay2Value(__gun_type_index + (2 * 2), _disappear);
+
             for(byte i = 0; i < _totalCount; i++)
             {
                 switch(_chargingInfoData[i]->Type)
                 {
                     case _Type_Chademo:
                     {
-                        if (ShmSysConfigAndInfo->SysInfo.CurGunSelected == i)
+                        if (ShmSysConfigAndInfo->SysInfo.CurGunSelected == i && !isShowAc)
                         {
                             ChangeDisplay2Value(__gun_type_index + (i * 2), _chademo_light);
                         }
@@ -815,7 +967,7 @@ void ProcessPageInfo()
                         break;
                     case _Type_GB:
                     {
-                        if (ShmSysConfigAndInfo->SysInfo.CurGunSelected == i)
+                        if (ShmSysConfigAndInfo->SysInfo.CurGunSelected == i && !isShowAc)
                         {
                             ChangeDisplay2Value(__gun_type_index + (i * 2), _gbt_light);
                         }
@@ -827,7 +979,7 @@ void ProcessPageInfo()
                         break;
                     case _Type_CCS_2:
                     {
-                        if (ShmSysConfigAndInfo->SysInfo.CurGunSelected == i)
+                        if (ShmSysConfigAndInfo->SysInfo.CurGunSelected == i && !isShowAc)
                         {
                             ChangeDisplay2Value(__gun_type_index + (i * 2), _ccs_light);
                         }
@@ -839,7 +991,7 @@ void ProcessPageInfo()
                         break;
                 }
 
-                if (_currentPage == _LCM_CHARGING)
+                if (_currentPage == _LCM_CHARGING && !isShowAc)
                 {
                     if (ShmSysConfigAndInfo->SysInfo.CurGunSelected == i)
                     {
@@ -848,10 +1000,12 @@ void ProcessPageInfo()
                             ChangeRemainTime(_chargingInfoData[i]->RemainChargingDuration);
                         else
                             ChangeRemainTime(0);
+
                         if (_chargingInfoData[i]->PresentChargingPower >= 0)
                             ChangeChargingPowerValue(_chargingInfoData[i]->PresentChargingPower);
                         else
                             ChangeChargingPowerValue(0);
+
                         if (_chargingInfoData[i]->PresentChargedEnergy >= 0.1)
                             ChangeChargingEnergyValue(_chargingInfoData[i]->PresentChargedEnergy);
                         else
@@ -863,7 +1017,7 @@ void ProcessPageInfo()
                             ChangeDisplay2Value(__stop_method_btn, _stop_charging_btn_scan);
                     }
                 }
-                else if (_currentPage == _LCM_COMPLETE)
+                else if (_currentPage == _LCM_COMPLETE && !isShowAc)
                 {
                     if (ShmSysConfigAndInfo->SysInfo.CurGunSelected == i)
                     {
@@ -872,6 +1026,7 @@ void ProcessPageInfo()
                             ChangeRemainTime(_chargingInfoData[i]->RemainChargingDuration);
                         else
                             ChangeRemainTime(0);
+
                         if (_chargingInfoData[i]->PresentChargingPower >= 0)
                             ChangeChargingPowerValue(_chargingInfoData[i]->PresentChargingPower);
                         else
@@ -890,14 +1045,25 @@ void ProcessPageInfo()
                         else
                         {
                             ChangeChargingEnergyValue(0);
+                            if (ShmSysConfigAndInfo->SysConfig.BillingData.isBilling)
                             ChangeChargingFeeValue(0);
                         }
+
+                        if(!ShmSysConfigAndInfo->SysConfig.BillingData.isBilling)
+                        {
+                            ChangeDisplay2Value(__charging_fee_map, _disappear);
+                            ChangeDisplay2Value(__charging_fee_tx, _disappear);
+                        }
+                        else
+                        {
+                            ChangeDisplay2Value(__charging_fee_map, _money_map);
+                        }
                     }
                 }
             }
 
             // gun btn and QR code
-            if (_totalCount == 2 && _currentPage)
+            if (_totalCount + acgunCount >= 2 && _currentPage)
             {
                 byte index = 0;
                 for(index = 0; index < _totalCount; index++)
@@ -975,6 +1141,25 @@ void Initialization()
         }
     }
 
+    isPass = false;
+
+    if (acgunCount > 0)
+    {
+        while(!isPass)
+        {
+            isPass = true;
+            for (byte _index = 0; _index < acgunCount; _index++)
+            {
+                if (!FindAcChargingInfoData(_index, &ac_chargingInfo[0]))
+                {
+                    DEBUG_ERROR("EvComm : FindAcChargingInfoData false \n");
+                    isPass = false;
+                    break;
+                }
+            }
+        }
+    }
+
     if (count == 0)
         PRINTF_FUNC("LCM Initialization Gun Fail.............\n");
 }
@@ -997,11 +1182,11 @@ int main(void)
     _port = CreateCommunicationLcmPort();
     byte changeWarningPriority = 0;
     byte curWarningCount = 255;
-    //ChangeBackLight(true);
+    ChangeBackLight(true);
     _totalCount = ShmSysConfigAndInfo->SysConfig.TotalConnectorCount;
+    acgunCount = ShmSysConfigAndInfo->SysConfig.AcConnectorCount;
     Initialization();
 
-    //ChangeToOtherPage(_LCM_INIT);
     //return 0;
 
     while(_port != -1)

+ 18 - 0
EVSE/Projects/DM30/Apps/Module_LcmControl.h

@@ -41,6 +41,8 @@ struct SysConfigAndInfo         *ShmSysConfigAndInfo;
 struct StatusCodeData           *ShmStatusCodeData;
 struct FanModuleData            *ShmFanModuleData;
 
+#define NO_DEFINE           255
+
 #define CMD_TITLE_1             0x5A
 #define CMD_TITLE_2             0xA5
 #define CMD_READ                0x80
@@ -51,13 +53,28 @@ struct FanModuleData            *ShmFanModuleData;
 #define CMD_BACKLIGHT           0x01
 #define CMD_REGISTER            0x03
 
+enum _BATTERY_LEVEL_FOR_MAP
+{
+    _BATTERY_LEVEL_FOR_MAP_EMP = 0x00,
+    _BATTERY_LEVEL_FOR_MAP_LV1 = 0x01,
+    _BATTERY_LEVEL_FOR_MAP_LV2 = 0x02,
+    _BATTERY_LEVEL_FOR_MAP_LV3 = 0x03,
+    _BATTERY_LEVEL_FOR_MAP_LV4 = 0x04,
+    _BATTERY_LEVEL_FOR_MAP_LV5 = 0x05,
+};
+
 int _port;
 //char* pPortName = "/dev/ttyO2";
 char* pPortName = "/dev/ttyS3";
 char* moduleName = "DMT80480T070_09WT";
 byte _totalCount;
+byte acgunCount;
 struct ChargingInfoData *_chargingInfoData[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
+struct ChargingInfoData *ac_chargingInfo[AC_QUANTITY];
 
+byte ac_ani_battery_level = _BATTERY_LEVEL_FOR_MAP_LV5;
+byte isDiffStatus = false;
+byte isChangeBattMap = false;
 // 當前選擇的槍號
 short _currentPage = _LCM_NONE;
 short _oldPage = _LCM_NONE;
@@ -103,6 +120,7 @@ short __remain_time_tx = 0x0110;
 short __output_eng_tx = 0x0120;
 short __total_out_eng_tx = 0x0130;
 short __conn_line_comp = 0x0140;
+short __charging_fee_map = 0x0146;
 short __charging_fee_tx = 0x0150;
 
 short __money_by_rate = 0x0200;

+ 296 - 148
EVSE/Projects/DM30/Apps/Module_PsuComm.c

@@ -7,13 +7,16 @@
 #define NO                  0
 #define DERATING            30
 #define ELEMENT_NOT_FIND    255
-#define CHK_VOL_RANGE       20
+#define CHK_VOL_RANGE       50
 #define CHK_CUR_RANGE       10
 #define DERATING_RANGE      100
-#define ZERO_CURRENT        0
-#define ZERO_VOLTAGE        10
+#define ZERO_CURRENT        10          // 該值須保持最小為 1A
+#define ZERO_VOLTAGE        50
 #define STOP_CURRENT        30
-#define PSU_MIN_CUR         100
+#define PSU_MIN_CUR         1000
+#define PRE_CHARG_STEP_CUR  30
+#define PRE_CHARG_RANGE     5
+#define EQUAL               0
 
 struct SysConfigAndInfo         *ShmSysConfigAndInfo;
 struct StatusCodeData           *ShmStatusCodeData;
@@ -186,7 +189,7 @@ void AbnormalStopAnalysis(byte gun_index, int errCode)
                             ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuDcSideShutDown = YES;
                     }
                         break;
-                case 1:
+                    case 1:
                     {
                         if (bitIndex == 1)
                             ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuFailureAlarm = YES;
@@ -200,7 +203,7 @@ void AbnormalStopAnalysis(byte gun_index, int errCode)
                             ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuDcSideShutDown = YES;
                     }
                     break;
-                case 2:
+                    case 2:
                     {
                         if (bitIndex == 0)
                             ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuPowerLimitedState = YES;
@@ -331,7 +334,7 @@ void GetAvailableCapCallback(byte address, short maxVol, short minVol, short max
         ShmPsuData->PsuGroup[group].PsuModule[address].AvailableCurrent = maxCur;
 
     ShmPsuData->PsuGroup[group].PsuModule[address].AvailablePower = totalPow;
-
+    // 總和該 Group 的可輸出電流
     for (byte index = 0; index < ShmPsuData->PsuGroup[group].GroupPresentPsuQuantity; index++)
     {
         _groupCurrent += ShmPsuData->PsuGroup[group].PsuModule[index].AvailableCurrent;
@@ -345,19 +348,26 @@ void GetAvailableCapCallback(byte address, short maxVol, short minVol, short max
     chargingInfo[group]->MaximumChargingVoltage = maxVol;
 
     int _power = 0, _current = 0, _ratingcurrent = 0;
+    bool isGetAllDeratingCurrent = true;
+
     for (byte index = 0; index < ShmPsuData->GroupCount; index++)
     {
         _power += ShmPsuData->PsuGroup[index].GroupAvailablePower;
         _current += ShmPsuData->PsuGroup[index].GroupAvailableCurrent;
         _ratingcurrent += chargingInfo[index]->DeratingChargingCurrent;
+        if (chargingInfo[index]->DeratingChargingCurrent == 0)
+            isGetAllDeratingCurrent = false;
     }
 
+    // 如果不是所有群都得到 Derating current,則先不採樣該次的 ratingCurrent
+    if (!isGetAllDeratingCurrent) _ratingcurrent = 0;
+
     ShmPsuData->SystemAvailableCurrent = _current;
     ShmPsuData->SystemAvailablePower = _power;
 
     if (ShmSysConfigAndInfo->SysInfo.MainChargingMode == _MAIN_CHARGING_MODE_AVER ||
-            (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag >= _REASSIGNED_GET_NEW_CAP &&
-             ShmSysConfigAndInfo->SysInfo.ReAssignedFlag <= _REASSIGNED_RELAY_M_TO_A))
+        (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag >= _REASSIGNED_GET_NEW_CAP &&
+        ShmSysConfigAndInfo->SysInfo.ReAssignedFlag <= _REASSIGNED_RELAY_M_TO_A))
     {
         int halfPow = ShmPsuData->PsuGroup[group].GroupAvailablePower;
         int halfCur = ShmPsuData->PsuGroup[group].GroupAvailableCurrent;
@@ -382,23 +392,23 @@ void GetAvailableCapCallback(byte address, short maxVol, short minVol, short max
     }
     else if (ShmSysConfigAndInfo->SysInfo.MainChargingMode == _MAIN_CHARGING_MODE_MAX)
     {
-    GetMaxPowerAndCur(_MAIN_CHARGING_MODE_MAX, _ratingcurrent, &_power, &_current);
+        GetMaxPowerAndCur(_MAIN_CHARGING_MODE_MAX, _ratingcurrent, &_power, &_current);
 
-    if (ShmSysConfigAndInfo->SysInfo.IsAlternatvieConf == YES)
-    {
-            for (byte count = 0; count < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; count++)
+        if (ShmSysConfigAndInfo->SysInfo.IsAlternatvieConf == YES)
         {
-            chargingInfo[count]->MaximumChargingVoltage = maxVol;
-            chargingInfo[count]->AvailableChargingCurrent = _current;
-            chargingInfo[count]->AvailableChargingPower = _power;
+            for (byte count = 0; count < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; count++)
+            {
+                chargingInfo[count]->MaximumChargingVoltage = maxVol;
+                chargingInfo[count]->AvailableChargingCurrent = _current;
+                chargingInfo[count]->AvailableChargingPower = _power;
+            }
         }
-    }
-    else
-    {
+        else
+        {
             // 如果是最大充,該槍資訊中的輸出能力為各群輸出能力的和
-        chargingInfo[group]->AvailableChargingCurrent = _current;
-        chargingInfo[group]->AvailableChargingPower = _power;
-    }
+            chargingInfo[group]->AvailableChargingCurrent = _current;
+            chargingInfo[group]->AvailableChargingPower = _power;
+        }
     }
 }
 
@@ -409,6 +419,8 @@ void GetFwCallback(byte address, short dcSwVer, short pfcSwVer, short hwVer)
 
     byte group = FindTargetGroup(address);
 
+    sprintf((char *)ShmPsuData->PsuVersion[address].FwPrimaryVersion, "DC %d.%02d", (dcSwVer & 0xFF00) >> 8, dcSwVer & 0xFF);
+    sprintf((char *)ShmPsuData->PsuVersion[address].FwSecondVersion, "PFC %d.%02d", (pfcSwVer & 0xFF00) >> 8, pfcSwVer & 0xFF);
     if (group == 1)
         address -= ShmPsuData->PsuGroup[group - 1].GroupPresentPsuQuantity;
     sprintf((char *)ShmPsuData->PsuGroup[group].PsuModule[address].FwVersion, "DC %d.%02d", (dcSwVer & 0xFF00) >> 8, dcSwVer & 0xFF);
@@ -440,7 +452,11 @@ void GetPresentOutputCallback(byte group, unsigned short outVol, unsigned short
     // PSU Group - 電流
     ShmPsuData->PsuGroup[group].GroupPresentOutputCurrent = outputCur;
 
-    if (ShmSysConfigAndInfo->SysInfo.MainChargingMode == _MAIN_CHARGING_MODE_MAX)
+    if (ShmSysConfigAndInfo->SysInfo.MainChargingMode == _MAIN_CHARGING_MODE_MAX ||
+        (ShmSysConfigAndInfo->SysInfo.MainChargingMode == _MAIN_CHARGING_MODE_AVER &&
+        (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag >= _REASSIGNED_WAITING &&
+        ShmSysConfigAndInfo->SysInfo.ReAssignedFlag <= _REASSIGNED_COMP))
+        )
     {
         outputVol = 0;
         outputCur = 0;
@@ -520,16 +536,15 @@ void GetFanSpeedCallback(byte address, unsigned int fanSpeed)
 void GetIavailableCallback(byte address, unsigned short Iavail, unsigned short Vext)
 {
     if (IsOverModuleCount(address))
-            return;
+        return;
 
+    //PRINTF_FUNC("address = %d, Iavail = %d \n", address, Iavail);
     byte group = FindTargetGroup(address);
 
     if (group == 1)
         address -= ShmPsuData->PsuGroup[group - 1].GroupPresentPsuQuantity;
 
     //PRINTF_FUNC("group = %d, address_%d, Iavail = %d \n", group, address, Iavail);
-
-    // PSU Group - 電壓
     ShmPsuData->PsuGroup[group].PsuModule[address].IAvailableCurrent = Iavail;
 
     bool isPass = true;
@@ -563,7 +578,7 @@ void GetIavailableCallback(byte address, unsigned short Iavail, unsigned short V
                 {
                     chargingInfo[group]->SampleChargingCur[count] = totalCur;
                     isPass = false;
-                    continue;
+                    break;
                 }
             }
         }
@@ -571,6 +586,7 @@ void GetIavailableCallback(byte address, unsigned short Iavail, unsigned short V
 
     if (isPass)
     {
+        //PRINTF_FUNC("rating pass value = %d \n", totalCur);
         chargingInfo[group]->DeratingChargingCurrent = totalCur;
     }
 }
@@ -666,7 +682,7 @@ void Initialization()
         {
             if (!FindChargingInfoData(_index, &chargingInfo[0]))
             {
-                DEBUG_ERROR("EvComm (main) : FindChargingInfoData false \n");
+                DEBUG_ERROR("Module_PsuComm : FindChargingInfoData false \n");
                 isPass = false;
                 break;
             }
@@ -677,21 +693,80 @@ void Initialization()
         ShmPsuData->GroupCount = 1;
     else
         ShmPsuData->GroupCount = _gunCount;
-}
 
-void CheckSmartChargingStep(bool isCharging)
-{
-    if (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag == _REASSIGNED_PREPARE_M_TO_A)
+    char EvsePower[2];
+
+    EvsePower[2] = '\0';
+    char count = 0;
+    byte psuTarIndex = 0;
+    // 解析 ModelName 取得各槍各有幾個 PSU 及編號
+    if (strlen((char *) ShmSysConfigAndInfo->SysConfig.ModelName) >= 6)
     {
-        if (ShmSysConfigAndInfo->SysInfo.MainChargingMode == _MAIN_CHARGING_MODE_MAX)
+        strncpy(EvsePower, (char *)(ShmSysConfigAndInfo->SysConfig.ModelName + 4), 2);
+        if (strcmp(EvsePower, "15") == EQUAL)
+            count = 5;
+        else if (strcmp(EvsePower, "30") == EQUAL)
+            count = 1;
+        else if (strcmp(EvsePower, "60") == EQUAL)
+            count = 2;
+        else if (strcmp(EvsePower, "18") == EQUAL)
+            count = 6;
+        else if (strcmp(EvsePower, "36") == EQUAL)
+            count = 12;
+
+        if (count > 0)
         {
-            PRINTF_FUNC("=============Smart Charging : _REASSIGNED_GET_NEW_CAP============= Step 2 \n");
-            ShmSysConfigAndInfo->SysInfo.ReAssignedFlag = _REASSIGNED_GET_NEW_CAP;
+            if (ShmPsuData->GroupCount == 1)
+                conn_1_count = count;
+            else if (ShmPsuData->GroupCount == 2)
+            {
+                if(count % 2 > 0)
+                    conn_1_count = (count / 2) + 1;
+                else
+                    conn_1_count = (count / 2);
+
+                conn_2_count = count - conn_1_count;
+            }
+
+            for(byte psuIndex = 0; psuIndex < conn_1_count; psuIndex++)
+            {
+                connector_1[psuIndex] = psuTarIndex;
+                psuTarIndex++;
+            }
+
+            for(byte psuIndex = 0; psuIndex < conn_2_count; psuIndex++)
+            {
+                connector_2[psuIndex] = psuTarIndex;
+                psuTarIndex++;
+            }
+
+            for(byte psuIndex = 0; psuIndex < conn_1_count; psuIndex++)
+                PRINTF_FUNC("Connector 1 - Number = %d \n", connector_1[psuIndex]);
+
+            for(byte psuIndex = 0; psuIndex < conn_2_count; psuIndex++)
+                PRINTF_FUNC("Connector 2 - Number = %d \n", connector_2[psuIndex]);
         }
         else
+            DEBUG_ERROR("Module_PsuComm : Can't parsing model name. \n");
+    }
+}
+
+void CheckSmartChargingStep(bool isWaitingAver, bool isCharging)
+{
+    if (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag == _REASSIGNED_PREPARE_M_TO_A)
+    {
+        if (isWaitingAver)
         {
-            PRINTF_FUNC("=============Smart Charging : _REASSIGNED_NONE============= Step 0 \n");
-            ShmSysConfigAndInfo->SysInfo.ReAssignedFlag = _REASSIGNED_NONE;
+            if (ShmSysConfigAndInfo->SysInfo.MainChargingMode == _MAIN_CHARGING_MODE_MAX)
+            {
+                PRINTF_FUNC("=============Smart Charging : _REASSIGNED_GET_NEW_CAP============= Step 2 \n");
+                ShmSysConfigAndInfo->SysInfo.ReAssignedFlag = _REASSIGNED_GET_NEW_CAP;
+            }
+            else
+            {
+                PRINTF_FUNC("=============Smart Charging : _REASSIGNED_NONE============= Step 0 \n");
+                ShmSysConfigAndInfo->SysInfo.ReAssignedFlag = _REASSIGNED_NONE;
+            }
         }
     }
     else  if (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag ==  _REASSIGNED_PREPARE_A_TO_M)
@@ -705,10 +780,15 @@ void CheckSmartChargingStep(bool isCharging)
             }
             else
             {
-                PRINTF_FUNC("=============Smart Charging : _REASSIGNED_COMP============= Step 15 \n");
+                PRINTF_FUNC("=============Smart Charging_1  : _REASSIGNED_COMP============= Step 15 \n");
                 ShmSysConfigAndInfo->SysInfo.ReAssignedFlag = _REASSIGNED_COMP;
             }
         }
+        else
+        {
+            PRINTF_FUNC("=============Smart Charging_2 : _REASSIGNED_COMP============= Step 15 \n");
+            ShmSysConfigAndInfo->SysInfo.ReAssignedFlag = _REASSIGNED_COMP;
+        }
     }
 }
 
@@ -780,6 +860,7 @@ int main(void)
                 PRINTF_FUNC("== PSU == INITIAL_START \n");
                 gettimeofday(&_cmdSubPriority_time, NULL);
                 sleep(5);
+                SwitchPower(SYSTEM_CMD, PSU_POWER_OFF);
                 ShmPsuData->Work_Step = GET_PSU_COUNT;
             }
                 break;
@@ -790,7 +871,8 @@ int main(void)
 
                 if (time > 2000)
                 {
-                    PRINTF_FUNC("== PSU == %d \n", ShmPsuData->GroupCount);
+                    PRINTF_FUNC("== PSU == indexCount = %d, moduleCount = %d, sysCount = %d\n",
+                            ShmPsuData->GroupCount, moduleCount, ShmPsuData->SystemPresentPsuQuantity);
 //                  if (ShmPsuData->GroupCount == 0)
 //                      ShmPsuData->GroupCount = ShmSysConfigAndInfo->SysConfig.TotalConnectorCount;
                     // 分別取各群模組數量
@@ -866,19 +948,30 @@ int main(void)
                 break;
             case BOOTING_COMPLETE:
             {
+                bool isSelfTestPass = true;
+                for (byte groupIndex = 0; groupIndex < _gunCount; groupIndex++)
+                {
+                    if (chargingInfo[groupIndex]->SystemStatus == S_BOOTING)
+                    {
+                        isSelfTestPass = false;
+                    }
+                }
+
+                if (isSelfTestPass)
+                    ShmPsuData->Work_Step = _WORK_CHARGING;
                 sleep(1);
             }
                 break;
             case _WORK_CHARGING:
             {
                 int time = GetTimeoutValue(_cmdSubPriority_time) / 1000;
-                // sdlu - test
-                int testtime = GetTimeoutValue(_test_time) / 1000;
 
-                bool isCharging = false;
                 // 低 Priority 的指令
                 if (time > 1500)
                 {
+                    isCharging = false;
+                    isWaitingAver = false;
+                    isReadToCharging = false;
                     for (byte index = 0; index < ShmPsuData->GroupCount; index++)
                     {
                         // Pooling Status
@@ -894,39 +987,54 @@ int main(void)
                         GetModuleIavailable(index);
 
                         if (chargingInfo[index]->SystemStatus == S_CHARGING)
-                            isCharging = true;
-                    }
-
-                    for (byte gunIndex = 0; gunIndex < _gunCount; gunIndex++)
-                    {
-                        if (chargingInfo[gunIndex]->FireChargingVoltage > 0 &&
-                            evseOutVol != (chargingInfo[gunIndex]->FireChargingVoltage / 10))
                         {
-                            evseOutVol = (chargingInfo[gunIndex]->FireChargingVoltage / 10);
-                            PRINTF_FUNC("groupIndex = %d, evse output vol = %f \n", gunIndex,
-                                    chargingInfo[gunIndex]->FireChargingVoltage);
+                            isCharging = true;
+                            if (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag == _REASSIGNED_PREPARE_M_TO_A)
+                            {
+                                if (toAverVolPoint > 0 &&
+                                        toAverVolPoint == chargingInfo[index]->EvBatterytargetCurrent)
+                                {
+                                    // 欲最大充 -> 均充需要等待充電中的輸出電流拉高到目標電流
+                                    if ((chargingInfo[index]->PresentChargingCurrent * 10) >=
+                                        chargingInfo[index]->EvBatterytargetCurrent - CHK_CUR_RANGE)
+                                    {
+                                        if (toAverVolCount == 0)
+                                            isWaitingAver = true;
+                                        else
+                                            toAverVolCount--;
+                                    }
+                                }
+                                else
+                                {
+                                    toAverVolPoint = chargingInfo[index]->EvBatterytargetCurrent;
+                                    toAverVolCount = 3;
+                                }
+                            }
+                            else
+                            {
+                                toAverVolPoint = 0;
+                                toAverVolCount = 3;
+                            }
                         }
 
-                        if ((chargingInfo[gunIndex]->PresentChargingCurrent * 10) > 0 &&
-                            evseOutCur != (chargingInfo[gunIndex]->PresentChargingCurrent * 10))
+                        if ((chargingInfo[index]->SystemStatus >= S_PREPARING_FOR_EVSE && chargingInfo[index]->SystemStatus <= S_CHARGING) ||
+                            (chargingInfo[index]->SystemStatus >= S_CCS_PRECHARGE_ST0 && chargingInfo[index]->SystemStatus <= S_CCS_PRECHARGE_ST1))
                         {
-                            evseOutCur = (chargingInfo[gunIndex]->PresentChargingCurrent * 10);
-                            PRINTF_FUNC("groupIndex = %d, evse output cur = %f \n", gunIndex,
-                                (chargingInfo[gunIndex]->PresentChargingCurrent * 10));
+                            isReadToCharging = true;
                         }
                     }
 
                     gettimeofday(&_cmdSubPriority_time, NULL);
+                    CheckSmartChargingStep(isWaitingAver, isCharging);
                 }
 
-                CheckSmartChargingStep(isCharging);
                 for (byte groupIndex = 0; groupIndex < _gunCount; groupIndex++)
                 {
                     GetModuleOutput(groupIndex);
                     // 針對各槍當前狀態,傳送需要回傳的資料指令
                     if (((chargingInfo[groupIndex]->SystemStatus >= S_PREPARING_FOR_EVSE && chargingInfo[groupIndex]->SystemStatus <= S_CHARGING) && chargingInfo[groupIndex]->RelayK1K2Status) ||
-                            (chargingInfo[groupIndex]->SystemStatus >= S_PREPARING_FOR_EVSE && chargingInfo[groupIndex]->Type == _Type_GB) ||
-                            (chargingInfo[groupIndex]->SystemStatus >= S_CCS_PRECHARGE_ST0 && chargingInfo[groupIndex]->SystemStatus <= S_CCS_PRECHARGE_ST1))
+                        (chargingInfo[groupIndex]->SystemStatus >= S_PREPARING_FOR_EVSE && chargingInfo[groupIndex]->SystemStatus <= S_CHARGING && chargingInfo[groupIndex]->Type == _Type_GB) ||
+                        (chargingInfo[groupIndex]->SystemStatus >= S_CCS_PRECHARGE_ST0 && chargingInfo[groupIndex]->SystemStatus <= S_CCS_PRECHARGE_ST1))
                     {
                         if (chargingInfo[groupIndex]->EvBatterytargetVoltage > 0 &&
                             carReqVol != chargingInfo[groupIndex]->EvBatterytargetVoltage)
@@ -942,8 +1050,30 @@ int main(void)
                             DEBUG_INFO("ev need cur = %f \n", chargingInfo[groupIndex]->EvBatterytargetCurrent);
                         }
 
+                        if (time > 1500)
+                        {
+                            if (chargingInfo[groupIndex]->FireChargingVoltage > 0 &&
+                                evseOutVol != (chargingInfo[groupIndex]->FireChargingVoltage / 10))
+                            {
+                                evseOutVol = (chargingInfo[groupIndex]->FireChargingVoltage / 10);
+                                PRINTF_FUNC("groupIndex = %d, evse output vol = %f \n", groupIndex,
+                                    chargingInfo[groupIndex]->FireChargingVoltage);
+                            }
+
+                            if ((chargingInfo[groupIndex]->PresentChargingCurrent * 10) > 0 &&
+                                evseOutCur != (chargingInfo[groupIndex]->PresentChargingCurrent * 10))
+                            {
+                                evseOutCur = (chargingInfo[groupIndex]->PresentChargingCurrent * 10);
+                                PRINTF_FUNC("groupIndex = %d, evse output cur = %f \n", groupIndex,
+                                    (chargingInfo[groupIndex]->PresentChargingCurrent * 10));
+                            }
+                        }
+
                         if (ShmSysConfigAndInfo->SysInfo.MainChargingMode == _MAIN_CHARGING_MODE_MAX)
                         {
+//                          PRINTF_FUNC("index = %d, SystemStatus = %d, Ev = %f, curCur = %f \n", groupIndex,
+//                                  chargingInfo[groupIndex]->SystemStatus, chargingInfo[groupIndex]->EvBatterytargetCurrent,
+//                                  (chargingInfo[groupIndex]->PresentChargingCurrent * 10));
                             // 智能判斷 Start -----------------------------------------------------------
                             if (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag == _REASSIGNED_GET_NEW_CAP)
                             {
@@ -960,9 +1090,9 @@ int main(void)
                                         deratingKeepCount = 0;
                                     }
                                     else
-                        {
+                                    {
                                         deratingKeepCount++;
-                        }
+                                    }
                                 }
 
                             }
@@ -972,7 +1102,7 @@ int main(void)
 
                                 // 需求電流不降低的情況下 -> 依然要切
                                 if (chargingInfo[groupIndex]->AvailableChargingCurrent < chargingInfo[groupIndex]->EvBatterytargetCurrent)
-                        {
+                                {
                                     PRINTF_FUNC("** _REASSIGNED_ADJUST_M_TO_A ** Gun_%d, AvailableChargingCurrent = %f, EvBatterytargetCurrent = %f \n", groupIndex,
                                             (chargingInfo[groupIndex]->PresentChargingCurrent * 10),
                                             chargingInfo[groupIndex]->AvailableChargingCurrent);
@@ -980,7 +1110,7 @@ int main(void)
                                     {
                                         if (chargingInfo[subIndex]->SystemStatus == S_REASSIGN)
                                         {
-                                            if ((chargingInfo[subIndex]->PresentChargingCurrent * 10) <= CHK_CUR_RANGE)
+                                            if ((ShmPsuData->PsuGroup[subIndex].GroupPresentOutputCurrent) <= CHK_CUR_RANGE)
                                                 isChanged = true;
                                             break;
                                         }
@@ -988,16 +1118,24 @@ int main(void)
 
                                     // 這狀況下輸出端的電流載滿載衝的狀況下,並不會降電流
                                     // 所以只能拉載到該槍端的最大輸出能力
-                                    if ((chargingInfo[groupIndex]->PresentChargingCurrent * 10)>= chargingInfo[groupIndex]->AvailableChargingCurrent - CHK_CUR_RANGE ||
-                                            (chargingInfo[groupIndex]->PresentChargingCurrent * 10) <= CHK_CUR_RANGE)
-                                    {
-                                        isChanged = true;
-                                    }
+//                                  if ((chargingInfo[groupIndex]->PresentChargingCurrent * 10) >= chargingInfo[groupIndex]->AvailableChargingCurrent - CHK_CUR_RANGE ||
+//                                          (chargingInfo[groupIndex]->PresentChargingCurrent * 10) <= CHK_CUR_RANGE)
+//                                  {
+//                                      isChanged = true;
+//                                  }
                                 }
                                 else if (((chargingInfo[groupIndex]->PresentChargingCurrent * 10) >= ShmPsuData->PsuGroup[groupIndex].GroupPresentOutputCurrent - CHK_CUR_RANGE) &&
                                         ((chargingInfo[groupIndex]->PresentChargingCurrent * 10) <= ShmPsuData->PsuGroup[groupIndex].GroupPresentOutputCurrent + CHK_CUR_RANGE))
                                 {
-                                    isChanged = true;
+                                    for (byte subIndex = 0; subIndex < ShmPsuData->GroupCount; subIndex++)
+                                    {
+                                        if (chargingInfo[subIndex]->SystemStatus == S_REASSIGN)
+                                        {
+                                            if ((ShmPsuData->PsuGroup[subIndex].GroupPresentOutputCurrent) <= CHK_CUR_RANGE)
+                                                isChanged = true;
+                                            break;
+                                        }
+                                    }
                                 }
 
                                 if (isChanged)
@@ -1012,34 +1150,15 @@ int main(void)
                                 }
                             }
 
-                            // 智能判斷 End -----------------------------------------------------------
-                            if (testtime > 500 &&
-                                (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag >= _REASSIGNED_GET_NEW_CAP && ShmSysConfigAndInfo->SysInfo.ReAssignedFlag <= _REASSIGNED_RELAY_M_TO_A))
+                            if (ShmPsuData->SystemAvailablePower > 0)
                             {
-                                PRINTF_FUNC("Gun_%d, AvailableChargingCurrent = %f, AvailableChargingPower = %f \n", groupIndex,
-                                        chargingInfo[groupIndex]->AvailableChargingCurrent,
-                                        chargingInfo[groupIndex]->AvailableChargingPower);
-
-                                PRINTF_FUNC("Gun_%d, NeedVol = %f, NeedCur = %f \n", groupIndex,
-                                    chargingInfo[groupIndex]->EvBatterytargetVoltage,
-                                    chargingInfo[groupIndex]->EvBatterytargetCurrent);
-
-                                PRINTF_FUNC("Gun_%d OutputVol = %f, OutputCur = %f \n", groupIndex,
-                                        (chargingInfo[groupIndex]->PresentChargingVoltage * 10),
-                                        (chargingInfo[groupIndex]->PresentChargingCurrent * 10));
-
-                                gettimeofday(&_test_time, NULL);
-                        }
-
-                        if (ShmPsuData->SystemAvailablePower > 0)
-                        {
                                 // 調整輸出電流 : 漸進調整方式
                                 if (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag >= _REASSIGNED_ADJUST_M_TO_A)
                                 {
                                     // 當前充電中的目標電壓
                                     float targetVol = chargingInfo[groupIndex]->EvBatterytargetVoltage;
                                     // 當前充電中的目標電流
-                                    float targetCur = 0;
+                                    //float targetCur = 0;
                                     // 準備切出去的模塊電流
                                     float deratingCur = 0;
 
@@ -1070,10 +1189,11 @@ int main(void)
                                             }
                                         }
 
+                                        // ***********直接降低要移除的模塊電流即可*************
                                         // 因為爬的速度沒有降的速度快,所以採兩倍速度爬升
-                                        targetCur = ShmPsuData->PsuGroup[groupIndex].GroupPresentOutputCurrent + (DERATING_RANGE * 2);
-                                        if (targetCur >= chargingInfo[groupIndex]->EvBatterytargetCurrent)
-                                                targetCur = chargingInfo[groupIndex]->EvBatterytargetCurrent;
+//                                      targetCur = ShmPsuData->PsuGroup[groupIndex].GroupPresentOutputCurrent + (DERATING_RANGE * 2);
+//                                      if (targetCur >= chargingInfo[groupIndex]->EvBatterytargetCurrent)
+//                                              targetCur = chargingInfo[groupIndex]->EvBatterytargetCurrent;
 
                                         if (targetVol == 0)
                                         {
@@ -1089,24 +1209,24 @@ int main(void)
                                 }
                                 else
                                 {
-                            // 該充電槍的目標電壓與目標電流
-                            PresentOutputVol(SYSTEM_CMD,
-                                    chargingInfo[groupIndex]->EvBatterytargetVoltage,
-                                    chargingInfo[groupIndex]->EvBatterytargetCurrent);
+                                    // 該充電槍的目標電壓與目標電流
+                                    PresentOutputVol(SYSTEM_CMD,
+                                        chargingInfo[groupIndex]->EvBatterytargetVoltage,
+                                        chargingInfo[groupIndex]->EvBatterytargetCurrent);
 
-                            if (chargingInfo[groupIndex]->EvBatterytargetVoltage == 0)
-                            {
-                                SwitchPower(SYSTEM_CMD, PSU_POWER_OFF);
-                                FlashLed(SYSTEM_CMD, PSU_FLASH_NORMAL);
-                            }
-                            else
-                            {
-                                SwitchPower(SYSTEM_CMD, PSU_POWER_ON);
-                                FlashLed(SYSTEM_CMD, PSU_FLASH_ON);
+                                    if (chargingInfo[groupIndex]->EvBatterytargetVoltage == 0)
+                                    {
+                                        SwitchPower(SYSTEM_CMD, PSU_POWER_OFF);
+                                        FlashLed(SYSTEM_CMD, PSU_FLASH_NORMAL);
+                                    }
+                                    else
+                                    {
+                                        SwitchPower(SYSTEM_CMD, PSU_POWER_ON);
+                                        FlashLed(SYSTEM_CMD, PSU_FLASH_ON);
+                                    }
+                                }
                             }
                         }
-                    }
-                        }
                         else if (ShmSysConfigAndInfo->SysInfo.MainChargingMode == _MAIN_CHARGING_MODE_AVER)
                         {
                             // 智能判斷 Start -----------------------------------------------------------
@@ -1117,7 +1237,7 @@ int main(void)
                                 for (byte subIndex = 0; subIndex < ShmPsuData->GroupCount; subIndex++)
                                 {
                                     if (chargingInfo[subIndex]->SystemStatus == S_IDLE ||
-                                            chargingInfo[subIndex]->SystemStatus == S_RESERVATION)
+                                        chargingInfo[subIndex]->SystemStatus == S_RESERVATION)
                                     {
                                         // 各群電壓接近平衡
                                         if (((chargingInfo[subIndex]->PresentChargingVoltage * 10) < (chargingInfo[groupIndex]->PresentChargingVoltage * 10) - ZERO_VOLTAGE) ||
@@ -1137,60 +1257,63 @@ int main(void)
                                 {
                                     // 閒置端與車端要求電壓接近
                                     PRINTF_FUNC("=============Smart Charging : _REASSIGNED_RELAY_A_TO_M============= Step 13 \n");
+                                    preChargingCur = preChargingTarget = 0;
                                     ShmSysConfigAndInfo->SysInfo.ReAssignedFlag = _REASSIGNED_RELAY_A_TO_M;
-                                    GetTimeoutValue(_averageComp_time);
                                 }
                             }
                             else if(ShmSysConfigAndInfo->SysInfo.ReAssignedFlag == _REASSIGNED_WAITING)
                             {
-                                int avrTime = GetTimeoutValue(_averageComp_time) / 1000;
+                                int idleCurrent = 0;
+                                int chargingCurrent = 0;
 
-                                if (avrTime > 3000)
+                                for (byte subIndex = 0; subIndex < ShmPsuData->GroupCount; subIndex++)
                                 {
-                                    // 閒置端與車端要求電壓接近
-                                    PRINTF_FUNC("=============Smart Charging : _REASSIGNED_COMP============= Step 15 \n");
-                                    ShmSysConfigAndInfo->SysInfo.ReAssignedFlag = _REASSIGNED_COMP;
+                                    if (chargingInfo[subIndex]->SystemStatus == S_IDLE ||
+                                        chargingInfo[subIndex]->SystemStatus == S_RESERVATION ||
+                                        chargingInfo[subIndex]->SystemStatus == S_REASSIGN_CHECK)
+                                        idleCurrent = ShmPsuData->PsuGroup[subIndex].GroupPresentOutputCurrent;
+                                    else
+                                        chargingCurrent = ShmPsuData->PsuGroup[subIndex].GroupPresentOutputCurrent;
                                 }
-                            }
-                            // 智能判斷 End -----------------------------------------------------------
-                            if (testtime > 500 &&
-                                    (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag >= _REASSIGNED_ADJUST_A_TO_M && ShmSysConfigAndInfo->SysInfo.ReAssignedFlag <= _REASSIGNED_WAITING))
-                            {
-                                PRINTF_FUNC("Gun_%d, AvailableChargingCurrent = %f, AvailableChargingPower = %f \n", groupIndex,
-                                    chargingInfo[groupIndex]->AvailableChargingCurrent,
-                                    chargingInfo[groupIndex]->AvailableChargingPower);
-
-                                PRINTF_FUNC("Gun_%d, NeedVol = %f, NeedCur = %f \n", groupIndex,
-                                    chargingInfo[groupIndex]->EvBatterytargetVoltage,
-                                    chargingInfo[groupIndex]->EvBatterytargetCurrent);
 
-                                PRINTF_FUNC("Gun_%d OutputVol = %f, OutputCur = %f \n", groupIndex,
-                                    (chargingInfo[groupIndex]->PresentChargingVoltage * 10),
-                                    (chargingInfo[groupIndex]->PresentChargingCurrent * 10));
-
-                                gettimeofday(&_test_time, NULL);
+                                if (idleCurrent >= chargingCurrent - PRE_CHARG_RANGE)
+                                {
+                                    PRINTF_FUNC("=============Smart Charging_0 : _REASSIGNED_COMP============= Step 15 \n");
+                                    ShmSysConfigAndInfo->SysInfo.ReAssignedFlag = _REASSIGNED_COMP;
+                                }
                             }
 
                             if (chargingInfo[groupIndex]->AvailableChargingCurrent > 0)
                             {
-                                if (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag == _REASSIGNED_ADJUST_A_TO_M)
+                                if (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag >= _REASSIGNED_ADJUST_A_TO_M)
                                 {
                                     for (byte subIndex = 0; subIndex < ShmPsuData->GroupCount; subIndex++)
                                     {
                                         if (chargingInfo[subIndex]->SystemStatus == S_IDLE ||
-                                                chargingInfo[subIndex]->SystemStatus == S_RESERVATION)
+                                            chargingInfo[subIndex]->SystemStatus == S_RESERVATION ||
+                                            chargingInfo[subIndex]->SystemStatus == S_REASSIGN_CHECK)
                                         {
-                                            // 閒置模塊升壓
+                                            // 閒置模塊升壓,另對剛分配近來的模塊,預上升電流值 (preChargingCur)
                                             PresentOutputVol(subIndex,
                                                     chargingInfo[groupIndex]->EvBatterytargetVoltage,
-                                                    ZERO_CURRENT);
+                                                    ZERO_CURRENT + preChargingTarget);
+
+                                            preChargingCur = ShmPsuData->PsuGroup[subIndex].GroupPresentOutputCurrent;
                                         }
                                         else
                                         {
+                                            PRINTF_FUNC("CurOutputCurrent = %d \n", ShmPsuData->PsuGroup[subIndex].GroupPresentOutputCurrent + preChargingCur);
                                             // 充電中的模塊維持輸出
                                             PresentOutputVol(subIndex,
                                                 chargingInfo[subIndex]->EvBatterytargetVoltage,
-                                                chargingInfo[subIndex]->EvBatterytargetCurrent);
+                                                chargingInfo[subIndex]->EvBatterytargetCurrent - preChargingCur);
+
+                                            if ((ShmSysConfigAndInfo->SysInfo.ReAssignedFlag >= _REASSIGNED_WAITING) &&
+                                                (preChargingCur >= preChargingTarget - ZERO_CURRENT))
+                                                preChargingTarget += PRE_CHARG_STEP_CUR;
+
+                                            if (preChargingTarget >= chargingInfo[subIndex]->EvBatterytargetCurrent / 2)
+                                                preChargingTarget = chargingInfo[subIndex]->EvBatterytargetCurrent / 2;
                                         }
 
                                         if (chargingInfo[groupIndex]->EvBatterytargetVoltage == 0)
@@ -1226,28 +1349,53 @@ int main(void)
                         }
                     }
                     else if (chargingInfo[groupIndex]->SystemStatus >= S_TERMINATING &&
-                                chargingInfo[groupIndex]->SystemStatus <= S_COMPLETE)
+                             chargingInfo[groupIndex]->SystemStatus <= S_COMPLETE)
                     {
                         if (ShmSysConfigAndInfo->SysInfo.MainChargingMode == _MAIN_CHARGING_MODE_MAX)
                         {
-                            SwitchPower(SYSTEM_CMD, PSU_POWER_OFF);
-                            FlashLed(SYSTEM_CMD, PSU_FLASH_NORMAL);
+                            if (!isCharging)
+                            {
+                                SwitchPower(SYSTEM_CMD, PSU_POWER_OFF);
+                                FlashLed(SYSTEM_CMD, PSU_FLASH_NORMAL);
 
-                            if (chargingInfo[groupIndex]->SystemStatus == S_TERMINATING)
+                                if (chargingInfo[groupIndex]->SystemStatus == S_COMPLETE)
+                                {
+                                    if (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag >= _REASSIGNED_PREPARE_M_TO_A &&
+                                        ShmSysConfigAndInfo->SysInfo.ReAssignedFlag <= _REASSIGNED_RELAY_M_TO_A)
+                                    {
+                                        // 代表在切換的過程中,停止充電了
+                                        if ((chargingInfo[groupIndex]->PresentChargingCurrent * 10) <= STOP_CURRENT)
+                                            ShmSysConfigAndInfo->SysInfo.ReAssignedFlag = _REASSIGNED_RELAY_M_TO_A;
+                                    }
+                                }
+                            }
+                            else if (chargingInfo[groupIndex]->SystemStatus == S_COMPLETE)
                             {
+                                // 代表充電的槍依舊在充電,欲進入充電的槍取消充電了
                                 if (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag >= _REASSIGNED_PREPARE_M_TO_A &&
-                                        ShmSysConfigAndInfo->SysInfo.ReAssignedFlag <= _REASSIGNED_RELAY_M_TO_A)
+                                    ShmSysConfigAndInfo->SysInfo.ReAssignedFlag <= _REASSIGNED_RELAY_M_TO_A)
                                 {
-                                    // 代表在切換的過程中,停止充電了
-                                    if ((chargingInfo[groupIndex]->PresentChargingCurrent * 10) <= STOP_CURRENT)
-                                        ShmSysConfigAndInfo->SysInfo.ReAssignedFlag = _REASSIGNED_RELAY_M_TO_A;
+                                    ShmSysConfigAndInfo->SysInfo.ReAssignedFlag = _REASSIGNED_NONE;
                                 }
                             }
                         }
                         else if (ShmSysConfigAndInfo->SysInfo.MainChargingMode == _MAIN_CHARGING_MODE_AVER)
                         {
-                            SwitchPower(groupIndex, PSU_POWER_OFF);
-                            FlashLed(groupIndex, PSU_FLASH_NORMAL);
+                            if (!isReadToCharging)
+                            {
+                                SwitchPower(SYSTEM_CMD, PSU_POWER_OFF);
+                                FlashLed(SYSTEM_CMD, PSU_FLASH_NORMAL);
+                            }
+                            else
+                            {
+                                SwitchPower(groupIndex, PSU_POWER_OFF);
+                                FlashLed(groupIndex, PSU_FLASH_NORMAL);
+                            }
+
+                            if (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag >= _REASSIGNED_WAITING)
+                                ShmSysConfigAndInfo->SysInfo.ReAssignedFlag = _REASSIGNED_COMP;
+                            else
+                                ShmSysConfigAndInfo->SysInfo.ReAssignedFlag = _REASSIGNED_NONE;
                         }
                     }
                 }

+ 13 - 3
EVSE/Projects/DM30/Apps/Module_PsuComm.h

@@ -41,10 +41,20 @@ struct ChargingInfoData *chargingInfo[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANT
 
 struct timeval _cmdSubPriority_time;
 byte _getCapDelayCount;
-struct timeval _averageComp_time;
 struct timeval _derating_time;
 
 struct timeval _test_time;
 
-int connector_1[] = {0};
-int connector_2[] = {1};
+bool isCharging = false;
+bool isWaitingAver = false;
+bool isReadToCharging = false;
+int preChargingTarget;
+int preChargingCur;
+
+float toAverVolPoint;
+byte toAverVolCount;
+
+int connector_1[12];
+int connector_2[12];
+byte conn_1_count = 0;
+byte conn_2_count = 0;

+ 238 - 79
EVSE/Projects/DM30/Apps/ReadCmdline.c

@@ -42,6 +42,8 @@ typedef unsigned char           byte;
 #define PASS                1
 #define FAIL                -1
 #define ARRAY_SIZE(A)       (sizeof(A) / sizeof(A[0]))
+#define NO_DEFINE           255
+#define DEFAULT_AC_INDEX    2
 
 #define TTY_PATH            "/dev/tty"
 #define STTY_US             "stty raw -echo -F "
@@ -58,7 +60,7 @@ struct RelayModuleData          *ShmRelayModuleData;
 struct PsuData                  *ShmPsuData;
 
 struct ChargingInfoData         *_chargingData[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
-int gunCount = CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY;
+struct ChargingInfoData         *ac_chargingInfo[AC_QUANTITY];
 
 char *msg = "state : get gun state (index) \n"
         "card : scanning card (x) : \n"
@@ -100,6 +102,17 @@ bool FindChargingInfoData(byte target, struct ChargingInfoData **chargingData)
     return false;
 }
 
+bool FindAcChargingInfoData(byte target, struct ChargingInfoData **acChargingData)
+{
+    if (target < AC_QUANTITY)
+    {
+        acChargingData[target] = &ShmSysConfigAndInfo->SysInfo.AcChargingData[target];
+        return true;
+    }
+
+    return false;
+}
+
 int InitShareMemory()
 {
     int result = PASS;
@@ -113,7 +126,7 @@ int InitShareMemory()
     else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1)
     {
         result = FAIL;
-     }
+    }
     else
     {}
 
@@ -129,10 +142,9 @@ int InitShareMemory()
     else
     {}
 
-    if(CHAdeMO_QUANTITY > 0)
-    {
+    if (CHAdeMO_QUANTITY > 0) {
         if ((MeterSMId = shmget(ShmCHAdeMOCommKey, sizeof(struct CHAdeMOData),
-                IPC_CREAT | 0777)) < 0) {
+        IPC_CREAT | 0777)) < 0) {
             result = FAIL;
         } else if ((ShmCHAdeMOData = shmat(MeterSMId, NULL, 0))
                 == (void *) -1) {
@@ -141,10 +153,9 @@ int InitShareMemory()
         }
     }
 
-    if(CCS_QUANTITY > 0)
-    {
+    if (CCS_QUANTITY > 0) {
         if ((MeterSMId = shmget(ShmCcsCommKey, sizeof(struct CcsData),
-                IPC_CREAT | 0777)) < 0) {
+        IPC_CREAT | 0777)) < 0) {
             result = FAIL;
         } else if ((ShmCcsData = shmat(MeterSMId, NULL, 0)) == (void *) -1) {
             result = FAIL;
@@ -152,8 +163,7 @@ int InitShareMemory()
         }
     }
 
-    if (GB_QUANTITY > 0)
-    {
+    if (GB_QUANTITY > 0) {
         if ((MeterSMId = shmget(ShmGBTCommKey, sizeof(struct GBTData),
         IPC_CREAT | 0777)) < 0) {
             return 0;
@@ -205,37 +215,66 @@ int InitShareMemory()
 void RunStatusProc(char *v1, char *v2)
 {
     int _index = atoi(v1);
-    if (!FindChargingInfoData(_index, &_chargingData[0]))
+    if (_index <= 1)
     {
-        printf ("FindChargingInfoData error\n");
-        return;
-    }
+        if (!FindChargingInfoData(_index, &_chargingData[0]))
+        {
+            printf ("FindChargingInfoData error\n");
+            return;
+        }
 
-    if (strcmp(v2, "-1") == 0 || strcmp(v2, "") == 0)
-    {
-        // get
-        printf ("index = %x, status = %x (%d)\n", _index, _chargingData[_index]->SystemStatus, _chargingData[_index]->IsAvailable);
-        printf ("SystemTimeoutFlag = %d, PageIndex = %d\n",
-                ShmSysConfigAndInfo->SysInfo.SystemTimeoutFlag, ShmSysConfigAndInfo->SysInfo.PageIndex);
+        if (strcmp(v2, "-1") == 0 || strcmp(v2, "") == 0)
+        {
+            // get
+            printf ("index = %x, status = %x (%d)\n", _index, _chargingData[_index]->SystemStatus, _chargingData[_index]->IsAvailable);
+            printf ("SystemTimeoutFlag = %d, PageIndex = %d\n",
+                    ShmSysConfigAndInfo->SysInfo.SystemTimeoutFlag, ShmSysConfigAndInfo->SysInfo.PageIndex);
+        }
+        else
+        {
+            // set
+            _chargingData[_index]->SystemStatus = atoi(v2);
+        }
     }
     else
     {
-        // set
-        _chargingData[_index]->SystemStatus = atoi(v2);
+        if (!FindAcChargingInfoData(0, &ac_chargingInfo[0]))
+        {
+            printf("FindChargingInfoData (AC) false \n");
+        }
+
+        if (strcmp(v2, "-1") == 0 || strcmp(v2, "") == 0)
+        {
+            // get
+            printf ("AC Type, status = %x (%d)\n", ac_chargingInfo[0]->SystemStatus, ac_chargingInfo[0]->IsAvailable);
+        }
+        else
+        {
+            // set
+            ac_chargingInfo[0]->SystemStatus = atoi(v2);
+        }
     }
 }
 
 void RunCardProc(char *v1, char *v2)
 {
-    if (ShmSysConfigAndInfo->SysInfo.WaitForPlugit)
+    if (strcmp(v1, "-1") == 0 || strcmp(v1, "") == 0)
     {
-        ShmSysConfigAndInfo->SysInfo.WaitForPlugit = 0x00;
-        printf ("SysInfo.WaitForPlugit = %x \n", ShmSysConfigAndInfo->SysInfo.WaitForPlugit);
+        if (ShmSysConfigAndInfo->SysInfo.WaitForPlugit)
+        {
+            ShmSysConfigAndInfo->SysInfo.WaitForPlugit = 0x00;
+            printf ("SysInfo.WaitForPlugit = %x \n", ShmSysConfigAndInfo->SysInfo.WaitForPlugit);
+        }
+        else
+        {
+            ShmSysConfigAndInfo->SysInfo.WaitForPlugit = 0x01;
+            printf ("SysInfo.WaitForPlugit = %x \n", ShmSysConfigAndInfo->SysInfo.WaitForPlugit);
+        }
     }
     else
     {
-        ShmSysConfigAndInfo->SysInfo.WaitForPlugit = 0x01;
-        printf ("SysInfo.WaitForPlugit = %x \n", ShmSysConfigAndInfo->SysInfo.WaitForPlugit);
+        memcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, v1, ARRAY_SIZE(v1));
+        printf("StartUserId = %s \n", ShmSysConfigAndInfo->SysConfig.UserId);
     }
 }
 
@@ -313,6 +352,22 @@ void GetFwVerProc(char *v1)
     {
         printf("DC Main Version = %s \n", ShmSysConfigAndInfo->SysInfo.CsuRootFsFwRev);
     }
+    else if (strcmp(v1, "ac") == 0)
+    {
+        if (!FindAcChargingInfoData(0, &ac_chargingInfo[0]))
+        {
+            printf("FindChargingInfoData (AC) false \n");
+        }
+        printf("AC Version = %s \n", ac_chargingInfo[0]->version);
+    }
+}
+
+void CreateOneError(char *v1)
+{
+    int value = atoi(v1);
+
+    ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PrimaryStestFail = value;
+    ShmSysConfigAndInfo->SysConfig.BillingData.isBilling = value;
 }
 
 void FwUpdateFlagProc()
@@ -344,6 +399,10 @@ void SetPowerValue(char *v1, char *v2)
 {
     int _index = atoi(v1);
     float _Current = atof(v2);
+    // 盲沖的時候才允許使用~
+    if (_chargingData[_index]->Type != 9)
+        return;
+
     if (!FindChargingInfoData(_index, &_chargingData[0]))
     {
         printf ("FindChargingInfoData error\n");
@@ -361,15 +420,49 @@ void GetSystemInfo()
             ShmSysConfigAndInfo->SysConfig.MaxChargingCurrent);
 }
 
+void ChangeGunNum()
+{
+    if (ShmSysConfigAndInfo->SysInfo.CurGunSelected + 1 < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount)
+    {
+        ShmSysConfigAndInfo->SysInfo.CurGunSelected += 1;
+        ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc = NO_DEFINE;
+    }
+    else if (ShmSysConfigAndInfo->SysConfig.AcConnectorCount > 0 &&
+            ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc == NO_DEFINE)
+        ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc = DEFAULT_AC_INDEX;
+    else
+    {
+        ShmSysConfigAndInfo->SysInfo.CurGunSelected = 0;
+        ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc = NO_DEFINE;
+    }
+}
+
 void GetGunSelectedNum(char *v1)
 {
     if (strcmp(v1, "-1") == 0 || strcmp(v1, "") == 0)
-        printf("connector selected = %d \n", ShmSysConfigAndInfo->SysInfo.CurGunSelected);
+    {
+        if (AC_QUANTITY > 0 &&
+            ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc != NO_DEFINE)
+        {
+            printf("connector select changed = AC \n");
+        }
+        else
+            printf("connector selected = %d \n", ShmSysConfigAndInfo->SysInfo.CurGunSelected);
+    }
     else
     {
         int _index = atoi(v1);
-        ShmSysConfigAndInfo->SysInfo.CurGunSelected = _index;
-        printf("connector select changed = %d \n", _index);
+        if (_index <= 1)
+        {
+            ShmSysConfigAndInfo->SysInfo.CurGunSelected = _index;
+            ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc = NO_DEFINE;
+            printf("connector select changed = %d \n", _index);
+        }
+        else if (AC_QUANTITY > 0)
+        {
+            ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc = DEFAULT_AC_INDEX;
+            printf("connector select changed = AC \n");
+        }
     }
 }
 
@@ -395,6 +488,13 @@ void SetDebugMode(char *v1)
     ShmSysConfigAndInfo->SysConfig.SwitchDebugFlag = mode;
 }
 
+void SetGFDMode(char *v1)
+{
+    int mode = atoi(v1);
+
+    ShmSysConfigAndInfo->SysConfig.AlwaysGfdFlag = mode;
+}
+
 void GetPsuTemp()
 {
     for (byte index = 0; index < ShmPsuData->GroupCount; index++)
@@ -406,9 +506,17 @@ void GetPsuTemp()
     }
 }
 
+void GetAcInputVol()
+{
+    printf("L1N_L12 = %f, L2N_L23 = %f, L3N_L31 = %f \n",
+            ShmSysConfigAndInfo->SysInfo.InputVoltageR,
+            ShmSysConfigAndInfo->SysInfo.InputVoltageS,
+            ShmSysConfigAndInfo->SysInfo.InputVoltageT);
+}
+
 void GetPsuInformation(char *v1)
 {
-    printf("**********************須搭上 AC Contact*************************\n");
+    printf("**********************AC Contact needed*************************\n");
     if(strcmp(v1, "count") == 0)
     {
         for (int i = 0; i < 4; i++)
@@ -418,6 +526,12 @@ void GetPsuInformation(char *v1)
     }
     else if(strcmp(v1, "ver") == 0)
     {
+        for (int i = 0; i < ShmPsuData->SystemPresentPsuQuantity; i++)
+        {
+            printf("Psu Index = %d, PriVersion = %s, SecVersion = %s \n",
+                    i, ShmPsuData->PsuVersion[i].FwPrimaryVersion, ShmPsuData->PsuVersion[i].FwSecondVersion);
+        }
+
         for (int i = 0; i < ShmPsuData->GroupCount; i++)
         {
             for (int j = 0; j < ShmPsuData->PsuGroup[i].GroupPresentPsuQuantity; j++)
@@ -446,11 +560,31 @@ void GetPsuInformation(char *v1)
     printf("*************************************************\n");
 }
 
-static int get_char()
+void GetConnectorCapInfo(char *v1)
+{
+    int _GunIndex = atoi(v1);
+
+    if (!FindChargingInfoData(_GunIndex, &_chargingData[0]))
+    {
+        printf ("FindChargingInfoData error\n");
+        return;
+    }
+
+    printf ("Charger Max Current = %d, Max Power = %d \n",
+            ShmSysConfigAndInfo->SysConfig.MaxChargingCurrent * 10,
+            ShmSysConfigAndInfo->SysConfig.MaxChargingPower * 10);
+
+    printf ("Index = %d, MaxPow = %f, MaxVol = %f, MaxCur = %f\n",
+            _GunIndex,
+            _chargingData[_GunIndex]->RealMaxPower,
+            _chargingData[_GunIndex]->RealMaxVoltage,
+            _chargingData[_GunIndex]->RealMaxCurrent);
+}
+
+static void get_char(char *word)
 {
     fd_set rfds;
     struct timeval tv;
-    int ch = 0;
 
     FD_ZERO(&rfds);
     FD_SET(0, &rfds);
@@ -460,10 +594,8 @@ static int get_char()
     //if input
     if (select(1, &rfds, NULL, NULL, &tv) > 0)
     {
-        ch = getchar();
+        fgets(word, 128, stdin);
     }
-
-    return ch;
 }
 
 void RunUnconditionalChargeIndex1(char *v1, char *v2, char *v3)
@@ -472,7 +604,6 @@ void RunUnconditionalChargeIndex1(char *v1, char *v2, char *v3)
     float _Voltage = atof(v2);
     float _Current = atof(v3);
     unsigned char PreviousSystemStatus = 0xff;
-    int ch = 0;
 
     if (!FindChargingInfoData(_GunIndex, &_chargingData[0]))
     {
@@ -635,8 +766,8 @@ void RunUnconditionalChargeIndex1(char *v1, char *v2, char *v3)
                 }
                 else if (_chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->GroundFaultStatus > 0x02)
                 {
-                         printf ("First Ground Fault check Fail (%d)\n",_chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->GroundFaultStatus);
-                        _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus = S_TERMINATING;
+                    printf ("First Ground Fault check Fail (%d)\n",_chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->GroundFaultStatus);
+                    _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus = S_TERMINATING;
                 }
 
             }
@@ -658,7 +789,8 @@ void RunUnconditionalChargeIndex1(char *v1, char *v2, char *v3)
                 }
 
                 //ev task do this
-                _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->PresentChargingPower = ((float)((_chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->PresentChargingVoltage) * (_chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->PresentChargingCurrent)) / 1000);
+                _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->PresentChargingPower =
+                        ((float)((_chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->PresentChargingVoltage) * (_chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->PresentChargingCurrent)) / 1000);
 
                 if (_chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->GroundFaultStatus == 0x02){
                      printf ("Charging Ground Fault check Fail (%d)\n",_chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->GroundFaultStatus);
@@ -699,7 +831,6 @@ void RunUnconditionalChargeIndex1(char *v1, char *v2, char *v3)
                     PreviousSystemStatus = _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus;
 
                     printf ("[UnconditionalCharge - S_COMPLETE]\n");
-
                 }
                 sleep(3);
                 return;
@@ -707,51 +838,60 @@ void RunUnconditionalChargeIndex1(char *v1, char *v2, char *v3)
             break;
         }
 
-        /*
-        //使用 Keyboard input 阻塞方法
-        fgets(InputChar, sizeof(InputChar), stdin);
+        char word[128];
+        char newString[7][10];
+        int i,j,ctr;
 
-        if (InputChar[0] == 's' && InputChar[1] == 't' && InputChar[2] == 'o' && InputChar[3] == 'p')
-        {
-           printf ("Precharge Done\n");
-           _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus = S_TERMINATING;
+        memset(word, 0x00, sizeof(word));
+        get_char(word);
 
-        }
-        */
+        if (strlen(word) == 0)
+            continue;
 
-        //使用 keybaord input 非阻塞方法
-        ch = get_char();
-        if (ch)
+        j=0; ctr=0;
+        strcpy(newString[1], "-1");
+        strcpy(newString[2], "-1");
+        for (i = 0; i <= (strlen(word)); i++)
         {
-            printf("%c \n\r", ch);
-
-            switch (ch)
+            if (word[i] == ' ' || word[i] == '\0' || word[i] == 10)
             {
-                //Ctrl + C
-                case 3:
-                    //system(STTY_DEF TTY_PATH);
-                        return;
-                //input c or C
-                case 'c':
-                case 'C':
-                    printf("stop \n\r");
-                    //system(STTY_DEF TTY_PATH);
-                    ShmSysConfigAndInfo->SysInfo.StartToChargingFlag = 0x00;
-                    _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus = S_TERMINATING;
-                    break;
+                newString[ctr][j] = '\0';
+                ctr++;
+                j = 0;
+            }
+            else
+            {
+                newString[ctr][j] = word[i];
+                j++;
             }
         }
 
-    }
+        if(strcmp(newString[0], "chg") == 0)
+        {
+            if (strcmp(newString[1], "-1") == 0 || strcmp(newString[1], "") == 0)
+               continue;
+            if (strcmp(newString[2], "-1") == 0 || strcmp(newString[2], "") == 0)
+               continue;
 
-}
+            float _vol = atof(newString[1]);
+            float _cur = atof(newString[2]);
 
-void test()
-{
-    printf("L1 = %d, L2 = %d, L3 = %d \n", ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP,
-            ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP,
-            ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP);
-    printf("ExtraErrProcess = %d \n", ShmSysConfigAndInfo->SysWarningInfo.ExtraErrProcess);
+            if (_cur <= 0 || _cur <= 0)
+               continue;
+
+            printf("vol = %f, cur = %f \n", _vol, _cur);
+            _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->EvBatterytargetVoltage = _vol * 10;
+            _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->EvBatterytargetCurrent = _cur * 10;
+        }
+        else if (strcmp(newString[0], "c") == 0)
+        {
+            printf("stop \n\r");
+            ShmSysConfigAndInfo->SysInfo.StartToChargingFlag = 0x00;
+            _chargingData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus = S_TERMINATING;
+        }
+
+        usleep(100000);
+    }
 }
 
 int main(void)
@@ -869,9 +1009,14 @@ int main(void)
         }
         else if(strcmp(newString[0], "select") == 0)
         {
-            // 取得當前選的槍號
+            // 取得 / 設定 當前選的槍號
             GetGunSelectedNum(newString[1]);
         }
+        else if(strcmp(newString[0], "change") == 0)
+        {
+            // 模擬按鈕改變選槍
+            ChangeGunNum();
+        }
         else if(strcmp(newString[0], "fan") == 0)
         {
             // 設定風扇速度
@@ -887,11 +1032,21 @@ int main(void)
             // 設定 debug mode
             SetDebugMode(newString[1]);
         }
+        else if (strcmp(newString[0], "gfd") == 0)
+        {
+            // 設定盲沖使用 GFD 功能
+            SetGFDMode(newString[1]);
+        }
         else if(strcmp(newString[0], "temp") == 0)
         {
             // 取得 PSU 溫度
             GetPsuTemp();
         }
+        else if(strcmp(newString[0], "acin") == 0)
+        {
+            // 取得三向輸入電壓
+            GetAcInputVol();
+        }
         else if(strcmp(newString[0], "psu") == 0)
         {
             //如果連一個參數都沒有 (此命令不理會) 加上判斷第二參數
@@ -904,9 +1059,13 @@ int main(void)
             // 取得 PSU 資訊
             GetPsuInformation(newString[1]);
         }
-        else if(strcmp(newString[0], "test") == 0)
+        else if (strcmp(newString[0], "cap") == 0)
+        {
+            GetConnectorCapInfo(newString[1]);
+        }
+        else if(strcmp(newString[0], "error") == 0)
         {
-            test();
+            CreateOneError(newString[1]);
         }
         else if(strcmp(newString[0], "strchg") == 0)
         {

+ 319 - 11
EVSE/Projects/DM30/Apps/internalComm.c

@@ -38,8 +38,9 @@
 #define PASS                1
 #define FAIL                -1
 
-struct Address Addr={0x01,0x02,0x03,0xFF};
-struct Command Cmd={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x81,0x83,0x85,0x86, 0x87,0x8B,0xe0,0xe1,0xe2,0xe3};
+struct Address Addr={0x01,0x02,0x03,0x05,0xFF};
+struct Command Cmd={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x27,0x28,0x29,0x2C,0x81,0x83,
+                    0x85,0x86,0x87,0x88,0x089,0x8A,0x8B,0x8C,0x90,0xe0,0xe1,0xe2,0xe3};
 
 int tranceive(int fd, unsigned char* cmd, unsigned char cmd_len, unsigned char* rx)
 {
@@ -48,7 +49,7 @@ int tranceive(int fd, unsigned char* cmd, unsigned char cmd_len, unsigned char*
     tcflush(fd,TCIOFLUSH);
     if(write(fd, cmd, cmd_len) >= cmd_len)
     {
-        usleep(30000);
+        usleep(15000);
         len = read(fd, rx, 512);
     }
     else
@@ -551,8 +552,7 @@ unsigned char Config_Gpio_Output(unsigned char fd, unsigned char targetAddr, Gpi
         if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
            (rx[2] == tx[1]) &&
            (rx[1] == tx[2]) &&
-           (rx[3] == tx[3]) &&
-           (rx[6] == tx[6]))
+           (rx[3] == tx[3]))
         {
             result = PASS;
         }
@@ -591,8 +591,7 @@ unsigned char Config_Gfd_Value(unsigned char fd, unsigned char targetAddr, Gfd_c
         if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
            (rx[2] == tx[1]) &&
            (rx[1] == tx[2]) &&
-           (rx[3] == tx[3]) &&
-           (rx[6] == tx[6]))
+           (rx[3] == tx[3]))
         {
             result = PASS;
         }
@@ -634,8 +633,7 @@ unsigned char Config_Model_Name(unsigned char fd, unsigned char targetAddr, unsi
         if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
               (rx[2] == tx[1]) &&
               (rx[1] == tx[2]) &&
-              (rx[3] == tx[3]) &&
-              (rx[6] == tx[6]))
+              (rx[3] == tx[3]))
         {
             result = PASS;
         }
@@ -668,8 +666,7 @@ unsigned char Config_Rtc_Data(unsigned char fd, unsigned char targetAddr, Rtc *S
         if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
                 (rx[2] == tx[1]) &&
                 (rx[1] == tx[2]) &&
-                (rx[3] == tx[3]) &&
-                (rx[6] == tx[6]))
+                (rx[3] == tx[3]))
         {
             result = PASS;
         }
@@ -823,3 +820,314 @@ unsigned char Update_Finish(unsigned char fd, unsigned char targetAddr)
 
     return result;
 }
+
+unsigned char Query_AC_Status(unsigned char fd, unsigned char targetAddr, Ac_Status *Ret_Buf)
+{
+    unsigned char result = FAIL;
+    unsigned char tx[7] = {0xaa, 0x00, targetAddr, Cmd.query_ac_status, 0x00, 0x00, 0x00};
+    unsigned char rx[512];
+    unsigned char chksum = 0x00;
+    unsigned char len = tranceive(fd, tx, sizeof(tx), rx);
+
+    if(len > 6)
+    {
+        if (len < 6+(rx[4] | rx[5]<<8))
+            return result;
+
+        for(int idx = 0;idx<(rx[4] | rx[5]<<8);idx++)
+        {
+            chksum ^= rx[6+idx];
+        }
+
+        if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
+                (rx[2] == tx[1]) &&
+                (rx[1] == tx[2]) &&
+                (rx[3] == tx[3]))
+        {
+            Ret_Buf->CpStatus = rx[6];
+            Ret_Buf->CurLimit = (rx[7] | (rx[8] << 8));
+            Ret_Buf->PilotVol_P = (rx[9] | (rx[10] << 8));
+            Ret_Buf->PilotVol_N = (rx[11] | (rx[12] << 8));
+            Ret_Buf->LockStatus = rx[13];
+            Ret_Buf->RelayStatus = rx[14];
+            Ret_Buf->ShutterStatus = rx[15];
+            Ret_Buf->MeterStatus = rx[16];
+            Ret_Buf->PpStatus = rx[17];
+            Ret_Buf->MaxCurrent = rx[18];
+            Ret_Buf->RotateSwitchStatus = rx[19];
+//
+//          Ret_Buf->AC_Connector       = (rx[6] >> 0) & 0x01;
+//          Ret_Buf->AC_MainBreaker     = (rx[6] >> 1) & 0x01;
+//          Ret_Buf->SPD                = (rx[6] >> 2) & 0x01;
+//          Ret_Buf->Door_Open          = (rx[6] >> 3) & 0x01;
+//          Ret_Buf->GFD[0]             = (rx[6] >> 4) & 0x01;
+//          Ret_Buf->GFD[1]             = (rx[6] >> 5) & 0x01;
+//          Ret_Buf->AC_Drop            = (rx[6] >> 6) & 0x01;
+//
+//          Ret_Buf->Emergency_IO       = (rx[7] >> 0) & 0x01;
+//
+//          Ret_Buf->Button_Emergency_Press = (rx[8] >> 0) & 0x01;
+//          Ret_Buf->Button_On_Press    = (rx[8] >> 1) & 0x01;
+//          Ret_Buf->Button_Off_Press   = (rx[8] >> 2) & 0x01;
+//          Ret_Buf->Key_1_Press        = (rx[8] >> 3) & 0x01;
+//          Ret_Buf->Key_2_Press        = (rx[8] >> 4) & 0x01;
+//          Ret_Buf->Key_3_Press        = (rx[8] >> 5) & 0x01;
+//          Ret_Buf->Key_4_Press        = (rx[8] >> 6) & 0x01;
+
+            result = PASS;
+        }
+    }
+
+    return result;
+}
+
+unsigned char Query_AC_Alarm_Code(unsigned char fd, unsigned char targetAddr, Ac_Alarm_code *Ret_Buf)
+{
+    unsigned char result = FAIL;
+    unsigned char tx[7] = {0xaa, 0x00, targetAddr, Cmd.query_ac_alarm_code, 0x00, 0x00};
+    unsigned char rx[512];
+    unsigned char chksum = 0x00;
+    unsigned char len = tranceive(fd, tx, sizeof(tx), rx);
+
+    if(len > 6)
+    {
+        if (len < 6+(rx[4] | rx[5]<<8))
+            return result;
+
+        for(int idx = 0;idx<(rx[4] | rx[5]<<8);idx++)
+        {
+            chksum ^= rx[6+idx];
+        }
+
+        if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
+           (rx[2] == tx[1]) &&
+           (rx[1] == tx[2]) &&
+           (rx[3] == tx[3]))
+        {
+            Ret_Buf->AcAlarmCode = rx[6] + (rx[7] << 8) + (rx[8] << 16) + (rx[9] << 24);
+            result = PASS;
+        }
+    }
+
+    return result;
+}
+
+unsigned char Query_Charging_Energy(unsigned char fd, unsigned char targetAddr, Ac_Charging_energy *Ret_Buf)
+{
+    unsigned char result = FAIL;
+    unsigned char tx[7] = {0xaa, 0x00, targetAddr, Cmd.query_ac_output_energy, 0x00, 0x00,0x00};
+    unsigned char rx[512];
+    unsigned char chksum = 0x00;
+    unsigned char len = tranceive(fd, tx, sizeof(tx), rx);
+
+    if(len > 6)
+    {
+        if (len < 6+(rx[4] | rx[5]<<8))
+            return result;
+
+        for(int idx = 0;idx<(rx[4] | rx[5]<<8);idx++)
+        {
+            chksum ^= rx[6+idx];
+        }
+
+        if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
+           (rx[2] == tx[1]) &&
+           (rx[1] == tx[2]) &&
+           (rx[3] == tx[3]))
+        {
+            Ret_Buf->Energy = rx[6] + (rx[7] << 8) + (rx[8] << 16) + (rx[9] << 24);
+            result = PASS;
+        }
+    }
+
+    return result;
+}
+
+unsigned char Query_Charging_Current(unsigned char fd, unsigned char targetAddr, Ac_Charging_current *Ret_Buf)
+{
+    unsigned char result = FAIL;
+    unsigned char tx[7] = {0xaa, 0x00, targetAddr, Cmd.query_ac_output_current, 0x00, 0x00, 0x00};
+    unsigned char rx[512];
+    unsigned char chksum = 0x00;
+    unsigned char len = tranceive(fd, tx, sizeof(tx), rx);
+
+    if(len > 6)
+    {
+        if (len < 6+(rx[4] | rx[5]<<8))
+            return result;
+
+        for(int idx = 0;idx<(rx[4] | rx[5]<<8);idx++)
+        {
+            chksum ^= rx[6+idx];
+        }
+
+        if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
+           (rx[2] == tx[1]) &&
+           (rx[1] == tx[2]) &&
+           (rx[3] == tx[3]))
+        {
+            Ret_Buf->OuputCurrentL1 = rx[6] + (rx[7] << 8);
+            Ret_Buf->OuputCurrentL2 = rx[8] + (rx[9] << 8);
+            Ret_Buf->OuputCurrentL3 = rx[10] + (rx[11] << 8);
+            result = PASS;
+        }
+    }
+
+    return result;
+}
+
+unsigned char Config_LED_Status(unsigned char fd, unsigned char targetAddr, Ac_Led_Status *Ret_Buf)
+{
+    unsigned char result = FAIL;
+    unsigned char tx[12] = {0xaa, 0x00, targetAddr, Cmd.config_ac_led_status, 0x05, 0x00, Ret_Buf->ActionMode, (Ret_Buf->AcAlarmCode >> 0) & 0xFF,
+            (Ret_Buf->AcAlarmCode >> 8) & 0xFF, (Ret_Buf->AcAlarmCode >> 16) & 0xFF, (Ret_Buf->AcAlarmCode >> 24) & 0xFF};
+    unsigned char rx[512];
+    unsigned char chksum = 0x00;
+
+    for (int idx = 0; idx < (tx[4] | tx[5] << 8); idx++)
+        chksum ^= tx[6 + idx];
+    tx[11] = chksum;
+
+    if (tranceive(fd, tx, sizeof(tx), rx) > 0)
+    {
+        chksum = 0x00;
+        for (int idx = 0; idx < (rx[4] | rx[5] << 8); idx++)
+        {
+            chksum ^= rx[6 + idx];
+        }
+
+        if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
+            (rx[2] == tx[1]) &&
+            (rx[1] == tx[2]) &&
+            (rx[3] == tx[3]))
+        {
+            result = PASS;
+        }
+    }
+
+    return result;
+}
+
+unsigned char Config_Legacy_Req(unsigned char fd, unsigned char targetAddr, unsigned char _switch)
+{
+    unsigned char result = FAIL;
+    unsigned char tx[9] = {0xaa, 0x00, targetAddr, Cmd.config_Legacy_Req, 0x02, 0x00, _switch, 0x00};
+    unsigned char rx[512];
+    unsigned char chksum = 0x00;
+
+    for (int idx = 0; idx < (tx[4] | tx[5] << 8); idx++)
+        chksum ^= tx[6 + idx];
+    tx[8] = chksum;
+
+    if (tranceive(fd, tx, sizeof(tx), rx) > 0)
+    {
+        chksum = 0x00;
+        for (int idx = 0; idx < (rx[4] | rx[5] << 8); idx++)
+        {
+            chksum ^= rx[6 + idx];
+        }
+
+        if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
+           (rx[2] == tx[1]) &&
+           (rx[1] == tx[2]) &&
+           (rx[3] == tx[3]))
+        {
+            result = PASS;
+        }
+    }
+
+    return result;
+}
+
+unsigned char Config_Ac_Duty(unsigned char fd, unsigned char targetAddr, unsigned char _value)
+{
+    unsigned char result = FAIL;
+    unsigned char tx[8] = {0xaa, 0x00, targetAddr, Cmd.config_ac_duty, 0x01, 0x00, _value};
+    unsigned char rx[512];
+    unsigned char chksum = 0x00;
+
+    for (int idx = 0; idx < (tx[4] | tx[5] << 8); idx++)
+        chksum ^= tx[6 + idx];
+    tx[7] = chksum;
+
+    if (tranceive(fd, tx, sizeof(tx), rx) > 0)
+    {
+        chksum = 0x00;
+        for (int idx = 0; idx < (rx[4] | rx[5] << 8); idx++)
+        {
+            chksum ^= rx[6 + idx];
+        }
+
+        if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
+           (rx[2] == tx[1]) &&
+           (rx[1] == tx[2]) &&
+           (rx[3] == tx[3]))
+        {
+            result = PASS;
+        }
+    }
+
+    return result;
+}
+
+unsigned char Config_CSU_Mode(unsigned char fd, unsigned char targetAddr)
+{
+    unsigned char result = FAIL;
+    unsigned char tx[9] = {0xaa, 0x00, targetAddr, Cmd.config_csu_mode, 0x02, 0x00, 0x01, 0x00};
+    unsigned char rx[512];
+    unsigned char chksum = 0x00;
+
+    for (int idx = 0; idx < (tx[4] | tx[5] << 8); idx++)
+        chksum ^= tx[6 + idx];
+    tx[7] = chksum;
+
+    if (tranceive(fd, tx, sizeof(tx), rx) > 0)
+    {
+        chksum = 0x00;
+        for (int idx = 0; idx < (rx[4] | rx[5] << 8); idx++)
+        {
+            chksum ^= rx[6 + idx];
+        }
+
+        if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
+           (rx[2] == tx[1]) &&
+           (rx[1] == tx[2]) &&
+           (rx[3] == tx[3]))
+        {
+            result = PASS;
+        }
+    }
+
+    return result;
+}
+
+unsigned char Config_Reset_MCU(unsigned char fd, unsigned char targetAddr)
+{
+    unsigned char result = FAIL;
+    unsigned char tx[9] = {0xaa, 0x00, targetAddr, Cmd.config_reset_mcu, 0x02, 0x00, 0x01, 0x00};
+    unsigned char rx[512];
+    unsigned char chksum = 0x00;
+
+    for (int idx = 0; idx < (tx[4] | tx[5] << 8); idx++)
+        chksum ^= tx[6 + idx];
+    tx[7] = chksum;
+
+    if (tranceive(fd, tx, sizeof(tx), rx) > 0)
+    {
+        chksum = 0x00;
+        for (int idx = 0; idx < (rx[4] | rx[5] << 8); idx++)
+        {
+            chksum ^= rx[6 + idx];
+        }
+
+        if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
+           (rx[2] == tx[1]) &&
+           (rx[1] == tx[2]) &&
+           (rx[3] == tx[3]))
+        {
+            result = PASS;
+        }
+    }
+
+    return result;
+}

+ 66 - 0
EVSE/Projects/DM30/Apps/internalComm.h

@@ -13,6 +13,7 @@ extern struct Address
     unsigned char Aux;
     unsigned char Fan;
     unsigned char Relay;
+    unsigned char AcPlug;
     unsigned char Broadcast;
 }Addr;
 
@@ -29,12 +30,25 @@ extern struct Command
     unsigned char query_Gfd_Adc;                //0x09
     unsigned char query_Gpio_In;                //0x0a
 
+    unsigned char query_ac_output_current;      //0x27
+    unsigned char query_ac_status;              //0x28
+    unsigned char query_ac_alarm_code;          //0x29
+
+    unsigned char query_ac_output_energy;       //0x2C
+
     unsigned char config_Fan_Speed;             //0x81
     unsigned char config_Model_Name;            //0x83
     unsigned char config_Relay_Output;          //0x85
     unsigned char config_Gpio_Output;           //0x86
     unsigned char config_Rtc_Data;              //0x87
+    unsigned char config_ac_led_status;         //0x88
+
+    unsigned char config_ac_duty;               //0x89
+    unsigned char config_Legacy_Req;            //0x8A
     unsigned char config_Gfd_Value;             //0x8B
+    unsigned char config_reset_mcu;             //0x8C
+
+    unsigned char config_csu_mode;              //0x90
 
     unsigned char update_Start;                 //0xe0
     unsigned char update_Abort;                 //0xe1
@@ -168,6 +182,49 @@ typedef struct RTC
     unsigned char RtcData[14];
 }Rtc;
 
+typedef struct AC_Status
+{
+    unsigned char       CpStatus;
+    unsigned short      CurLimit;
+    short               PilotVol_P;
+    short               PilotVol_N;
+    unsigned char       LockStatus;
+    unsigned char       RelayStatus;
+    unsigned char       ShutterStatus;
+    unsigned char       MeterStatus;
+    unsigned char       PpStatus;
+    unsigned char       MaxCurrent;
+    unsigned char       RotateSwitchStatus;
+}
+Ac_Status;
+
+typedef struct AC_LED_Status
+{
+    unsigned char       ActionMode;
+    unsigned long       AcAlarmCode;
+}
+Ac_Led_Status;
+
+typedef struct AC_Alarm_Code
+{
+    unsigned int        AcAlarmCode;
+}
+Ac_Alarm_code;
+
+typedef struct AC_Charging_Energy
+{
+    unsigned int        Energy;
+}
+Ac_Charging_energy;
+
+typedef struct AC_Charging_Current
+{
+    unsigned short      OuputCurrentL1;
+    unsigned short      OuputCurrentL2;
+    unsigned short      OuputCurrentL3;
+}
+Ac_Charging_current;
+
 extern unsigned char Query_FW_Ver(unsigned char fd, unsigned char targetAddr, Ver *Ret_Buf);
 extern unsigned char Query_HW_Ver(unsigned char fd, unsigned char targetAddr, Ver *Ret_Buf);
 extern unsigned char Query_Present_InputVoltage(unsigned char fd, unsigned char targetAddr, PresentInputVoltage *Ret_Buf);
@@ -191,4 +248,13 @@ extern unsigned char Update_Abord(unsigned char fd, unsigned char targetAddr);
 extern unsigned char Update_Transfer(unsigned char fd, unsigned char targetAddr, unsigned int startAddr, unsigned char *data, unsigned short int length);
 extern unsigned char Update_Finish(unsigned char fd, unsigned char targetAddr);
 
+extern unsigned char Query_AC_Status(unsigned char fd, unsigned char targetAddr, Ac_Status *Ret_Buf);
+extern unsigned char Query_AC_Alarm_Code(unsigned char fd, unsigned char targetAddr, Ac_Alarm_code *Ret_Buf);
+extern unsigned char Query_Charging_Energy(unsigned char fd, unsigned char targetAddr, Ac_Charging_energy *Ret_Buf);
+extern unsigned char Query_Charging_Current(unsigned char fd, unsigned char targetAddr, Ac_Charging_current *Ret_Buf);
+extern unsigned char Config_LED_Status(unsigned char fd, unsigned char targetAddr, Ac_Led_Status *Ret_Buf);
+extern unsigned char Config_Legacy_Req(unsigned char fd, unsigned char targetAddr, unsigned char _switch);
+extern unsigned char Config_Ac_Duty(unsigned char fd, unsigned char targetAddr, unsigned char _value);
+extern unsigned char Config_CSU_Mode(unsigned char fd, unsigned char targetAddr);
+extern unsigned char Config_Reset_MCU(unsigned char fd, unsigned char targetAddr);
 #endif /* INTERNALCOMM_H_ */

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 379 - 145
EVSE/Projects/DM30/Apps/main.c


+ 1 - 0
EVSE/Projects/DM30/Apps/web.sh

@@ -0,0 +1 @@
+/sbin/lighttpd -f /etc/lighttpd/lighttpd.conf  -m /lib

Vissa filer visades inte eftersom för många filer har ändrats