瀏覽代碼

2022-07-12/Alston Lin
Actions
1. Add startTransaction and stopTransaction functions for maintenance server
2. Add chademo type (L) support to 80A and CCS type (Y/Z) support to 150A
3. Add CCS type (S) support boost mode to 500A
4. add offline power key function to limit output power when offline
5. Add a button to detect plugin functionality for TPC adapter
6. Filter all error codes about internet status
7. Import the PSU dynamic allocation schema
Files
1. As follow commit history

Alston Lin 2 年之前
父節點
當前提交
6bee6a3368
共有 35 個文件被更改,包括 3963 次插入1199 次删除
  1. 10 5
      EVSE/Projects/DS60-120/Apps/CheckSystemTask.c
  2. 158 28
      EVSE/Projects/DS60-120/Apps/Config.h
  3. 二進制
      EVSE/Projects/DS60-120/Apps/FactoryConfig
  4. 7 2
      EVSE/Projects/DS60-120/Apps/Makefile
  5. 二進制
      EVSE/Projects/DS60-120/Apps/Module_EvComm
  6. 393 247
      EVSE/Projects/DS60-120/Apps/Module_EvComm.c
  7. 0 1
      EVSE/Projects/DS60-120/Apps/Module_EvComm.h
  8. 二進制
      EVSE/Projects/DS60-120/Apps/Module_EventLogging
  9. 70 23
      EVSE/Projects/DS60-120/Apps/Module_EventLogging.c
  10. 二進制
      EVSE/Projects/DS60-120/Apps/Module_InternalComm
  11. 456 105
      EVSE/Projects/DS60-120/Apps/Module_InternalComm.c
  12. 62 0
      EVSE/Projects/DS60-120/Apps/Module_LcmContro.h
  13. 二進制
      EVSE/Projects/DS60-120/Apps/Module_LcmControl
  14. 86 13
      EVSE/Projects/DS60-120/Apps/Module_LcmControl.c
  15. 二進制
      EVSE/Projects/DS60-120/Apps/Module_PrimaryComm
  16. 3 5
      EVSE/Projects/DS60-120/Apps/Module_PrimaryComm.c
  17. 二進制
      EVSE/Projects/DS60-120/Apps/Module_PsuComm
  18. 415 574
      EVSE/Projects/DS60-120/Apps/Module_PsuComm.c
  19. 12 11
      EVSE/Projects/DS60-120/Apps/Module_PsuComm.h
  20. 二進制
      EVSE/Projects/DS60-120/Apps/Module_SmartBox
  21. 1475 0
      EVSE/Projects/DS60-120/Apps/Module_SmartBox.c
  22. 75 0
      EVSE/Projects/DS60-120/Apps/Module_SmartBox.h
  23. 1 1
      EVSE/Projects/DS60-120/Apps/OutputTask.c
  24. 二進制
      EVSE/Projects/DS60-120/Apps/ReadCmdline
  25. 344 39
      EVSE/Projects/DS60-120/Apps/ReadCmdline.c
  26. 二進制
      EVSE/Projects/DS60-120/Apps/UnsafetyOutputTask
  27. 3 3
      EVSE/Projects/DS60-120/Apps/internalComm.c
  28. 4 4
      EVSE/Projects/DS60-120/Apps/internalComm.h
  29. 二進制
      EVSE/Projects/DS60-120/Apps/main
  30. 387 137
      EVSE/Projects/DS60-120/Apps/main.c
  31. 2 1
      EVSE/Projects/DS60-120/Apps/timeout.h
  32. 二進制
      EVSE/Projects/DS60-120/Images/FactoryDefaultConfig.bin
  33. 二進制
      EVSE/Projects/DS60-120/Images/ramdisk.gz
  34. 二進制
      EVSE/rootfs/root/Module_Payment_Bazel8
  35. 二進制
      EVSE/rootfs/root/Module_PowerSharing

+ 10 - 5
EVSE/Projects/DS60-120/Apps/CheckSystemTask.c

@@ -11,6 +11,7 @@
 #define	TASK_CNT_MAIN		5
 #define TASK_CNT_EV_COMM	2
 #define TASK_CNT_PSU_COMM	2
+#define TASK_CNT_SBOX_COMM	3
 
 bool Taskconutstring(char *src, char *taskname)
 {
@@ -58,6 +59,7 @@ unsigned char CheckSystemTask(unsigned char systemPage)
 	unsigned char count_main 		= GetProcessCount("Module_CSU");
 	unsigned char count_evComm 		= GetProcessCount("Module_EvComm");
 	unsigned char count_psuComm 	= GetProcessCount("Module_PsuComm");
+	unsigned char count_sboxComm	= GetProcessCount("Module_SmartBox");
 
 	if (count_main == 0)
 		count_main = GetProcessCount("main");
@@ -74,7 +76,7 @@ unsigned char CheckSystemTask(unsigned char systemPage)
 
 	if (systemPage == _LCM_FIX || systemPage == _LCM_EMC)
 	{
-		if (count_main < TASK_CNT_MAIN || count_psuComm < TASK_CNT_PSU_COMM)
+		if (count_main < TASK_CNT_MAIN || count_psuComm < TASK_CNT_PSU_COMM || count_sboxComm < TASK_CNT_SBOX_COMM)
 		{
 			system("killall Module_EventLogging");
 			system("killall Module_PrimaryComm");
@@ -82,10 +84,11 @@ unsigned char CheckSystemTask(unsigned char systemPage)
 			system("killall Module_LcmControl");
 			system("killall Module_InternalComm");
 			system("killall Module_PsuComm");
-			system("killall OcppBackend &");
-			system("killall Module_4g &");
-			system("killall Module_Wifi &");
-			system("killall Module_DcMeter &");
+			system("killall OcppBackend");
+			system("killall Module_4g");
+			system("killall Module_Wifi");
+			system("killall Module_DcMeter");
+			system("killall Module_SmartBox");
 			sleep(3);
 			system("/usr/bin/run_evse_restart.sh");
 		}
@@ -120,6 +123,8 @@ unsigned char CheckSystemTask(unsigned char systemPage)
 		result = _SYSTEM_TASK_LOST_ITEM_EVCOMM;
 	else if (count_psuComm < TASK_CNT_PSU_COMM)
 		result = _SYSTEM_TASK_LOST_ITEM_PSUCOMM;
+	else if (count_sboxComm < TASK_CNT_SBOX_COMM)
+		result = _SYSTEM_TASK_LOST_ITEM_SMARTBOX;
 	else if (system("pidof -s Module_EventLogging > /dev/null") != 0)
 		result = _SYSTEM_TASK_LOST_ITEM_EVENTLOG;
 	else if (system("pidof -s Module_PrimaryComm > /dev/null") != 0)

+ 158 - 28
EVSE/Projects/DS60-120/Apps/Config.h

@@ -15,8 +15,10 @@
 typedef unsigned char			byte;
 
 #define TOTAL_QUANTITY_GUN			4				//Max Count
+#define PSU_GROUP_COUNT				4
 #define DC_CONNECTOR_COUNT			2
 #define AC_CONNECTOR_COUNT			1
+#define VOLTAGE_SAMPLE_COUNT		30
 
 #define GFD_WAIT			0
 #define GFD_PASS			1
@@ -34,6 +36,21 @@ typedef unsigned char			byte;
 #define	AC_MINIMUM_DUTY			6
 #define	AC_STOP_DUTY			100
 
+#define GUN_LEFT			0
+#define GUN_RIGHT			1
+#define GUN_CHECK			255
+
+//=======================================
+// Price type
+//=======================================
+#define DEFAULT_VALUE						0
+#define CONNECTION_FEE						1
+#define CURRENT_RATE						2
+#define OCCUPANCY_FEE						3
+#define SESSION_FEE							4
+#define TOTAL_COST							5
+#define ACCOUNT_BALANCE						6
+
 enum _AC_SYSTEM_STATUS
 {
 	AC_SYS_NONE = 	0,
@@ -47,10 +64,11 @@ enum _AC_SYSTEM_STATUS
 
 enum _GUN_TYPE
 {
-	_Type_Chademo = 		0,
-	_Type_CCS,
-	_Type_GB,
-	_Type_AC,
+	_Type_Chademo 	= 0,
+	_Type_CCS		= 1,
+	_Type_GB		= 2,
+	_Type_AC		= 3,
+	_Type_Test		= 9
 };
 
 enum _CCS_TYPE
@@ -108,25 +126,10 @@ enum _OFFLINE_POLICY
 	_OFFLINE_POLICY_NO_CHARGING = 0x03,
 };
 
-enum _REASSIGNED_RESOURCE_STEP
-{
-	_REASSIGNED_NONE = 				0,	//
-	_REASSIGNED_PREPARE_M_TO_A =	1,	// 系統收到需要降載需求 (輸出總電流降低),PSU Task 收到將狀態切換至下個狀態
-	_REASSIGNED_GET_NEW_CAP = 		2,	// 充電中的重新取得屬於自己火線上的總能量並透過小板通知車端 - 超過10秒直接跳下一步
-	_REASSIGNED_ADJUST_M_TO_A = 	3,	// 模塊重新分配完成
-	_REASSIGNED_RELAY_M_TO_A =		4,	// 切斷橋接的 Relay
-
-	_REASSIGNED_PREPARE_A_TO_M = 	11,
-	_REASSIGNED_ADJUST_A_TO_M = 	12, // 模塊升壓
-	_REASSIGNED_RELAY_A_TO_M = 		13,	// 搭接橋接的 Relay
-	_REASSIGNED_WAITING = 			14,
-	_REASSIGNED_COMP = 				15
-};
-
 enum _MAIN_CHARGING_MODE
 {
-	_MAIN_CHARGING_MODE_MAX = 0,
-	_MAIN_CHARGING_MODE_AVER = 1,
+	_MAIN_CHARGING_MODE_NORMAL	 	= 0,
+	_MAIN_CHARGING_MODE_BOTH 		= 1,
 };
 
 enum _EXTRA_ERR_PROCESS
@@ -140,6 +143,7 @@ enum _CHARGER_TYPE
 {
 	_CHARGER_TYPE_IEC = 0,
 	_CHARGER_TYPE_UL = 1,
+	_CHARGER_TYPE_JARI = 2 //LWADD
 };
 
 enum _SYS_WIFI_MODE
@@ -221,7 +225,67 @@ enum _SYSTEM_TASK_LOST_ITEM
 	_SYSTEM_TASK_LOST_ITEM_EVENTLOG		= 4,
 	_SYSTEM_TASK_LOST_ITEM_PRIMARYCOMM	= 5,
 	_SYSTEM_TASK_LOST_ITEM_LCMCONTROL	= 6,
-	_SYSTEM_TASK_LOST_ITEM_INTERCOMM	= 7
+	_SYSTEM_TASK_LOST_ITEM_INTERCOMM	= 7,
+	_SYSTEM_TASK_LOST_ITEM_SMARTBOX		= 8
+};
+
+enum _PSU_PROTOCOL_TYPE
+{
+	_PSU_PROTOCOL_INFY 					= 0,
+	_PSU_PROTOCOL_UU					= 1
+};
+
+
+enum _PSU_USING_TARGET
+{
+	_PSU_USING_TARGET_CON1		= 0x00,
+	_PSU_USING_TARGET_CON2		= 0x01,
+	_PSU_USING_TARGET_READY		= 0xFF,
+};
+
+enum _PSU_POWER_STATUS
+{
+	_PSU_POWER_STATUS_OFF		= 0x00,
+	_PSU_POWER_STATUS_ON		= 0x01,
+};
+
+enum _PSU_DYNAMIC_FETCH_STEP
+{
+	_PSU_DYNAMIC_FETCH_STEP_NONE			= 0x00,
+	_PSU_DYNAMIC_FETCH_STEP_WAIT			= 0x01,
+	_PSU_DYNAMIC_FETCH_STEP_TG_VOL			= 0x02,
+	_PSU_DYNAMIC_FETCH_STEP_RELAY			= 0x03,
+	_PSU_DYNAMIC_FETCH_STEP_CUR_SHARE		= 0x04,
+	_PSU_DYNAMIC_FETCH_STEP_WATI_FINISH		= 0x05,
+	_PSU_DYNAMIC_FETCH_STEP_FINISH			= 0x06,
+	_PSU_DYNAMIC_FETCH_STEP_ABORT			= 0x10,
+};
+
+enum _PSU_DYNAMIC_RELEASE_STEP
+{
+	_PSU_DYNAMIC_RELEASE_STEP_NONE			= 0x00,
+	_PSU_DYNAMIC_RELEASE_STEP_WAIT			= 0x01,
+	_PSU_DYNAMIC_RELEASE_STEP_LIMIT			= 0x02,
+	_PSU_DYNAMIC_RELEASE_STEP_PWROFF		= 0x03,
+	_PSU_DYNAMIC_RELEASE_STEP_RELAYOFF		= 0x04,
+	_PSU_DYNAMIC_RELEASE_STEP_WAIT_FINISH 	= 0x05,
+	_PSU_DYNAMIC_RELEASE_STEP_FINISH		= 0x06,
+	_PSU_DYNAMIC_RELEASE_STEP_ABORT			= 0x10,
+};
+
+enum _PSU_GROUP_INDEX
+{
+	_PSU_GROUP_INDEX_0	= 0x00,
+	_PSU_GROUP_INDEX_1	= 0x01,
+	_PSU_GROUP_INDEX_2	= 0x02,
+	_PSU_GROUP_INDEX_3	= 0x03,
+};
+
+enum _RELAY_SWITCH_NAME
+{
+	_RELAY_SWITCH_NAME_R3			= 0x00,
+	_RELAY_SWITCH_NAME_R4			= 0x01,
+	_RELAY_SWITCH_NAME_R5			= 0x02,
 };
 
 struct StructMeter
@@ -239,6 +303,19 @@ struct MeterInformation
 	byte isWorking;
 };
 
+//struct ConnectorBalanceInfo
+//{
+//	unsigned int UserPrice; // connector user's user price, unit: 0.01 (dollar / kWh)
+//	unsigned int TotalCost; // connector user's total cost, unit: 0.01 dollar
+//	int AccountBalance; // connector user's account balance, unit: 0.01 dollar
+//};
+//
+//struct BalanceInfo
+//{
+//	unsigned int defaultPrice;
+//	struct ConnectorBalanceInfo connectorBalanceInfo[3]; // Max count : DC * 2 + AC * 1
+//};
+
 struct ConnectorBalanceInfo
 {
 	unsigned int UserPrice; // connector user's user price, unit: 0.01 (dollar / kWh)
@@ -273,6 +350,7 @@ enum RELAY_STATUS_ERROR_INDEX
 	RELAY_SMR2_N_STATUS = 	3,
 	RELAY_PARA_P_STATUS = 	4,
 	RELAY_PARA_N_STATUS = 	5,
+	RELAY_PRE_STATUS =		6
 };
 
 enum RELAY_STATUS_ERROR_TYPE
@@ -315,6 +393,26 @@ enum _CCID_INDEX
 	_CCID_NONE 		= 0xFF,
 };
 
+enum _CONNECTOR_STATUS
+{
+	_CONNECTOR_STATUS_NONE 		= 0x00,
+	_CONNECTOR_STATUS_WAIT		= 0x01,
+	_CONNECTOR_STATUS_USING		= 0x02,
+};
+
+enum _SYSTEM_TYPE
+{
+	_SYSTEM_TYPE_SIMPLE 		= 0x00,
+	_SYSTEM_TYPE_STANDARD		= 0x01,
+	_SYSTEM_TYPE_SMART			= 0x10
+};
+
+enum _TPC_PLUG_DETECT_STATUS
+{
+	_TPC_PLUG_DETECT_STATUS_NONE 		= 0x00,
+	_TPC_PLUG_DETECT_STATUS_WAIT		= 0x01,
+};
+
 typedef union
 {
     unsigned int GunErrMessage;
@@ -352,12 +450,16 @@ typedef union
 		unsigned char GBTConnectUCP :1;
 		unsigned char ParallelRelayWeldingFault :1;
 		unsigned char ParallelRelayDrivingFault :1;
-		unsigned char :3;
+		unsigned char StopByEvseCondition:1;
+		unsigned char :2;
     }GunBits;
 }GunErr;
 
 struct DcCommonInformation
 {
+	// 0 : Standard (only one psu module), 1 : Standard (two psu module), 2 : Smart
+	byte systemType;
+	byte halfGroupCount;
 	byte rebootCount;
 	// charger type (standard、simple)
 	byte chargerType;
@@ -379,6 +481,7 @@ struct DcCommonInformation
 	byte acContactSwitch;
 	byte psuKeepCommunication;
 	byte startTransactionFlag[DC_CONNECTOR_COUNT];
+	int startTransactionID[DC_CONNECTOR_COUNT];
 
 	GunErr ConnectErrList[DC_CONNECTOR_COUNT];
 	byte CcsTypeSaved[DC_CONNECTOR_COUNT];
@@ -411,28 +514,55 @@ struct DcCommonInformation
 	// for reset ev board (GBT or Chademo)
 	byte evBoardResetFlag;
 
-	// Psu module split by connector
-	int connector[DC_CONNECTOR_COUNT][12];
-	byte conn_1_count;
-	byte conn_2_count;
-
 	// Use ccid to obtain authorization
 	byte enObtainAuthorizbyCCID;
 	byte _CcidAuthProcessStep;
 	byte _authWithCcidFlag[DC_CONNECTOR_COUNT];
 
 	// balance information - for tariff
+	//struct BalanceInfo balanceInfo;
+	// balance information - for standard
 	struct BalanceInfo balanceInfo;
 
 	// the hold time before return idle
 	byte _returnIdleHoldFlag[DC_CONNECTOR_COUNT];
 
+	// Date - YYYY/MM/DD
+	byte _sys_date[11];
+	// Date - hh/mm
+	byte _sys_time[8];
+	// Date - a / p .m
+	byte _sys_period[6];
+
 	// isPsuError
 	byte _isPsuErrorOccur;
 
+	// PSU Protocol
+	byte _psuProtocol;
+
+	//CHAdeMo transfer TPC plug in detect
+	//LW_tpc plug detect
+	byte _tpcPlugDetectState;
+	byte TpcDetectFunction;
+
+	// Check if the output voltage is stable
+	float _outputVoltageSapmle[PSU_GROUP_COUNT][VOLTAGE_SAMPLE_COUNT];
+
+	// offline power - LW_OfflinePower
+	int _offlinePower;
+
+	// CTEP : California Type Evaluation Program
+	double _ctepEnergyCost [DC_CONNECTOR_COUNT];
+	double _ctepParkingFee [DC_CONNECTOR_COUNT];
+	double _ctepTotalCost [DC_CONNECTOR_COUNT];
+
 	byte for_alston_test_1;
 	byte for_alston_test_2;
 	byte for_alston_test_3;
+
+	// for test smartbox - fetch / release
+	byte smartFetchRun[DC_CONNECTOR_COUNT];
+	byte smartReleaseRun[DC_CONNECTOR_COUNT];
 };
 
 #endif /* CONFIG_H_ */

二進制
EVSE/Projects/DS60-120/Apps/FactoryConfig


+ 7 - 2
EVSE/Projects/DS60-120/Apps/Makefile

@@ -13,7 +13,7 @@ Lib_SQLite3 = "-L../../../Modularization/ocppfiles" -lsqlite3
 all: CopyFile apps
 #apps: Module_CSU Module_EvComm Module_EventLogging Module_InternalComm Module_LcmControl Module_PrimaryComm Module_PsuComm 
 # ReadCmdline kill.sh
-apps: MainTask EvCommTask EventLoggingTask InternalCommTask LcmControlTask PrimaryCommTask PsuCommTask ReadCmdlineTask UnsafetyOutputTool FactoryConfigApp OtherTools
+apps: MainTask EvCommTask EventLoggingTask InternalCommTask LcmControlTask PrimaryCommTask PsuCommTask SmartBoxTask ReadCmdlineTask UnsafetyOutputTool FactoryConfigApp OtherTools
 
 MainTask:
 	rm -f *.o
@@ -62,7 +62,12 @@ PsuCommTask:
 	$(CC) -D $(Project) -include../../../Modularization/Infypwr_PsuCommObj.h -includeConfig.h -O0 -g3 -Wall -c -fmessage-length=0 -o Module_PsuComm.o Module_PsuComm.c
 	$(CC) -lrt -o Module_PsuComm Module_PsuComm.o ../../../Modularization/libInfypwr_PsuCommObj.a
 	cp -f Module_PsuComm ../Images/root	
-	
+SmartBoxTask:
+	rm -f Module_SmartBox; 
+	$(CC) -D $(Project) -include../../../Modularization/Infypwr_PsuCommObj.h -includeConfig.h -O0 -g3 -Wall -c -fmessage-length=0 -o Module_SmartBox.o Module_SmartBox.c
+	$(CC) -lrt -o Module_SmartBox Module_SmartBox.o ../../../Modularization/libInfypwr_PsuCommObj.a
+	cp -f Module_SmartBox ../Images/root	
+
 ReadCmdlineTask:
 	rm -f ReadCmdline; 
 	$(CC) -D $(Project) -includeConfig.h -O0 -g3 -Wall -c -fmessage-length=0 -o ReadCmdline.o ReadCmdline.c

二進制
EVSE/Projects/DS60-120/Apps/Module_EvComm


文件差異過大導致無法顯示
+ 393 - 247
EVSE/Projects/DS60-120/Apps/Module_EvComm.c


+ 0 - 1
EVSE/Projects/DS60-120/Apps/Module_EvComm.h

@@ -7,7 +7,6 @@ int CanFd;
 
 typedef unsigned char 		byte;
 
-
 typedef enum
 {
     EV_Slave_Address_Broadcast  	= 0xFF,

二進制
EVSE/Projects/DS60-120/Apps/Module_EventLogging


+ 70 - 23
EVSE/Projects/DS60-120/Apps/Module_EventLogging.c

@@ -87,7 +87,7 @@ int StoreLogMsg(const char *fmt, ...)
 	}
 	else
 	{
-		sprintf(Buf,"echo \"%04d-%02d-%02d %02d:%02d:%02d:%03d - %s\" >> /Storage/SystemLog/[%04d.%02d]SystemLog_%s",
+		sprintf(Buf,"echo \"%04d-%02d-%02d %02d:%02d:%02d:%03d - %s\" >> /Storage/SystemLog/[%04d.%02d]SystemLog_%s_Log",
 			tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec,SeqEndTime.millitm,
 			buffer,
 			tm->tm_year+1900,tm->tm_mon+1,
@@ -437,21 +437,43 @@ int main(void)
 					{
 						memset(EventCodeTmp,0,sizeof(EventCodeTmp));
 						memcpy(EventCodeTmp,FaultStatusCode[ByteCount*8+BitCount],sizeof(EventCodeTmp)-1);
-						if(((tmp>>BitCount)&0x01)==0)//Recovered
+
+						if((strstr((char*)EventCodeTmp, "11021") == NULL) &&
+								(strstr((char*)EventCodeTmp, "11022") == NULL))
 						{
-							//EventCodeTmp[0]=1;
-							DEBUG_INFO("Recovery Fault Code = %s\n", EventCodeTmp);
-							ShmStatusCodeData->FaultCode.PreviousFaultVal[ByteCount] &= ~(1<<BitCount);
-							RemoveFaultCodeToBuf(EventCodeTmp);
-							EventCodeTmp[0] = '1';
-							isChanged = CHANGED;
+							if(((tmp>>BitCount)&0x01)==0)//Recovered
+							{
+								//EventCodeTmp[0]=1;
+								DEBUG_INFO("Recovery Fault Code = %s\n", EventCodeTmp);
+								ShmStatusCodeData->FaultCode.PreviousFaultVal[ByteCount] &= ~(1<<BitCount);
+								RemoveFaultCodeToBuf(EventCodeTmp);
+								EventCodeTmp[0] = '1';
+								isChanged = CHANGED;
+							}
+							else
+							{
+								DEBUG_INFO("Fault Code = %s\n", EventCodeTmp);
+								ShmStatusCodeData->FaultCode.PreviousFaultVal[ByteCount] |= (1<<BitCount);
+								AddFaultCodeToBuf(EventCodeTmp);
+								isChanged = CHANGED;
+							}
 						}
 						else
 						{
-							DEBUG_INFO("Fault Code = %s\n", EventCodeTmp);
-							ShmStatusCodeData->FaultCode.PreviousFaultVal[ByteCount] |= (1<<BitCount);
-							AddFaultCodeToBuf(EventCodeTmp);
-							isChanged = CHANGED;
+							if (((tmp >> BitCount) & 0x01) == 0) //Recovered
+							{
+								//EventCodeTmp[0]=1;
+								DEBUG_INFO( "Recovery Fault Code - no show = %s\n", EventCodeTmp );
+								ShmStatusCodeData->FaultCode.PreviousFaultVal [ByteCount] &= ~ (1 << BitCount);
+								EventCodeTmp [0] = '1';
+								isChanged = CHANGED;
+							}
+							else
+							{
+								DEBUG_INFO( "Fault Code - no show = %s\n", EventCodeTmp );
+								ShmStatusCodeData->FaultCode.PreviousFaultVal [ByteCount] |= (1 << BitCount);
+								isChanged = CHANGED;
+							}
 						}
 
 						EVENT_INFO("%s\n", EventCodeTmp);
@@ -521,21 +543,46 @@ int main(void)
 					{
 						memset(EventCodeTmp,0,sizeof(EventCodeTmp));
 						memcpy(EventCodeTmp,InfoStatusCode[ByteCount*8+BitCount],sizeof(EventCodeTmp)-1);
-						if(((tmp>>BitCount)&0x01)==0)//Recovered
+
+						if ((strstr ( (char*) EventCodeTmp, "13622" ) == NULL) &&
+								(strstr ( (char*) EventCodeTmp, "13623" ) == NULL) &&
+								(strstr ( (char*) EventCodeTmp, "13624" ) == NULL) &&
+								(strstr ( (char*) EventCodeTmp, "13625" ) == NULL) &&
+								(strstr ( (char*) EventCodeTmp, "13626" ) == NULL))
 						{
-							//EventCodeTmp[0]=1;
-							DEBUG_INFO("Recovery Info Code = %s\n", EventCodeTmp);
-							ShmStatusCodeData->InfoCode.PreviousInfoVal[ByteCount] &= ~(1<<BitCount);
-							RemoveFaultCodeToBuf(EventCodeTmp);
-							EventCodeTmp[0] = '1';
-							isChanged = CHANGED;
+							if(((tmp>>BitCount)&0x01)==0)//Recovered
+							{
+								//EventCodeTmp[0]=1;
+								DEBUG_INFO("Recovery Info Code = %s\n", EventCodeTmp);
+								ShmStatusCodeData->InfoCode.PreviousInfoVal[ByteCount] &= ~(1<<BitCount);
+								RemoveFaultCodeToBuf(EventCodeTmp);
+								EventCodeTmp[0] = '1';
+								isChanged = CHANGED;
+							}
+							else
+							{
+								DEBUG_INFO("Info Code = %s\n", EventCodeTmp);
+								ShmStatusCodeData->InfoCode.PreviousInfoVal[ByteCount] |= (1<<BitCount);
+								AddFaultCodeToBuf(EventCodeTmp);
+								isChanged = CHANGED;
+							}
 						}
 						else
 						{
-							DEBUG_INFO("Info Code = %s\n", EventCodeTmp);
-							ShmStatusCodeData->InfoCode.PreviousInfoVal[ByteCount] |= (1<<BitCount);
-							AddFaultCodeToBuf(EventCodeTmp);
-							isChanged = CHANGED;
+							if (((tmp >> BitCount) & 0x01) == 0) //Recovered
+							{
+								//EventCodeTmp[0]=1;
+								DEBUG_INFO( "Recovery Info Code - no show = %s\n", EventCodeTmp );
+								ShmStatusCodeData->InfoCode.PreviousInfoVal [ByteCount] &= ~ (1 << BitCount);
+								EventCodeTmp [0] = '1';
+								isChanged = CHANGED;
+							}
+							else
+							{
+								DEBUG_INFO( "Info Code - no show = %s \n", EventCodeTmp );
+								ShmStatusCodeData->InfoCode.PreviousInfoVal [ByteCount] |= (1 << BitCount);
+								isChanged = CHANGED;
+							}
 						}
 
 						EVENT_INFO("%s\n", EventCodeTmp);

二進制
EVSE/Projects/DS60-120/Apps/Module_InternalComm


+ 456 - 105
EVSE/Projects/DS60-120/Apps/Module_InternalComm.c

@@ -69,6 +69,7 @@ struct OCPP16Data				*ShmOCPP16Data;
 struct OCPP20Data				*ShmOCPP20Data;
 struct PrimaryMcuData			*ShmPrimaryMcuData;
 struct DcCommonInformation		*ShmDcCommonData;
+struct SmartBoxData				*ShmSmartBoxData;
 
 #define VIN_MAX_VOLTAGE_IEC			285	// 大於該值 : OVP
 #define VIN_MAX_REV_VOLTAGE_IEC		275	// 小於賦歸 OVP
@@ -80,6 +81,18 @@ struct DcCommonInformation		*ShmDcCommonData;
 #define VIN_MIN_VOLTAGE_UL			210	// 小於該值 : UVP
 #define VIN_MIN_REV_VOLTAGE_UL 		220	// 大於賦歸 UVP
 
+//LWADD
+#define VIN_MAX_VOLTAGE_JARI			285	// 大於該值 : OVP // 日規 (W)
+#define VIN_MAX_REV_VOLTAGE_JARI		275	// 小於賦歸 OVP
+#define VIN_MIN_VOLTAGE_JARI			187	// 小於該值 : UVP
+#define VIN_MIN_REV_VOLTAGE_JARI 		197	// 大於賦歸 UVP
+
+// 50KW 系統
+#define VIN_MAX_VOLTAGE_JARI_50KW		250	// 大於該值 : OVP // 日規 (W)
+#define VIN_MAX_REV_VOLTAGE_JARI_50KW	240	// 小於賦歸 OVP
+#define VIN_MIN_VOLTAGE_JARI_50KW		170	// 小於該值 : UVP
+#define VIN_MIN_REV_VOLTAGE_JARI_50KW	180	// 大於賦歸 UVP
+
 #define VIN_DROP_VOLTAGE	150	// 小於該值 : ac drop
 
 #define VOUT_MAX_VOLTAGE	995
@@ -168,11 +181,14 @@ byte 			_ac_duty;
 
 bool isCriticalStop;
 struct timespec	_psuCriticalStop;
+bool isSelftestComp = false;
 
 unsigned short _setFanSpeed = 0;
 float _beforeChargingTotalEnergy = 0.0;
 byte _checkLedChanged = 3;
 byte relayMatchFlag = 0;
+// 50KW系統
+bool is50kwSystem;
 
 Ver ver;
 PresentInputVoltage inputVoltage;
@@ -304,7 +320,7 @@ int StoreLogMsg(const char *fmt, ...)
 	}
 	else
 	{
-		sprintf(Buf,"echo \"%04d-%02d-%02d %02d:%02d:%02d:%03d - %s\" >> /Storage/SystemLog/[%04d.%02d]SystemLog_%s",
+		sprintf(Buf,"echo \"%04d-%02d-%02d %02d:%02d:%02d:%03d - %s\" >> /Storage/SystemLog/[%04d.%02d]SystemLog_%s_Log",
 			tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec,SeqEndTime.millitm,
 			buffer,
 			tm->tm_year+1900,tm->tm_mon+1,
@@ -520,10 +536,17 @@ void GetPresentInputVol()
 	if (Query_Present_InputVoltage(Uart5Fd, Addr.Relay, &inputVoltage) == PASS)
 	{
 		// resolution : 0.1
+		if (ShmSysConfigAndInfo->SysInfo.ChargerType == _CHARGER_TYPE_JARI &&
+				is50kwSystem)
+		{
+			inputVoltage.L1N_L12 *= 1.732;
+			inputVoltage.L2N_L23 *= 1.732;
+			inputVoltage.L3N_L31 *= 1.732;
+		}
+
 		ShmSysConfigAndInfo->SysInfo.InputVoltageR = ShmRelayModuleData->InputL1Volt = inputVoltage.L1N_L12;
 		ShmSysConfigAndInfo->SysInfo.InputVoltageS = ShmRelayModuleData->InputL2Volt = inputVoltage.L2N_L23;
 		ShmSysConfigAndInfo->SysInfo.InputVoltageT = ShmRelayModuleData->InputL3Volt = inputVoltage.L3N_L31;
-
 		//********************************************************************************************************//
 		// Vin (UVP)
 		if (ShmSysConfigAndInfo->SysInfo.ChargerType == _CHARGER_TYPE_IEC)
@@ -650,6 +673,134 @@ void GetPresentInputVol()
 				}
 			}
 		}
+		else if (ShmSysConfigAndInfo->SysInfo.ChargerType == _CHARGER_TYPE_JARI)
+		{
+			if (!is50kwSystem)
+			{
+				//LWADD
+				if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP == NO)
+				{
+					if (inputVoltage.L1N_L12 < VIN_MIN_VOLTAGE_JARI)
+					{
+						PRINTF_FUNC("In Uvp L1N_L12 = %f \n", inputVoltage.L1N_L12);
+						if (_threePhaseUvp[0] >= OVP_UVP_CHK_COUNT)
+							ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP = YES;
+						else
+							_threePhaseUvp[0] += 1;
+					}
+				}
+				else
+				{
+					if (inputVoltage.L1N_L12 > VIN_MIN_REV_VOLTAGE_JARI)
+					{
+						ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP = NO;
+						_threePhaseUvp[0] = 0;
+					}
+				}
+
+				if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP == NO)
+				{
+					if (inputVoltage.L2N_L23 < VIN_MIN_VOLTAGE_JARI)
+					{
+						PRINTF_FUNC("In Uvp L2N_L23 = %f \n", inputVoltage.L2N_L23);
+						if (_threePhaseUvp[1] >= OVP_UVP_CHK_COUNT)
+							ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP = YES;
+						else
+							_threePhaseUvp[1] += 1;
+					}
+				}
+				else
+				{
+					if (inputVoltage.L2N_L23 > VIN_MIN_REV_VOLTAGE_JARI)
+					{
+						ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP = NO;
+						_threePhaseUvp[1] = 0;
+					}
+				}
+
+				if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP == NO)
+				{
+					if (inputVoltage.L3N_L31 < VIN_MIN_VOLTAGE_JARI)
+					{
+						PRINTF_FUNC("In Uvp L3N_L31 = %f \n", inputVoltage.L3N_L31);
+						if (_threePhaseUvp[2] >= OVP_UVP_CHK_COUNT)
+							ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP = YES;
+						else
+							_threePhaseUvp[2] += 1;
+					}
+				}
+				else
+				{
+					if (inputVoltage.L3N_L31 > VIN_MIN_REV_VOLTAGE_JARI)
+					{
+						ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP = NO;
+						_threePhaseUvp[2] = 0;
+					}
+				}
+			}
+			else
+			{
+				if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP == NO)
+				{
+					if (inputVoltage.L1N_L12 < VIN_MIN_VOLTAGE_JARI_50KW)
+					{
+						PRINTF_FUNC("In Uvp L1N_L12 = %f \n", inputVoltage.L1N_L12);
+						if (_threePhaseUvp[0] >= OVP_UVP_CHK_COUNT)
+							ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP = YES;
+						else
+							_threePhaseUvp[0] += 1;
+					}
+				}
+				else
+				{
+					if (inputVoltage.L1N_L12 > VIN_MIN_REV_VOLTAGE_JARI_50KW)
+					{
+						ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP = NO;
+						_threePhaseUvp[0] = 0;
+					}
+				}
+
+				if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP == NO)
+				{
+					if (inputVoltage.L2N_L23 < VIN_MIN_VOLTAGE_JARI_50KW)
+					{
+						PRINTF_FUNC("In Uvp L2N_L23 = %f \n", inputVoltage.L2N_L23);
+						if (_threePhaseUvp[1] >= OVP_UVP_CHK_COUNT)
+							ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP = YES;
+						else
+							_threePhaseUvp[1] += 1;
+					}
+				}
+				else
+				{
+					if (inputVoltage.L2N_L23 > VIN_MIN_REV_VOLTAGE_JARI_50KW)
+					{
+						ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP = NO;
+						_threePhaseUvp[1] = 0;
+					}
+				}
+
+				if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP == NO)
+				{
+					if (inputVoltage.L3N_L31 < VIN_MIN_VOLTAGE_JARI_50KW)
+					{
+						PRINTF_FUNC("In Uvp L3N_L31 = %f \n", inputVoltage.L3N_L31);
+						if (_threePhaseUvp[2] >= OVP_UVP_CHK_COUNT)
+							ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP = YES;
+						else
+							_threePhaseUvp[2] += 1;
+					}
+				}
+				else
+				{
+					if (inputVoltage.L3N_L31 > VIN_MIN_REV_VOLTAGE_JARI_50KW)
+					{
+						ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP = NO;
+						_threePhaseUvp[2] = 0;
+					}
+				}
+			}
+		}
 		//********************************************************************************************************//
 		// Vin (OVP)
 		if (ShmSysConfigAndInfo->SysInfo.ChargerType == _CHARGER_TYPE_IEC)
@@ -776,6 +927,134 @@ void GetPresentInputVol()
 				}
 			}
 		}
+		else if (ShmSysConfigAndInfo->SysInfo.ChargerType == _CHARGER_TYPE_JARI)
+		{
+			if (!is50kwSystem)
+			{
+				//LWADD
+				if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP == NO)
+				{
+					if (inputVoltage.L1N_L12 > VIN_MAX_VOLTAGE_JARI)
+					{
+						PRINTF_FUNC("In Ovp L1N_L12 = %f \n", inputVoltage.L1N_L12);
+						if (_threePhaseOvp[0] >= OVP_UVP_CHK_COUNT)
+							ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP = YES;
+						else
+							_threePhaseOvp[0] += 0;
+					}
+				}
+				else
+				{
+					if (inputVoltage.L1N_L12 < VIN_MAX_REV_VOLTAGE_JARI)
+					{
+						ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP = NO;
+						_threePhaseOvp[0] = 0;
+					}
+				}
+
+				if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP == NO)
+				{
+					if (inputVoltage.L2N_L23 > VIN_MAX_VOLTAGE_JARI)
+					{
+						PRINTF_FUNC("In Ovp L2N_L23 = %f \n", inputVoltage.L2N_L23);
+						if (_threePhaseOvp[1] >= OVP_UVP_CHK_COUNT)
+							ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP = YES;
+						else
+							_threePhaseOvp[1] += 0;
+					}
+				}
+				else
+				{
+					if (inputVoltage.L2N_L23 < VIN_MAX_REV_VOLTAGE_JARI)
+					{
+						ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP = NO;
+						_threePhaseOvp[1] = 0;
+					}
+				}
+
+				if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP == NO)
+				{
+					if (inputVoltage.L3N_L31 > VIN_MAX_VOLTAGE_JARI)
+					{
+						PRINTF_FUNC("In Ovp L3N_L31 = %f \n", inputVoltage.L3N_L31);
+						if (_threePhaseOvp[2] >= OVP_UVP_CHK_COUNT)
+							ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP = YES;
+						else
+							_threePhaseOvp[2] += 1;
+					}
+				}
+				else
+				{
+					if (inputVoltage.L3N_L31 < VIN_MAX_REV_VOLTAGE_JARI)
+					{
+						ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP = NO;
+						_threePhaseOvp[2] = 0;
+					}
+				}
+			}
+			else
+			{
+				if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP == NO)
+				{
+					if (inputVoltage.L1N_L12 > VIN_MAX_VOLTAGE_JARI_50KW)
+					{
+						PRINTF_FUNC("In Ovp L1N_L12 = %f \n", inputVoltage.L1N_L12);
+						if (_threePhaseOvp[0] >= OVP_UVP_CHK_COUNT)
+							ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP = YES;
+						else
+							_threePhaseOvp[0] += 0;
+					}
+				}
+				else
+				{
+					if (inputVoltage.L1N_L12 < VIN_MAX_REV_VOLTAGE_JARI_50KW)
+					{
+						ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP = NO;
+						_threePhaseOvp[0] = 0;
+					}
+				}
+
+				if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP == NO)
+				{
+					if (inputVoltage.L2N_L23 > VIN_MAX_VOLTAGE_JARI_50KW)
+					{
+						PRINTF_FUNC("In Ovp L2N_L23 = %f \n", inputVoltage.L2N_L23);
+						if (_threePhaseOvp[1] >= OVP_UVP_CHK_COUNT)
+							ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP = YES;
+						else
+							_threePhaseOvp[1] += 0;
+					}
+				}
+				else
+				{
+					if (inputVoltage.L2N_L23 < VIN_MAX_REV_VOLTAGE_JARI_50KW)
+					{
+						ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP = NO;
+						_threePhaseOvp[1] = 0;
+					}
+				}
+
+				if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP == NO)
+				{
+					if (inputVoltage.L3N_L31 > VIN_MAX_VOLTAGE_JARI_50KW)
+					{
+						PRINTF_FUNC("In Ovp L3N_L31 = %f \n", inputVoltage.L3N_L31);
+						if (_threePhaseOvp[2] >= OVP_UVP_CHK_COUNT)
+							ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP = YES;
+						else
+							_threePhaseOvp[2] += 1;
+					}
+				}
+				else
+				{
+					if (inputVoltage.L3N_L31 < VIN_MAX_REV_VOLTAGE_JARI_50KW)
+					{
+						ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP = NO;
+						_threePhaseOvp[2] = 0;
+					}
+				}
+			}
+		}
 	}
 }
 
@@ -935,17 +1214,37 @@ void CheckK1K2RelayOutput(byte index)
 		}
 	}
 
-	if (ShmSysConfigAndInfo->SysInfo.BridgeRelayStatus == YES)
+	if (ShmSmartBoxData->RcbParallelStatus[0] == YES)
 	{
-		if (regRelay.relay_event.bits.Gun1_Parallel_N == NO &&
-				regRelay.relay_event.bits.Gun1_Parallel_P == NO)
-			ShmSysConfigAndInfo->SysInfo.BridgeRelayStatus = NO;
+		if (regRelay.relay_event.bits.R3_BOTH_K1_K4 == NO)
+			ShmSmartBoxData->RcbParallelStatus[0] = NO;
 	}
-	else if (ShmSysConfigAndInfo->SysInfo.BridgeRelayStatus == NO)
+	else if (ShmSmartBoxData->RcbParallelStatus[0] == NO)
 	{
-		if (regRelay.relay_event.bits.Gun1_Parallel_N == YES &&
-				regRelay.relay_event.bits.Gun1_Parallel_P == YES)
-				ShmSysConfigAndInfo->SysInfo.BridgeRelayStatus = YES;
+		if (regRelay.relay_event.bits.R3_BOTH_K1_K4 == YES)
+			ShmSmartBoxData->RcbParallelStatus[0] = YES;
+	}
+
+	if (ShmSmartBoxData->RcbParallelStatus[1] == YES)
+	{
+		if (regRelay.relay_event.bits.R4_BOTH_K2_K5 == NO)
+			ShmSmartBoxData->RcbParallelStatus [1] = NO;
+	}
+	else if (ShmSmartBoxData->RcbParallelStatus [1] == NO)
+	{
+		if (regRelay.relay_event.bits.R4_BOTH_K2_K5 == YES)
+			ShmSmartBoxData->RcbParallelStatus [1] = YES;
+	}
+
+	if (ShmSmartBoxData->RcbParallelStatus[2] == YES)
+	{
+		if (regRelay.relay_event.bits.R5_BOTH_K3_K6 == NO)
+			ShmSmartBoxData->RcbParallelStatus [2] = NO;
+	}
+	else if (ShmSmartBoxData->RcbParallelStatus [2] == NO)
+	{
+		if (regRelay.relay_event.bits.R5_BOTH_K3_K6 == YES)
+			ShmSmartBoxData->RcbParallelStatus [2] = YES;
 	}
 
 //	PRINTF_FUNC("Check Relay Output. index = %d, RelayKPK2Status = %d, BridgeRelayStatus = %d \n",
@@ -1155,23 +1454,11 @@ void SetK1K2RelayStatus(byte index)
 		{
 			outputRelay.relay_event.bits.Gun1_P = NO;
 			outputRelay.relay_event.bits.Gun1_N = NO;
-
-			if (gunCount == 1 && _chargingData[index]->Type == _Type_CCS)
-			{
-				if(regRelay.relay_event.bits.CCS_Precharge == YES)
-					outputRelay.relay_event.bits.CCS_Precharge = NO;
-			}
 		}
 		else if (_chargingData[index]->Evboard_id == 0x02)
 		{
 			outputRelay.relay_event.bits.Gun2_P = NO;
 			outputRelay.relay_event.bits.Gun2_N = NO;
-
-			if (_chargingData[index]->Type == _Type_CCS)
-			{
-				if(regRelay.relay_event.bits.CCS_Precharge == YES)
-					outputRelay.relay_event.bits.CCS_Precharge = NO;
-			}
 		}
 	}
 	else if ((_chargingData[index]->SystemStatus >= SYS_MODE_PREPARE_FOR_EVSE &&
@@ -1276,60 +1563,46 @@ void SetParalleRelayStatus()
 	if (gunCount >= 2 && ShmSysConfigAndInfo->SysInfo.IsAlternatvieConf == NO)
 	{
 		if (_chargingData[0]->SystemStatus == SYS_MODE_BOOTING || _chargingData[1]->SystemStatus == SYS_MODE_BOOTING ||
-				ShmSysConfigAndInfo->SysWarningInfo.Level == _ALARM_LEVEL_CRITICAL ||
+				ShmSysConfigAndInfo->SysWarningInfo.Level == _ALARM_LEVEL_CRITICAL || !isSelftestComp ||
 				((_chargingData[0]->SystemStatus == SYS_MODE_IDLE || _chargingData[0]->SystemStatus == SYS_MODE_MAINTAIN) &&
 				(_chargingData[1]->SystemStatus == SYS_MODE_IDLE || _chargingData[1]->SystemStatus == SYS_MODE_MAINTAIN)))
 		{
 			// 初始化~ 不搭橋接
-			if (regRelay.relay_event.bits.Gun1_Parallel_P == YES)
-				outputRelay.relay_event.bits.Gun1_Parallel_P = NO;
-			else if (regRelay.relay_event.bits.Gun1_Parallel_N == YES)
-				outputRelay.relay_event.bits.Gun1_Parallel_N = NO;
+
 		}
 		else
 		{
-			if (_chargingData[0]->IsReadyToCharging == YES ||
-					_chargingData[1]->IsReadyToCharging == YES)
+			if (ShmSmartBoxData->ParallelRelayStatus[_RELAY_SWITCH_NAME_R3])
 			{
-				// ************需考慮在切換中 - 切開 relay 與搭回 relay 的時機點************
-				if (ShmSysConfigAndInfo->SysInfo.MainChargingMode == _MAIN_CHARGING_MODE_MAX)
-				{
-					if (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag < _REASSIGNED_RELAY_M_TO_A)
-					{
-						// 最大充 - 搭上橋接
-						if (regRelay.relay_event.bits.Gun1_Parallel_N == NO)
-							outputRelay.relay_event.bits.Gun1_Parallel_N = YES;
-						else if (regRelay.relay_event.bits.Gun1_Parallel_P == NO)
-							outputRelay.relay_event.bits.Gun1_Parallel_P = YES;
-					}
-					else
-					{
-						// 平均充 - 不搭
-						if (regRelay.relay_event.bits.Gun1_Parallel_P == YES)
-							outputRelay.relay_event.bits.Gun1_Parallel_P = NO;
-						else if (regRelay.relay_event.bits.Gun1_Parallel_N == YES)
-							outputRelay.relay_event.bits.Gun1_Parallel_N = NO;
-					}
-				}
-				else if (ShmSysConfigAndInfo->SysInfo.MainChargingMode == _MAIN_CHARGING_MODE_AVER)
-				{
-					if (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag < _REASSIGNED_RELAY_A_TO_M)
-					{
-						// 平均充 - 不搭
-						if (regRelay.relay_event.bits.Gun1_Parallel_P == YES)
-							outputRelay.relay_event.bits.Gun1_Parallel_P = NO;
-						else if (regRelay.relay_event.bits.Gun1_Parallel_N == YES)
-							outputRelay.relay_event.bits.Gun1_Parallel_N = NO;
-					}
-					else
-					{
-						// 最大充 - 搭上橋接
-						if (regRelay.relay_event.bits.Gun1_Parallel_N == NO)
-							outputRelay.relay_event.bits.Gun1_Parallel_N = YES;
-						else if (regRelay.relay_event.bits.Gun1_Parallel_P == NO)
-							outputRelay.relay_event.bits.Gun1_Parallel_P = YES;
-					}
-				}
+				if (regRelay.relay_event.bits.R3_BOTH_K1_K4 == NO)
+					outputRelay.relay_event.bits.R3_BOTH_K1_K4 = YES;
+			}
+			else
+			{
+				if (regRelay.relay_event.bits.R3_BOTH_K1_K4 == YES)
+					outputRelay.relay_event.bits.R3_BOTH_K1_K4 = NO;
+			}
+
+			if (ShmSmartBoxData->ParallelRelayStatus [_RELAY_SWITCH_NAME_R4])
+			{
+				if (regRelay.relay_event.bits.R4_BOTH_K2_K5 == NO)
+					outputRelay.relay_event.bits.R4_BOTH_K2_K5 = YES;
+			}
+			else
+			{
+				if (regRelay.relay_event.bits.R4_BOTH_K2_K5 == YES)
+					outputRelay.relay_event.bits.R4_BOTH_K2_K5 = NO;
+			}
+
+			if (ShmSmartBoxData->ParallelRelayStatus [_RELAY_SWITCH_NAME_R5])
+			{
+				if (regRelay.relay_event.bits.R5_BOTH_K3_K6 == NO)
+					outputRelay.relay_event.bits.R5_BOTH_K3_K6 = YES;
+			}
+			else
+			{
+				if (regRelay.relay_event.bits.R5_BOTH_K3_K6 == YES)
+					outputRelay.relay_event.bits.R5_BOTH_K3_K6 = NO;
 			}
 		}
 	}
@@ -1614,7 +1887,7 @@ void SetLedColor(struct ChargingInfoData *chargingData_1, struct ChargingInfoDat
 		}
 	}
 	else if (IsNoneMatchLedColor())
-		_checkLedChanged = 3;
+		_checkLedChanged = 5;
 }
 //==========================================
 // Init all share memory
@@ -1792,6 +2065,21 @@ int InitShareMemory()
    		return 0;
    	}
 
+	if ((MeterSMId = shmget ( ShmSmartBoxKey, sizeof(struct SmartBoxData), IPC_CREAT | 0777 )) < 0)
+	{
+		#ifdef SystemLogMessage
+		DEBUG_ERROR("shmat ShmSmartBoxKey NG \n");
+		#endif
+		return 0;
+	}
+	else if ((ShmSmartBoxData = shmat ( MeterSMId, NULL, 0 )) == (void *) - 1)
+	{
+		#ifdef SystemLogMessage
+		DEBUG_ERROR("shmat ShmSmartBoxData NG \n");
+		#endif
+		return 0;
+	}
+
 	return result;
 }
 
@@ -1961,13 +2249,13 @@ bool IsNoneMatchRelayStatus()
 	bool result = false;
 
 	if ((regRelay.relay_event.bits.AC_Contactor != outputRelay.relay_event.bits.AC_Contactor) ||
-		(regRelay.relay_event.bits.CCS_Precharge != outputRelay.relay_event.bits.CCS_Precharge) ||
+		(regRelay.relay_event.bits.R3_BOTH_K1_K4 != outputRelay.relay_event.bits.R3_BOTH_K1_K4) ||
 		(regRelay.relay_event.bits.Gun1_P != outputRelay.relay_event.bits.Gun1_P) ||
 		(regRelay.relay_event.bits.Gun1_N != outputRelay.relay_event.bits.Gun1_N) ||
 		(regRelay.relay_event.bits.Gun2_P != outputRelay.relay_event.bits.Gun2_P) ||
 		(regRelay.relay_event.bits.Gun2_N != outputRelay.relay_event.bits.Gun2_N) ||
-		(regRelay.relay_event.bits.Gun1_Parallel_P != outputRelay.relay_event.bits.Gun1_Parallel_P) ||
-		(regRelay.relay_event.bits.Gun1_Parallel_N != outputRelay.relay_event.bits.Gun1_Parallel_N))
+		(regRelay.relay_event.bits.R4_BOTH_K2_K5 != outputRelay.relay_event.bits.R4_BOTH_K2_K5) ||
+		(regRelay.relay_event.bits.R5_BOTH_K3_K6 != outputRelay.relay_event.bits.R5_BOTH_K3_K6))
 	{
 		result = true;
 	}
@@ -1977,11 +2265,6 @@ bool IsNoneMatchRelayStatus()
 		//PRINTF_FUNC("AC Contact Relay none match, try to switch to %d \n", outputRelay.relay_event.bits.AC_Contactor);
 	}
 
-	if (regRelay.relay_event.bits.CCS_Precharge != outputRelay.relay_event.bits.CCS_Precharge)
-	{
-		//PRINTF_FUNC("CCS Precharge Relay none match, try to switch to %d \n", outputRelay.relay_event.bits.CCS_Precharge);
-	}
-
 	if (regRelay.relay_event.bits.Gun1_P != outputRelay.relay_event.bits.Gun1_P)
 	{
 		StartCheckRelayInfo(RELAY_SMR1_P_STATUS, outputRelay.relay_event.bits.Gun1_P);
@@ -2023,9 +2306,9 @@ bool IsNoneMatchRelayStatus()
 		StopCheckRelayInfo(RELAY_SMR2_N_STATUS);
 	}
 
-	if (regRelay.relay_event.bits.Gun1_Parallel_P != outputRelay.relay_event.bits.Gun1_Parallel_P)
+	if (regRelay.relay_event.bits.R4_BOTH_K2_K5 != outputRelay.relay_event.bits.R4_BOTH_K2_K5)
 	{
-		StartCheckRelayInfo(RELAY_PARA_P_STATUS, outputRelay.relay_event.bits.Gun1_Parallel_P);
+		StartCheckRelayInfo(RELAY_PARA_P_STATUS, outputRelay.relay_event.bits.R4_BOTH_K2_K5);
 		//PRINTF_FUNC("Parallel:D+ Relay none match, try to switch to %d \n", outputRelay.relay_event.bits.Gun1_Parallel_P);
 	}
 	else
@@ -2033,9 +2316,9 @@ bool IsNoneMatchRelayStatus()
 		StopCheckRelayInfo(RELAY_PARA_P_STATUS);
 	}
 
-	if (regRelay.relay_event.bits.Gun1_Parallel_N != outputRelay.relay_event.bits.Gun1_Parallel_N)
+	if (regRelay.relay_event.bits.R5_BOTH_K3_K6 != outputRelay.relay_event.bits.R5_BOTH_K3_K6)
 	{
-		StartCheckRelayInfo(RELAY_PARA_N_STATUS, outputRelay.relay_event.bits.Gun1_Parallel_N);
+		StartCheckRelayInfo(RELAY_PARA_N_STATUS, outputRelay.relay_event.bits.R5_BOTH_K3_K6);
 		//PRINTF_FUNC("Parallel:D- Relay none match, try to switch to %d \n", outputRelay.relay_event.bits.Gun1_Parallel_N);
 	}
 	else
@@ -2043,6 +2326,16 @@ bool IsNoneMatchRelayStatus()
 		StopCheckRelayInfo(RELAY_PARA_N_STATUS);
 	}
 
+	if (regRelay.relay_event.bits.R3_BOTH_K1_K4 != outputRelay.relay_event.bits.R3_BOTH_K1_K4)
+	{
+		StartCheckRelayInfo(RELAY_PRE_STATUS, outputRelay.relay_event.bits.R3_BOTH_K1_K4);
+		//PRINTF_FUNC("Parallel:D- Relay none match, try to switch to %d \n", outputRelay.relay_event.bits.Gun1_Parallel_N);
+	}
+	else
+	{
+		StopCheckRelayInfo(RELAY_PRE_STATUS);
+	}
+
 	return result;
 }
 
@@ -2051,13 +2344,13 @@ void MatchRelayStatus()
 	// 因為 AC Contactor 沒有 Feedback,所以暫時先這樣處理
 	//regRelay.relay_event.bits.AC_Contactor = outputRelay.relay_event.bits.AC_Contactor;
 	ShmSysConfigAndInfo->SysInfo.AcContactorStatus  = regRelay.relay_event.bits.AC_Contactor = outputRelay.relay_event.bits.AC_Contactor;
-	regRelay.relay_event.bits.CCS_Precharge = outputRelay.relay_event.bits.CCS_Precharge;
+	regRelay.relay_event.bits.R5_BOTH_K3_K6 = outputRelay.relay_event.bits.R5_BOTH_K3_K6;
 	regRelay.relay_event.bits.Gun1_P = outputRelay.relay_event.bits.Gun1_P;
 	regRelay.relay_event.bits.Gun1_N = outputRelay.relay_event.bits.Gun1_N;
 	regRelay.relay_event.bits.Gun2_P = outputRelay.relay_event.bits.Gun2_P;
 	regRelay.relay_event.bits.Gun2_N = outputRelay.relay_event.bits.Gun2_N;
-	regRelay.relay_event.bits.Gun1_Parallel_P = outputRelay.relay_event.bits.Gun1_Parallel_P;
-	regRelay.relay_event.bits.Gun1_Parallel_N = outputRelay.relay_event.bits.Gun1_Parallel_N;
+	regRelay.relay_event.bits.R4_BOTH_K2_K5 = outputRelay.relay_event.bits.R4_BOTH_K2_K5;
+	regRelay.relay_event.bits.R3_BOTH_K1_K4 = outputRelay.relay_event.bits.R3_BOTH_K1_K4;
 }
 
 void CheckRelayStatusByADC()
@@ -2140,7 +2433,8 @@ void CableCheckDetected(byte index)
 			else if (_chargingData[index]->SystemStatus >= SYS_MODE_CHARGING &&
 					_chargingData[index]->SystemStatus < SYS_MODE_TERMINATING)
 			{
-				if (_chargingData[index]->Type == _Type_GB || _chargingData[index]->Type == _Type_Chademo)
+				//if (_chargingData[index]->Type == _Type_GB || _chargingData[index]->Type == _Type_Chademo)
+				if (_chargingData[index]->Type == _Type_GB)
 					SetGfdConfig(index, GFD_IDLE);
 				else
 					SetGfdConfig(index, GFD_CHARGING);
@@ -2241,13 +2535,13 @@ void CheckOutputVolNoneMatchFire(byte index)
 					PRINTF_FUNC("Abnormal voltage on the Output at the stage of GFD. (%d) : pre = %.1f, fire = %.1f \n",
 							index, (_chargingData[index]->PresentChargingVoltage * 10), _chargingData[index]->FireChargingVoltage);
 
-					if (index == 0)
+					if (index == GUN_LEFT)
 					{
 						ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AbnormalVoltageOnOutputLine_1 = YES;
 						if (strncmp((char *)_chargingData[index]->ConnectorAlarmCode, "", 6) == EQUAL)
 								memcpy(_chargingData[index]->ConnectorAlarmCode, "012324", 6);
 					}
-					else if (index == 1)
+					else if (index == GUN_RIGHT)
 					{
 						ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AbnormalVoltageOnOutputLine_2 = YES;
 						if (strncmp((char *)_chargingData[index]->ConnectorAlarmCode, "", 6) == EQUAL)
@@ -2345,6 +2639,24 @@ void GetFanSpeedByFunction()
 	}
 
 	ShmFanModuleData->TestFanSpeed = (((50 * _pw_rate * _temp_rate) + (0.5 * _temp_diff)) / 100) * MAX_FAN_SPEED;
+	// 日規 50KW 系統~ 只能限制 3000 轉輸出
+	if (ShmSysConfigAndInfo->SysInfo.ChargerType == _CHARGER_TYPE_JARI)
+	{
+		if (is50kwSystem)
+		{
+			// 50KW 系統,使用 14000 轉風扇
+			// 如果輸出大於 2.5KW
+			if (ShmFanModuleData->TestFanSpeed > 5000 ||
+					power >= 25)
+				ShmFanModuleData->TestFanSpeed = 5000;
+		}
+		else
+		{
+			// 日規其他系統,使用 4400 轉風扇
+			if (ShmFanModuleData->TestFanSpeed > 9545)
+				ShmFanModuleData->TestFanSpeed = 9545;
+		}
+	}
 
 	if (ShmFanModuleData->TestFanSpeed > MAX_FAN_SPEED)
 		ShmFanModuleData->TestFanSpeed = MAX_FAN_SPEED;
@@ -3198,6 +3510,24 @@ void AcChargeTypeProcess()
 	}
 }
 
+bool Is50kwSystemChk()
+{
+	bool result = false;
+	char EvsePower[2];
+
+	EvsePower[2] = '\0';
+	if (strlen ( (char *) ShmSysConfigAndInfo->SysConfig.ModelName ) >= 6)
+	{
+		strncpy ( EvsePower, (char *) (ShmSysConfigAndInfo->SysConfig.ModelName + 4), 2);
+		if (strcmp ( EvsePower, "50" ) == EQUAL)
+		{
+			result = true;
+		}
+	}
+
+	return result;
+}
+
 void RunForceStopProcess()
 {
 	if (isCriticalStop == NO)
@@ -3244,6 +3574,8 @@ int main(void)
 	// Open Uart5 for RB
 	Uart5Fd = InitComPort();
 	Initialization();
+	is50kwSystem = Is50kwSystemChk();
+
 	sleep(1);
 
 	if(Uart5Fd < 0)
@@ -3261,16 +3593,27 @@ int main(void)
 	}
 
 	outputRelay.relay_event.bits.AC_Contactor = 0x00;
-	outputRelay.relay_event.bits.CCS_Precharge = 0x00;
-	outputRelay.relay_event.bits.Gun1_Parallel_P = 0x00;
-	outputRelay.relay_event.bits.Gun1_Parallel_N = 0x00;
-	outputRelay.relay_event.bits.Gun1_P = 0x00;
-	outputRelay.relay_event.bits.Gun1_N = 0x00;
-	outputRelay.relay_event.bits.Gun2_N = 0x00;
-	outputRelay.relay_event.bits.Gun2_P = 0x00;
+	outputRelay.relay_event.bits.R5_BOTH_K3_K6 = 0x00;		// K3 - K6 (R4)
+	outputRelay.relay_event.bits.R4_BOTH_K2_K5 = 0x00;		// K2 - K5 (R4)
+	outputRelay.relay_event.bits.R3_BOTH_K1_K4 = 0x00;		// K1 - K4 (R3)
+	outputRelay.relay_event.bits.Gun1_P = 0x00;				// 左槍 D+ (R1 +)
+	outputRelay.relay_event.bits.Gun1_N = 0x00;				// 左槍 D- (R1 -)
+	outputRelay.relay_event.bits.Gun2_N = 0x00;				// 右槍 D- (R2 -)
+	outputRelay.relay_event.bits.Gun2_P = 0x00;				// 右槍 D+ (R2 +)
 	if(Config_Relay_Output(Uart5Fd, Addr.Relay, &outputRelay) != PASS)
 		PRINTF_FUNC("Config_Relay_Output fail \n");
 
+//	sleep(1);
+//	GetRelayOutputStatus();
+//	PRINTF_FUNC("Gun1_P = %d \n", outputRelay.relay_event.bits.Gun1_P);
+//	PRINTF_FUNC("Gun1_N = %d \n", outputRelay.relay_event.bits.Gun1_N);
+//	PRINTF_FUNC("Gun2_P = %d", outputRelay.relay_event.bits.Gun2_P);
+//	PRINTF_FUNC("Gun2_N = %d", outputRelay.relay_event.bits.Gun2_N);
+//	PRINTF_FUNC("R3 = %d \n", regRelay.relay_event.bits.R3_BOTH_K1_K4);
+//	PRINTF_FUNC("R4 = %d \n", regRelay.relay_event.bits.R4_BOTH_K2_K5);
+//	PRINTF_FUNC("R5 = %d \n", regRelay.relay_event.bits.R5_BOTH_K3_K6);
+//	return -1;
+
 	cur_led_color.Connect_1_Red = COLOR_MIN_LV;
 	cur_led_color.Connect_1_Green = COLOR_MIN_LV;
 	cur_led_color.Connect_1_Blue = COLOR_MIN_LV;
@@ -3280,6 +3623,7 @@ int main(void)
 
 	relayMatchFlag = NO;
 	isCriticalStop = NO;
+	isSelftestComp = NO;
 	GetTimespecFunc(&_led_blink_time);
 
 	for(;;)
@@ -3325,6 +3669,8 @@ int main(void)
 
 		if (ShmRelayModuleData->SelfTest_Comp == YES)
 		{
+			if (ShmSysConfigAndInfo->SysInfo.PageIndex == _LCM_IDLE && !isSelftestComp)
+				isSelftestComp = true;
 			// ==============優先權最高 10 ms ==============
 			// 輸出電壓
 			GetPersentOutputVol();
@@ -3354,7 +3700,7 @@ int main(void)
 					_isOvpChkTimeFlag[i] = NO;
 				}
 
-				if (_chargingData[i]->SystemStatus == SYS_MODE_BOOTING	||
+				if (_chargingData[i]->SystemStatus == SYS_MODE_BOOTING || _chargingData[i]->ConnectorPlugIn ||
 					(_chargingData[i]->SystemStatus >= SYS_MODE_MODE_REASSIGN_CHECK && _chargingData[i]->SystemStatus <= SYS_MODE_ALARM) ||
 					(_chargingData[i]->SystemStatus >= SYS_MODE_CCS_PRECHARGE_STEP0 && _chargingData[i]->SystemStatus <= SYS_MODE_CCS_PRECHARGE_STEP1) ||
 					ShmSysConfigAndInfo->SysInfo.WaitForPlugit == YES ||
@@ -3435,7 +3781,11 @@ int main(void)
 
 				if (Config_Relay_Output(Uart5Fd, Addr.Relay, &outputRelay))
 				{
-					//regRelay.relay_event.bits.AC_Contactor = ShmSysConfigAndInfo->SysInfo.AcContactorStatus;
+//					regRelay.relay_event.bits.R5_BOTH_K3_K6 = outputRelay.relay_event.bits.R5_BOTH_K3_K6;
+//					regRelay.relay_event.bits.R4_BOTH_K2_K5 = outputRelay.relay_event.bits.R4_BOTH_K2_K5;
+//					regRelay.relay_event.bits.R3_BOTH_K1_K4 = outputRelay.relay_event.bits.R3_BOTH_K1_K4;
+
+//					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;
@@ -3474,20 +3824,21 @@ int main(void)
 				else
 					PRINTF_FUNC("Conn2(-) : OFF \n");
 
-				if (regRelay.relay_event.bits.CCS_Precharge == YES)
-					PRINTF_FUNC("Precharge : ON \n");
+				if (regRelay.relay_event.bits.R3_BOTH_K1_K4 == YES)
+					PRINTF_FUNC("R3_BOTH_K1_K4 : ON \n");
 				else
-					PRINTF_FUNC("Precharge : OFF \n");
+					PRINTF_FUNC("R3_BOTH_K1_K4 : OFF \n");
 
-				if (regRelay.relay_event.bits.Gun1_Parallel_P == YES)
-					PRINTF_FUNC("Parallel(+) : ON \n");
+				if (regRelay.relay_event.bits.R4_BOTH_K2_K5 == YES)
+					PRINTF_FUNC("R4_BOTH_K2_K5 : ON \n");
 				else
-					PRINTF_FUNC("Parallel(+) : OFF \n");
+					PRINTF_FUNC("R4_BOTH_K2_K5 : OFF \n");
 
-				if (regRelay.relay_event.bits.Gun1_Parallel_N == YES)
-					PRINTF_FUNC("Parallel(-) : ON \n");
+				if (regRelay.relay_event.bits.R5_BOTH_K3_K6 == YES)
+					PRINTF_FUNC("R5_BOTH_K3_K6 : ON \n");
 				else
-					PRINTF_FUNC("Parallel(-) : OFF \n");
+					PRINTF_FUNC("R5_BOTH_K3_K6 : OFF \n");
+
 				PRINTF_FUNC("======== Relay Status End========\n");
 			}
 		}

+ 62 - 0
EVSE/Projects/DS60-120/Apps/Module_LcmContro.h

@@ -123,11 +123,16 @@ short __plug_in_arrow = 0x0060;
 short __conn_line = 0x0066;
 
 short __gun_type_index = 0x0070;
+short __gun_type_index_jp = 0x0076;
 short __cmp_gun_type_index = 0x0080;
+short __cmp_gun_type_index_jp = 0x0086;
 short __qr_code_pre = 0x0280;
 
 short __batt_map_empty = 0x0090;
 
+//LW_tpc plug detect
+short __tpc_detect_map = 0x0092;
+
 short __conn_line_chag = 0x0096;
 short __batt_map = 0x0100;
 short __soc_value_charging = 0x0102;
@@ -165,6 +170,40 @@ short __eth0_ip_value = 0x0370;
 short __sn_string = 0x0410;
 short __sn_value = 0x0420;
 
+short __sys_date_value = 0x0470;
+short __sys_time_value = 0x0480;
+short __sys_period_value = 0x0489;
+
+short __Energy_Cost_complete = 0x0500;
+short __Parking_Fee_complete = 0x0510;
+short __Total_Cost_complete = 0x0520;
+short __ctep_time_string = 0x0530;
+short __ctep_energy_string = 0x0540;
+short __ctep_energy_mon_string = 0x0550;
+short __ctep_packing_mon_string = 0x0560;
+short __ctep_total_mon_string = 0x0570;
+
+short __Energy_Cost_charging = 0x610;
+short __Parking_Fee_charging = 0x620;
+short __Total_Cost_charging = 0x630;
+
+short __Energy_Cost_comp = 0x640;
+short __Parking_Fee_comp = 0x650;
+short __Total_Cost_comp = 0x660;
+short __receipt_qrcode = 0x0670;
+short __receipt_qrcode_bg = 0x0700;
+short _ctep_energy_mon_comm = 0x0702;
+short _ctep_packing_mon_comm = 0x0704;
+short _ctep_total_mon_comm = 0x0706;
+short _ctep_energy_mon_chg = 0x0708;
+short _ctep_packing_mon_chg = 0x070A;
+short _ctep_total_mon_chg = 0x070C;
+short _ctep_energy_mon_comp = 0x070E;
+short _ctep_packing_mon_comp = 0x0710;
+short _ctep_total_mon_comp = 0x0712;
+
+short __scroll_display_value = 0x6010;
+
 // ICON ID
 byte _disappear = 0;
 byte _disconnect = 1;
@@ -233,3 +272,26 @@ byte _battery_eng_trp_map = 63;
 byte _money_trp_map = 64;
 byte _elapse_time_trp_map = 65;
 byte _phihong_string_map = 66;
+byte _ctep_qr_background = 67;
+byte _ctep_packing_mon_comm_map = 68;
+byte _ctep_energy_mon_comm_map = 69;
+byte _ctep_total_mon_comm_map = 70;
+byte _ctep_packing_mon_comp_map = 71;
+byte _ctep_energy_mon_comp_map = 72;
+byte _ctep_total_mon_comp_map = 73;
+byte _ctep_packing_mon_chg_map= 74;
+byte _ctep_energy_mon_chg_map = 75;
+byte _ctep_total_mon_chg_map = 76;
+
+//LW_tpc plug detect
+byte _tpc_start_detect_btn = 77;
+byte _tpc_wait_plugin_btn= 78;
+
+byte _n1_jp_cha_dark = 96;
+byte _n2_jp_cha_dark = 97;
+byte _n1_jp_cha_light = 98;
+byte _n2_jp_cha_light = 99;
+byte _n1_jp_cha_dark_cmp = 100;
+byte _n2_jp_cha_dark_cmp = 101;
+byte _n1_jp_cha_light_cmp = 102;
+byte _n2_jp_cha_light_cmp = 103;

二進制
EVSE/Projects/DS60-120/Apps/Module_LcmControl


+ 86 - 13
EVSE/Projects/DS60-120/Apps/Module_LcmControl.c

@@ -44,7 +44,7 @@ int StoreLogMsg(const char *fmt, ...)
 	}
 	else
 	{
-		sprintf(Buf,"echo \"%04d-%02d-%02d %02d:%02d:%02d:%03d - %s\" >> /Storage/SystemLog/[%04d.%02d]SystemLog_%s",
+		sprintf(Buf,"echo \"%04d-%02d-%02d %02d:%02d:%02d:%03d - %s\" >> /Storage/SystemLog/[%04d.%02d]SystemLog_%s_Log",
 			tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec,SeqEndTime.millitm,
 			buffer,
 			tm->tm_year+1900,tm->tm_mon+1,
@@ -1329,6 +1329,17 @@ void ProcessPageInfo()
 			{
 				ChangeDisplay2Value(__sel_gun_btn, _disappear);
 			}
+
+			//LW_tpc plug detect
+			if (ShmDcCommonData->TpcDetectFunction == YES)
+			{
+				if (ShmDcCommonData->_tpcPlugDetectState == _TPC_PLUG_DETECT_STATUS_NONE)
+					ChangeDisplay2Value ( __tpc_detect_map, _tpc_start_detect_btn );
+				else if (ShmDcCommonData->_tpcPlugDetectState == _TPC_PLUG_DETECT_STATUS_WAIT)
+					ChangeDisplay2Value ( __tpc_detect_map, _tpc_wait_plugin_btn );
+			}
+			else
+				ChangeDisplay2Value ( __tpc_detect_map, _disappear );
 		}
 			break;
 		case _LCM_AUTHORIZING:
@@ -1476,6 +1487,7 @@ void ProcessPageInfo()
 			}
 			else
 			{
+				// 超過一把槍, 把中間圖隱藏
 				if (_totalCount > 1)
 				{
 					gunTargetIndex = 2;
@@ -1488,7 +1500,7 @@ void ProcessPageInfo()
 			for(byte i = 0; i < _totalCount; i++)
 			{
 				if (_totalCount == 1 && acgunCount <= 0)
-					gunTargetIndex = 2;
+					gunTargetIndex = 1;
 				else
 					gunTargetIndex = i;
 
@@ -1498,17 +1510,57 @@ void ProcessPageInfo()
 					{
 						if (ShmSysConfigAndInfo->SysInfo.CurGunSelected == i && !isShowAc)
 						{
-							if (_currentPage == _LCM_COMPLETE)
-								ChangeDisplay2Value(__cmp_gun_type_index + (gunTargetIndex * 2), _chademo_light_cmp);
+							if (_totalCount >= 2 && ShmSysConfigAndInfo->SysInfo.ChargerType == _CHARGER_TYPE_JARI)
+							{
+								if (_currentPage == _LCM_COMPLETE)
+								{
+									if (i == 0)
+										ChangeDisplay2Value(__cmp_gun_type_index_jp + (gunTargetIndex * 2), _n1_jp_cha_light_cmp);
+									else
+										ChangeDisplay2Value(__cmp_gun_type_index_jp + (gunTargetIndex * 2), _n2_jp_cha_light_cmp);
+								}
+								else
+								{
+									if (i == 0)
+										ChangeDisplay2Value(__gun_type_index_jp + (gunTargetIndex * 2), _n1_jp_cha_light);
+									else
+										ChangeDisplay2Value(__gun_type_index_jp + (gunTargetIndex * 2), _n2_jp_cha_light);
+								}
+							}
 							else
-								ChangeDisplay2Value(__gun_type_index + (gunTargetIndex * 2), _chademo_light);
+							{
+								if (_currentPage == _LCM_COMPLETE)
+									ChangeDisplay2Value(__cmp_gun_type_index + (gunTargetIndex * 2), _chademo_light_cmp);
+								else
+									ChangeDisplay2Value(__gun_type_index + (gunTargetIndex * 2), _chademo_light);
+							}
 						}
 						else
 						{
-							if (_currentPage == _LCM_COMPLETE)
-								ChangeDisplay2Value(__cmp_gun_type_index + (gunTargetIndex * 2), _chademo_dark_cmp);
+							if (_totalCount >= 2 && ShmSysConfigAndInfo->SysInfo.ChargerType == _CHARGER_TYPE_JARI)
+							{
+								if (_currentPage == _LCM_COMPLETE)
+								{
+									if (i == 0)
+										ChangeDisplay2Value(__cmp_gun_type_index_jp + (gunTargetIndex * 2), _n1_jp_cha_dark_cmp);
+									else
+										ChangeDisplay2Value(__cmp_gun_type_index_jp + (gunTargetIndex * 2), _n2_jp_cha_dark_cmp);
+								}
+								else
+								{
+									if (i == 0)
+										ChangeDisplay2Value(__gun_type_index_jp + (gunTargetIndex * 2), _n1_jp_cha_dark);
+									else
+										ChangeDisplay2Value(__gun_type_index_jp + (gunTargetIndex * 2), _n2_jp_cha_dark);
+								}
+							}
 							else
-								ChangeDisplay2Value(__gun_type_index + (gunTargetIndex * 2), _chademo_dark);
+							{
+								if (_currentPage == _LCM_COMPLETE)
+									ChangeDisplay2Value(__cmp_gun_type_index + (gunTargetIndex * 2), _chademo_dark_cmp);
+								else
+									ChangeDisplay2Value(__gun_type_index + (gunTargetIndex * 2), _chademo_dark);
+							}
 						}
 					}
 						break;
@@ -1584,7 +1636,7 @@ void ProcessPageInfo()
 								strcmp((char *)_chargingInfoData[i]->StartUserId, "") == 0 ||
 								ShmSysConfigAndInfo->SysConfig.StopChargingByButton == YES ||
 								_chargingInfoData[i]->isRemoteStart ||
-								ShmDcCommonData->_authWithCcidFlag [i] == _CCID_AUTHCOMP)
+								ShmDcCommonData->enObtainAuthorizbyCCID)
 							ChangeDisplay2Value(__stop_method_btn, _stop_charging_btn);
 						else
 							ChangeDisplay2Value(__stop_method_btn, _stop_charging_btn_scan);
@@ -1858,6 +1910,15 @@ void DefaultIconStatus()
 	for(byte i = 0; i < 3; i++)
 		ChangeDisplay2Value(__gun_type_index + (i * 2), _disappear);
 
+	for(byte i = 0; i < 3; i++)
+		ChangeDisplay2Value(__cmp_gun_type_index + (i * 2), _disappear);
+
+	for(byte i = 0; i < 2; i++)
+		ChangeDisplay2Value(__gun_type_index_jp + (i * 2), _disappear);
+
+	for(byte i = 0; i < 2; i++)
+		ChangeDisplay2Value(__cmp_gun_type_index_jp + (i * 2), _disappear);
+
 	if (ShmSysConfigAndInfo->SysInfo.IsAlternatvieConf == YES || _totalCount == 1)
 		ChangeDisplay2Value(__sel_gun_btn, _disappear);
 	else
@@ -1874,6 +1935,12 @@ void DefaultIconStatus()
 		ChangeDisplay2Value(__logo_cmp, _disappear);
 	}
 
+	//LW_tpc plug detects
+	if (ShmDcCommonData->TpcDetectFunction == YES)
+		ChangeDisplay2Value(__tpc_detect_map, _tpc_start_detect_btn);
+	else
+		ChangeDisplay2Value(__tpc_detect_map, _disappear);
+
 	char _buf[3] = {0};
 	memcpy(_buf, &ShmSysConfigAndInfo->SysConfig.ModelName[12], 2);
 
@@ -1914,9 +1981,13 @@ int main(void)
 
 	Initialization();
 
-	//	ChangeToOtherPage(_LCM_IDLE);
-	//	ChangeDisplay2Value(__phihong_string, _disappear);
-	//	return -1;
+//	ChangeToOtherPage(_LCM_CHARGING);
+	//ChangeChargingPowerValue(1.1);
+	//ChangeChargingEnergyValue(3.225);
+//	ChangeDisplay2Value(__phihong_string, _disappear);
+
+	///ChangeDisplayMoneyInfo();
+//	ChangeToOtherPage(_LCM_INIT);
 
 	DefaultIconStatus();
 
@@ -1947,7 +2018,7 @@ int main(void)
 
 			if (_verShowCount > 0)
 			{
-				PRINTF_FUNC("LCM Version = V.%03d \n", ShmDcCommonData->LcmFwVersion);
+				//PRINTF_FUNC("LCM Version = V.%03d \n", ShmDcCommonData->LcmFwVersion);
 				_verShowCount--;
 			}
 
@@ -1979,11 +2050,13 @@ int main(void)
 
 				ChangeWarningFunc();
 			}
+
 			// 頁面資訊處理
 			ProcessPageInfo();
 
 			// 網路 - wifi - 連線訊號處理
 			RefreshConnStatus();
+
 			// 換頁處理
 			GetCurrentPage();
 			ChangeCurPage();

二進制
EVSE/Projects/DS60-120/Apps/Module_PrimaryComm


+ 3 - 5
EVSE/Projects/DS60-120/Apps/Module_PrimaryComm.c

@@ -99,7 +99,7 @@ int StoreLogMsg(const char *fmt, ...)
 	}
 	else
 	{
-		sprintf(Buf,"echo \"%04d-%02d-%02d %02d:%02d:%02d:%03d - %s\" >> /Storage/SystemLog/[%04d.%02d]SystemLog_%s",
+		sprintf(Buf,"echo \"%04d-%02d-%02d %02d:%02d:%02d:%03d - %s\" >> /Storage/SystemLog/[%04d.%02d]SystemLog_%s_Log",
 			tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec,SeqEndTime.millitm,
 			buffer,
 			tm->tm_year+1900,tm->tm_mon+1,
@@ -403,9 +403,7 @@ void GetMeterConsumption(byte index)
 				// 最大充時,兩個都會累加,但只輸出給一槍使用
 				ShmCsuMeterData->_meter[index]._chargingValue += ShmCsuMeterData->_meter[index].newMeterValue - ShmCsuMeterData->_meter[index].curMeterValue;
 
-				if (ShmSysConfigAndInfo->SysInfo.MainChargingMode == _MAIN_CHARGING_MODE_MAX ||
-					(ShmSysConfigAndInfo->SysInfo.MainChargingMode == _MAIN_CHARGING_MODE_AVER &&
-					ShmSysConfigAndInfo->SysInfo.ReAssignedFlag >= _REASSIGNED_RELAY_A_TO_M))
+				if (ShmSysConfigAndInfo->SysInfo.MainChargingMode == _MAIN_CHARGING_MODE_NORMAL)
 				{
 					for (byte subIndex = 0; subIndex < gun_count; subIndex++)
 					{
@@ -667,7 +665,7 @@ int main(void)
 		// 模組更新 FW 後,需重新做
 		if(ShmPrimaryMcuData->SelfTest_Comp != PASS)
 		{
-			PRINTF_FUNC("(407) Get Fw and Hw Ver. \n");
+			//PRINTF_FUNC("(407) Get Fw and Hw Ver. \n");
 			GetFwAndHwVersion();
 			sleep(1);
 			ShmPrimaryMcuData->SelfTest_Comp = PASS;

二進制
EVSE/Projects/DS60-120/Apps/Module_PsuComm


文件差異過大導致無法顯示
+ 415 - 574
EVSE/Projects/DS60-120/Apps/Module_PsuComm.c


+ 12 - 11
EVSE/Projects/DS60-120/Apps/Module_PsuComm.h

@@ -34,7 +34,10 @@ typedef unsigned char 		byte;
 typedef unsigned short 	word;
 typedef unsigned int 		unit;
 
-unsigned char _gunCount;
+#define PSU_CUR_GAP			20 	// 0.1A
+#define LOG_TIME			5000 // 1ms
+
+unsigned char _gunCountRecord;
 struct ChargingInfoData *chargingInfo[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
 bool isStartOutputSwitch[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
 
@@ -43,6 +46,8 @@ struct timespec _derating_time;
 struct timespec _max_time;
 struct timespec _log_time;
 
+byte _delayToGetCap;
+
 byte _maxChargingStatus;
 bool isReadyToCharging = false;
 int preChargingTarget;
@@ -51,13 +56,9 @@ int preChargingCur;
 float toAverVolPoint;
 byte toAverVolCount;
 
-byte _delayCount;
+int _forceWaitToCompforMaxMode;
 
-//int connector_1[12];
-//int connector_2[12];
-//int connector[2][12];
-//byte conn_1_count = 0;
-//byte conn_2_count = 0;
+byte _delay2GetPsuTemp;
 
 enum _CHARGING_GUN_STATUS
 {
@@ -73,10 +74,10 @@ enum _PSU_CMD_SEQ
 	_PSU_CMD_VERSION	= 2,
 
 	_PSU_CMD_CAP		= 10,
-	_PSU_CMD_OUTPUT		= 11,
-	_PSU_CMD_IVAILIABLE	= 12,
-	_PSU_CMD_TEMP		= 13,
-	_PSU_CMD_GETCOUNT	= 14,
+	_PSU_CMD_IAVAILABLE	= 11,
+	_PSU_CMD_TEMP		= 12,
+	_PSU_CMD_GETCOUNT	= 13,
+	_PSU_CMD_OUTPUT_V	= 14,
 };
 
 enum _CHARGING_LOG_INDEX

二進制
EVSE/Projects/DS60-120/Apps/Module_SmartBox


+ 1475 - 0
EVSE/Projects/DS60-120/Apps/Module_SmartBox.c

@@ -0,0 +1,1475 @@
+/*
+ * Module_SmartBox.c
+ *
+ *  Created on: 2022年5月3日
+ *      Author: 7564
+ */
+
+#include "Module_SmartBox.h"
+
+struct SysConfigAndInfo			*ShmSysConfigAndInfo;
+struct StatusCodeData 			*ShmStatusCodeData;
+struct PsuData 					*ShmPsuData;
+struct DcCommonInformation		*ShmDcCommonData;
+struct SmartBoxData				*ShmSmartBoxData;
+
+struct ChargingInfoData *chargingInfo[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
+byte ConnectorUsingSeq[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY][4] =
+{{0, 2, 3, 1}, {1, 3, 2, 0}};
+
+struct timespec _log_time;
+
+#define DEBUG_INFO(format, args...) StoreLogMsg("[%s:%d][%s][Info] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+#define DEBUG_WARN(format, args...) StoreLogMsg("[%s:%d][%s][Warn] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+#define DEBUG_ERROR(format, args...) StoreLogMsg("[%s:%d][%s][Error] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+
+int StoreLogMsg(const char *fmt, ...)
+{
+	char Buf[4096+256];
+	char buffer[4096];
+	va_list args;
+	struct timeb  SeqEndTime;
+	struct tm *tm;
+
+	va_start(args, fmt);
+	int rc = vsnprintf(buffer, sizeof(buffer), fmt, args);
+	va_end(args);
+
+	memset(Buf,0,sizeof(Buf));
+	ftime(&SeqEndTime);
+	SeqEndTime.time = time(NULL);
+	tm=localtime(&SeqEndTime.time);
+
+	if (ShmSysConfigAndInfo->SysConfig.SwitchDebugFlag == YES)
+	{
+		sprintf(Buf,"%02d:%02d:%02d:%03d - %s",
+			tm->tm_hour,tm->tm_min,tm->tm_sec,SeqEndTime.millitm, buffer);
+		printf("%s \n", Buf);
+	}
+	else
+	{
+		sprintf(Buf,"echo \"%04d-%02d-%02d %02d:%02d:%02d:%03d - %s\" >> /Storage/SystemLog/[%04d.%02d]SystemLog_%s_Log",
+			tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec,SeqEndTime.millitm,
+			buffer,
+			tm->tm_year+1900,tm->tm_mon+1,
+			ShmSysConfigAndInfo->SysConfig.SerialNumber);
+		system(Buf);
+	}
+
+	return rc;
+}
+
+void PRINTF_FUNC(char *string, ...)
+{
+	va_list args;
+	char buffer[4096];
+	va_start(args, string);
+	vsnprintf(buffer, sizeof(buffer), string, args);
+	va_end(args);
+
+	DEBUG_INFO("%s ", buffer);
+}
+//==========================================
+// Init all share memory
+//==========================================
+int InitShareMemory()
+{
+	int result = PASS;
+	int MeterSMId;
+
+	//creat ShmSysConfigAndInfo
+	if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo),  0777)) < 0)
+    {
+		#ifdef SystemLogMessage
+		DEBUG_ERROR("shmget ShmSysConfigAndInfoKey NG %d \n");
+		#endif
+		result = FAIL;
+	}
+    else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+    {
+    	#ifdef SystemLogMessage
+    	DEBUG_ERROR("shmat ShmSysConfigAndInfo NG \n");
+		#endif
+    	result = FAIL;
+   	}
+
+   	//creat ShmStatusCodeData
+   	if ((MeterSMId = shmget(ShmStatusCodeKey, sizeof(struct StatusCodeData),  0777)) < 0)
+    {
+		#ifdef SystemLogMessage
+   		DEBUG_ERROR("shmget ShmStatusCodeKey NG \n");
+		#endif
+   		result = FAIL;
+	}
+    else if ((ShmStatusCodeData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+    {
+    	#ifdef SystemLogMessage
+    	DEBUG_ERROR("shmat ShmStatusCodeData NG \n");
+		#endif
+    	result = FAIL;
+   	}
+
+   	//creat ShmPsuData
+	if ((MeterSMId = shmget(ShmPsuKey, sizeof(struct PsuData),  0777)) < 0)
+	{
+		#ifdef SystemLogMessage
+		DEBUG_ERROR("shmget ShmPsuKey NG \n");
+		#endif
+		result = FAIL;
+	}
+	else if ((ShmPsuData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+	{
+		#ifdef SystemLogMessage
+		DEBUG_ERROR("shmat ShmPsuData NG \n");
+		#endif
+		result = FAIL;
+	}
+
+	if ((MeterSMId = shmget(ShmCommonKey, sizeof(struct DcCommonInformation), IPC_CREAT | 0777)) < 0)
+	{
+		#ifdef SystemLogMessage
+	   	DEBUG_ERROR("shmget ShmCommonKey NG \n");
+	   	#endif
+	   	result = FAIL;
+	}
+	else if ((ShmDcCommonData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+	{
+		#ifdef SystemLogMessage
+	   	DEBUG_ERROR("shmat ShmDcCommonData NG \n");
+	   	#endif
+	   	result = FAIL;
+	}
+
+	if ((MeterSMId = shmget ( ShmSmartBoxKey, sizeof(struct SmartBoxData), IPC_CREAT | 0777 )) < 0)
+	{
+		#ifdef SystemLogMessage
+	   	DEBUG_ERROR("shmat ShmSmartBoxKey NG \n");
+	   	#endif
+		return FAIL;
+	}
+	else if ((ShmSmartBoxData = shmat ( MeterSMId, NULL, 0 )) == (void *) - 1)
+	{
+		#ifdef SystemLogMessage
+	   	DEBUG_ERROR("shmat ShmSmartBoxData NG \n");
+	   	#endif
+		return FAIL;
+	}
+
+    return result;
+}
+
+//==========================================
+// Public Function
+//==========================================
+bool FindChargingInfoData(byte target, struct ChargingInfoData **chargingData)
+{
+	for (byte index = 0; index < CHAdeMO_QUANTITY; index++)
+	{
+		if (ShmSysConfigAndInfo->SysInfo.ChademoChargingData[index].Index == target)
+		{
+			chargingData[target] = &ShmSysConfigAndInfo->SysInfo.ChademoChargingData[index];
+			return true;
+		}
+	}
+
+	for (byte index = 0; index < CCS_QUANTITY; index++)
+	{
+		if (ShmSysConfigAndInfo->SysInfo.CcsChargingData[index].Index == target)
+		{
+			chargingData[target] = &ShmSysConfigAndInfo->SysInfo.CcsChargingData[index];
+			return true;
+		}
+	}
+
+	for (byte index = 0; index < GB_QUANTITY; index++)
+	{
+		if (ShmSysConfigAndInfo->SysInfo.GbChargingData[index].Index == target)
+		{
+			chargingData[target] = &ShmSysConfigAndInfo->SysInfo.GbChargingData[index];
+			return true;
+		}
+	}
+
+	return false;
+}
+
+void Initialization()
+{
+	bool isPass = false;
+	while(!isPass)
+	{
+		isPass = true;
+		for (byte _index = 0; _index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _index++)
+		{
+			if (!FindChargingInfoData(_index, &chargingInfo[0]))
+			{
+				DEBUG_ERROR("SmartBox (main) : FindChargingInfoData false \n");
+				isPass = false;
+				break;
+			}
+		}
+		sleep(1);
+	}
+
+	for (byte _index = 0; _index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _index++)
+	{
+		ShmSmartBoxData->Dynamic4Fetch[_index].ShareGroup = NONE_GROUP_CAN_SELECTED;
+		ShmSmartBoxData->Dynamic4Fetch[_index].TargetRelay = NONE_RELAY_SELECTED;
+		ShmSmartBoxData->Dynamic4Fetch[_index].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_NONE;
+
+		ShmSmartBoxData->Dynamic4Release[_index].ReleaseGroup = NONE_GROUP_CAN_SELECTED;
+		ShmSmartBoxData->Dynamic4Release[_index].TargetRelay = NONE_RELAY_SELECTED;
+		ShmSmartBoxData->Dynamic4Release[_index].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_NONE;
+
+		ShmSmartBoxData->ConnectorUsingGroupCount[_index] = 0;
+	}
+}
+
+void PrintfLog()
+{
+	if (ShmPsuData->Work_Step != _WORK_CHARGING)
+	{
+		PRINTF_FUNC ( "****************************************************************** \n" );
+		PRINTF_FUNC ( "SystemPresentPsuQuantity = %d \n", ShmPsuData->SystemPresentPsuQuantity);
+		PRINTF_FUNC ( "SystemAvailableCurrent = %d (A) \n", ShmPsuData->SystemAvailableCurrent / 10);
+		PRINTF_FUNC ( "SystemAvailablePower = %d (kw) \n", ShmPsuData->SystemAvailablePower / 10);
+		PRINTF_FUNC ( "GroupCount = %d \n", ShmPsuData->GroupCount );
+
+		for (int _count = 0; _count < ARRAY_SIZE(ConnectorUsingSeq[0]); _count ++)
+		{
+			PRINTF_FUNC ( "----------------------------------------------------------------- \n" );
+			PRINTF_FUNC ( "Group Index = %d, UsingTarget for Gun-%d \n", _count, ShmPsuData->PsuGroup[_count].UsingTarget);
+			PRINTF_FUNC ( "GroupPresentPsuQuantity = %d \n", ShmPsuData->PsuGroup[_count].GroupPresentPsuQuantity );
+			PRINTF_FUNC ( "GroupTargetOutputVoltage = %d (V) \n", ShmPsuData->PsuGroup[_count].GroupTargetOutputVoltage / 10);
+			PRINTF_FUNC ( "GroupTargetOutputCurrent = %d (A) \n", ShmPsuData->PsuGroup[_count].GroupTargetOutputCurrent / 10);
+			PRINTF_FUNC ( "GroupAvailableCurrent = %d (A) \n", ShmPsuData->PsuGroup[_count].GroupAvailableCurrent / 10);
+			PRINTF_FUNC ( "GroupAvailablePower = %d (kw) \n", ShmPsuData->PsuGroup[_count].GroupAvailablePower / 10);
+			PRINTF_FUNC ( "GroupMaxVoltage = %d (V) \n", ShmPsuData->PsuGroup[_count].GroupMaxVoltage / 10);
+			PRINTF_FUNC ( "GroupPresentOutputVoltage = %.1f (V) \n", (double)ShmPsuData->PsuGroup[_count].GroupPresentOutputVoltage / 10);
+			PRINTF_FUNC ( "GroupPresentOutputCurrent = %.1f (A) \n", (double)ShmPsuData->PsuGroup[_count].GroupPresentOutputCurrent / 10);
+			PRINTF_FUNC ( "GroupPresentOutputPower = %d \n", ShmPsuData->PsuGroup[_count].GroupPresentOutputPower );
+			PRINTF_FUNC ( "TotalRatingPower = %f \n", (double)ShmPsuData->PsuGroup[_count].TotalRatingPower);
+			PRINTF_FUNC ( "TotalIAvailableCurrent = %f \n", (double)ShmPsuData->PsuGroup[_count].TotalIAvailableCurrent / 10);
+		}
+	}
+	else
+	{
+		for (byte conn = 0; conn < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; conn++)
+		{
+			byte totalUsingGpCount = 0;
+			byte totalQuantity = 0;
+			unsigned short _targetVol = 0 , _targetCur = 0;
+			unsigned short _avaCur = 0 , _avaPow = 0;
+			unsigned short _outputVol = 0 , _outputCur = 0;
+			unsigned short _ratingPow = 0;
+
+			for (byte gp = 0; gp < ShmSmartBoxData->ConnectorUsingGroupCount[conn]; gp++)
+			{
+				if (ShmPsuData->PsuGroup[ConnectorUsingSeq[conn][gp]].UsingTarget == GUN_LEFT)
+				{
+					totalUsingGpCount++;
+					byte tarGp = ConnectorUsingSeq[conn][gp];
+
+					totalQuantity += ShmPsuData->PsuGroup[tarGp].GroupPresentPsuQuantity;
+					_targetVol = ShmPsuData->PsuGroup[tarGp].GroupTargetOutputVoltage / 10;
+					_targetCur += ShmPsuData->PsuGroup[tarGp].GroupTargetOutputCurrent / 10;
+					_avaCur += ShmPsuData->PsuGroup[tarGp].GroupAvailableCurrent / 10;
+					_avaPow += ShmPsuData->PsuGroup[tarGp].GroupAvailablePower / 10;
+					_outputVol = (double)ShmPsuData->PsuGroup[tarGp].GroupPresentOutputVoltage / 10;
+					_outputCur = (double)ShmPsuData->PsuGroup[tarGp].GroupPresentOutputCurrent / 10;
+					_ratingPow += ShmPsuData->PsuGroup[tarGp].TotalRatingPower;
+				}
+			}
+
+			if (totalUsingGpCount > 0)
+			{
+				PRINTF_FUNC ( "----------------------------------------------------------------- \n" );
+				PRINTF_FUNC ( "Group Index = %d, totalUsingGpCount = %d \n", conn, totalUsingGpCount);
+				PRINTF_FUNC ( "totalQuantity = %d \n", totalQuantity);
+				PRINTF_FUNC ( "_targetVol = %d (V), _targetCur = %d (A) \n", _targetVol, _targetCur);
+				PRINTF_FUNC ( "_avaCur = %d (A), _avaPow = %d (kw) \n", _avaCur, _avaPow);
+				PRINTF_FUNC ( "_outputVol = %d (V), _outputCur = %d (A) \n", _outputVol, _outputCur);
+				PRINTF_FUNC ( "_ratingPow = %d \n", _ratingPow);
+			}
+
+			for (byte gp = 0; gp < ShmSmartBoxData->ConnectorUsingGroupCount[conn]; gp++)
+			{
+				if (ShmPsuData->PsuGroup[ConnectorUsingSeq[conn][gp]].UsingTarget == GUN_RIGHT)
+				{
+					totalUsingGpCount++;
+					byte tarGp = ConnectorUsingSeq[conn][gp];
+
+					totalQuantity += ShmPsuData->PsuGroup [tarGp].GroupPresentPsuQuantity;
+					_targetVol = ShmPsuData->PsuGroup [tarGp].GroupTargetOutputVoltage / 10;
+					_targetCur += ShmPsuData->PsuGroup [tarGp].GroupTargetOutputCurrent / 10;
+					_avaCur += ShmPsuData->PsuGroup [tarGp].GroupAvailableCurrent / 10;
+					_avaPow += ShmPsuData->PsuGroup [tarGp].GroupAvailablePower / 10;
+					_outputVol = (double) ShmPsuData->PsuGroup [tarGp].GroupPresentOutputVoltage / 10;
+					_outputCur = (double) ShmPsuData->PsuGroup [tarGp].GroupPresentOutputCurrent / 10;
+					_ratingPow += ShmPsuData->PsuGroup [tarGp].TotalRatingPower;
+				}
+			}
+
+			if (totalUsingGpCount > 0)
+			{
+				PRINTF_FUNC ( "----------------------------------------------------------------- \n" );
+				PRINTF_FUNC ( "Group Index = %d, totalUsingGpCount = %d \n", conn, totalUsingGpCount);
+				PRINTF_FUNC ( "totalQuantity = %d \n", totalQuantity);
+				PRINTF_FUNC ( "_targetVol = %d (V), _targetCur = %d (A) \n", _targetVol, _targetCur);
+				PRINTF_FUNC ( "_avaCur = %d (A), _avaPow = %d (kw) \n", _avaCur, _avaPow);
+				PRINTF_FUNC ( "_outputVol = %d (V), _outputCur = %d (A) \n", _outputVol, _outputCur);
+				PRINTF_FUNC ( "_ratingPow = %d \n", _ratingPow);
+			}
+		}
+	}
+}
+
+void GetSystemMaxVoltage()
+{
+	if (ShmSysConfigAndInfo->SysInfo.BootingStatus == BOOTTING)
+	{
+		int _sysVol = 0;
+
+		for (byte group = 0; group < ShmPsuData->GroupCount; group++)
+		{
+			if (ShmPsuData->PsuGroup[group].GroupMaxVoltage > _sysVol)
+				_sysVol = ShmPsuData->PsuGroup[group].GroupMaxVoltage;
+		}
+
+		for (byte gun_index = 0; gun_index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; gun_index++)
+		{
+			if (chargingInfo[gun_index]->MaximumChargingVoltage != _sysVol)
+			{
+				chargingInfo[gun_index]->MaximumChargingVoltage = _sysVol;
+			}
+		}
+	}
+}
+
+void GetTimespecFunc(struct timespec *time)
+{
+	clock_gettime(CLOCK_MONOTONIC, time);
+}
+
+long int GetTimeoutValue(struct timespec *startTime)
+{
+	struct timespec endTime;
+
+	clock_gettime(CLOCK_MONOTONIC, &endTime);
+	return 1000 * (endTime.tv_sec - startTime->tv_sec) + (endTime.tv_nsec - startTime->tv_nsec) / 1000000;
+}
+
+//==========================================
+// Relay Processing
+//==========================================
+void SmartRelayCheck()
+{
+	/*
+	---------------------------------------
+	G_0 -----------(R1)----------------> Gun - 0
+				| -> R3
+	G_2 --------|
+				| -> R4
+	G_3 --------|
+				| -> R5
+	G_1 -----------(R2)----------------> Gun - 1
+	---------------------------------------
+	R3 ON 時機 : G_2 屬於 Gun-0 輸出、G_0屬於 Gun - 1 輸出
+	R4 ON 時機 : G_3 屬於 Gun-0 輸出、G_2屬於 Gun - 1 輸出
+	R5 ON 時機 : G_3 屬於 Gun-1 輸出、G_1屬於 Gun - 0 輸出
+	-------------------------
+	掃描PSU四個群及兩輸出的ShareGroup內的值各屬於哪個輸出
+	*/
+	byte _buff[3] = {0};
+
+	for (byte group = 0; group < ShmPsuData->GroupCount; group++)
+	{
+		switch(group)
+		{
+			case _PSU_GROUP_INDEX_0:
+			{
+				if (ShmPsuData->PsuGroup[group].UsingTarget == GUN_RIGHT)
+				{
+					// 如果是標準品
+					if(ShmDcCommonData->systemType == _SYSTEM_TYPE_STANDARD)
+					{
+						_buff[_RELAY_SWITCH_NAME_R4] = 0x01;
+						_buff[_RELAY_SWITCH_NAME_R5] = 0x01;
+					}
+					else
+					{
+						// R3 ON
+						_buff[_RELAY_SWITCH_NAME_R3] = 0x01;
+					}
+				}
+			}
+				break;
+			case _PSU_GROUP_INDEX_2:
+			{
+				if (ShmPsuData->PsuGroup[group].UsingTarget == GUN_LEFT)
+				{
+					// R3 ON
+					_buff[_RELAY_SWITCH_NAME_R3] = 0x01;
+				}
+
+				if (ShmPsuData->PsuGroup[group].UsingTarget == GUN_RIGHT)
+				{
+					// R4 ON
+					_buff[_RELAY_SWITCH_NAME_R4] = 0x01;
+				}
+			}
+				break;
+			case _PSU_GROUP_INDEX_3:
+			{
+				if (ShmPsuData->PsuGroup[group].UsingTarget == GUN_LEFT)
+				{
+					// R4 ON
+					_buff[_RELAY_SWITCH_NAME_R4] = 0x01;
+				}
+
+				if (ShmPsuData->PsuGroup[group].UsingTarget == GUN_RIGHT)
+				{
+					// R5 ON
+					_buff[_RELAY_SWITCH_NAME_R5] = 0x01;
+				}
+			}
+				break;
+			case _PSU_GROUP_INDEX_1:
+			{
+				if (ShmPsuData->PsuGroup[group].UsingTarget == GUN_LEFT)
+				{
+					// 如果是標準品
+					if(ShmDcCommonData->systemType == _SYSTEM_TYPE_STANDARD)
+					{
+						_buff[_RELAY_SWITCH_NAME_R4] = 0x01;
+						_buff[_RELAY_SWITCH_NAME_R5] = 0x01;
+					}
+					else
+					{
+						// R5 ON
+						_buff[_RELAY_SWITCH_NAME_R5] = 0x01;
+					}
+				}
+			}
+				break;
+		}
+	}
+
+	for (byte _Conn = 0; _Conn < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _Conn++)
+	{
+		if (ShmSmartBoxData->Dynamic4Fetch[_Conn].FetchLoopStep >= _PSU_DYNAMIC_FETCH_STEP_RELAY)
+		{
+			byte targetGroup = ShmSmartBoxData->Dynamic4Fetch[_Conn].ShareGroup;
+
+			switch(targetGroup)
+			{
+				case _PSU_GROUP_INDEX_0:
+				{
+					if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_RIGHT)
+					{
+						// 如果是標準品
+						if(ShmDcCommonData->systemType == _SYSTEM_TYPE_STANDARD)
+						{
+							_buff[_RELAY_SWITCH_NAME_R4] = 0x01;
+							_buff[_RELAY_SWITCH_NAME_R5] = 0x01;
+							ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4;
+						}
+						else
+						{
+							// R3 ON -- P
+							_buff[_RELAY_SWITCH_NAME_R3] = 0x01;
+							ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R3;
+						}
+					}
+				}
+					break;
+				case _PSU_GROUP_INDEX_2:
+				{
+					if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_LEFT)
+					{
+						// R3 ON -- P
+						_buff[_RELAY_SWITCH_NAME_R3] = 0x01;
+						ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R3;
+					}
+
+					if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_RIGHT)
+					{
+						// R4 ON -- P
+						_buff[_RELAY_SWITCH_NAME_R4] = 0x01;
+						ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4;
+					}
+				}
+					break;
+				case _PSU_GROUP_INDEX_3:
+				{
+					if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_LEFT)
+					{
+						// R4 ON -- P
+						_buff[_RELAY_SWITCH_NAME_R4] = 0x01;
+						ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4;
+					}
+
+					if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_RIGHT)
+					{
+						// R5 ON -- P
+						_buff[_RELAY_SWITCH_NAME_R5] = 0x01;
+						ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R5;
+					}
+				}
+					break;
+				case _PSU_GROUP_INDEX_1:
+				{
+					if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_LEFT)
+					{
+						// 如果是標準品
+						if(ShmDcCommonData->systemType == _SYSTEM_TYPE_STANDARD)
+						{
+							_buff[_RELAY_SWITCH_NAME_R4] = 0x01;
+							_buff[_RELAY_SWITCH_NAME_R5] = 0x01;
+							ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4;
+						}
+						else
+						{
+							// R5 ON -- P
+							_buff[_RELAY_SWITCH_NAME_R5] = 0x01;
+							ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R5;
+						}
+					}
+				}
+					break;
+			}
+		}
+
+		if (ShmSmartBoxData->Dynamic4Release[_Conn].ReleaseLoopStep >= _PSU_DYNAMIC_RELEASE_STEP_RELAYOFF)
+		{
+			byte targetGroup = ShmSmartBoxData->Dynamic4Release[_Conn].ReleaseGroup;
+
+			switch(targetGroup)
+			{
+				case _PSU_GROUP_INDEX_0:
+				{
+					if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_RIGHT)
+					{
+						// R3 OFF
+						_buff[_RELAY_SWITCH_NAME_R3] = 0x00;
+						ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R3;
+
+						// 如果是標準品
+						if(ShmDcCommonData->systemType == _SYSTEM_TYPE_STANDARD)
+						{
+							_buff[_RELAY_SWITCH_NAME_R4] = 0x00;
+							_buff[_RELAY_SWITCH_NAME_R5] = 0x00;
+							ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4;
+						}
+					}
+				}
+					break;
+				case _PSU_GROUP_INDEX_2:
+				{
+					if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_LEFT)
+					{
+						// R3 OFF
+						_buff[_RELAY_SWITCH_NAME_R3] = 0x00;
+						ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R3;
+					}
+
+					if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_RIGHT)
+					{
+						// R5 OFF
+						_buff[_RELAY_SWITCH_NAME_R4] = 0x00;
+						ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4;
+					}
+				}
+					break;
+				case _PSU_GROUP_INDEX_3:
+				{
+					if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_LEFT)
+					{
+						// R4 OFF
+						_buff[_RELAY_SWITCH_NAME_R4] = 0x00;
+						ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4;
+					}
+
+					if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_RIGHT)
+					{
+						// R5 OFF
+						_buff[_RELAY_SWITCH_NAME_R5] = 0x00;
+						ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R5;
+					}
+				}
+					break;
+				case _PSU_GROUP_INDEX_1:
+				{
+					if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_LEFT)
+					{
+						// 如果是標準品
+						if(ShmDcCommonData->systemType == _SYSTEM_TYPE_STANDARD)
+						{
+							_buff[_RELAY_SWITCH_NAME_R4] = 0x00;
+							_buff[_RELAY_SWITCH_NAME_R5] = 0x00;
+							ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4;
+						}
+						else
+						{
+							// R4 OFF
+							_buff[_RELAY_SWITCH_NAME_R5] = 0x00;
+							ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R5;
+						}
+					}
+				}
+					break;
+			}
+		}
+	}
+
+	memcpy(ShmSmartBoxData->ParallelRelayStatus, _buff, sizeof(_buff));
+}
+
+//==========================================
+// Sub Processing
+//==========================================
+void Assign2ConnectorProcessing(byte _targetConn)
+{
+	// 根據現在該槍拿到的群數量, 依順去設定群的使用目標為左 /右槍
+	// 一旦設定該模塊目標為左 /右槍後,AssignedPwr2Connector function 會將該模塊的資訊給對應的左/右槍
+	for (byte aGp = 0; aGp < ShmSmartBoxData->ConnectorUsingGroupCount[_targetConn]; aGp++)
+	{
+		if (ShmPsuData->PsuGroup[ConnectorUsingSeq[_targetConn][aGp]].IsUsing == YES)
+		{
+			ShmPsuData->PsuGroup[ConnectorUsingSeq[_targetConn][aGp]].UsingTarget = _targetConn;
+		}
+	}
+}
+
+// 將_group該群的模塊配給_targetConn槍號
+void AddGroup2Connector(byte _targetConn, byte _group)
+{
+	ShmPsuData->PsuGroup[_group].IsUsing = YES;
+	if ((ShmSysConfigAndInfo->SysInfo.IsAlternatvieConf == YES && _targetConn == GUN_RIGHT) ||
+			(ShmDcCommonData->systemType == _SYSTEM_TYPE_STANDARD && ShmSmartBoxData->ConnectorUsingGroupCount[_targetConn] > 0))
+		ShmSmartBoxData->ConnectorUsingGroupCount[_targetConn] = 4;
+	else
+		ShmSmartBoxData->ConnectorUsingGroupCount[_targetConn]++;
+	// 對應到相對群
+	Assign2ConnectorProcessing(_targetConn);
+}
+
+// 將targetGp該群的模塊從_targetConn槍號移除
+bool ReleaseConnectorProcessing(byte _targetConn, byte targetGp)
+{
+	bool result = false;
+
+	if (ShmPsuData->PsuGroup[targetGp].PwSwitchStatus == _PSU_POWER_STATUS_OFF)
+	{
+		result = true;
+		ShmPsuData->PsuGroup[targetGp].UsingTarget = GUN_CHECK;
+		ShmPsuData->PsuGroup[targetGp].IsUsing = NO;
+		ShmSmartBoxData->ConnectorUsingGroupCount[_targetConn]--;
+	}
+
+	return result;
+}
+
+//==========================================
+// Fetch fork
+//==========================================
+void InitializeDynamicFetch(byte _targetConn)
+{
+	ShmSmartBoxData->Dynamic4Fetch[_targetConn].ShareGroup = NONE_GROUP_CAN_SELECTED;
+	ShmSmartBoxData->Dynamic4Fetch[_targetConn].TargetRelay = NONE_RELAY_SELECTED;
+	ShmSmartBoxData->Dynamic4Fetch[_targetConn].ShareTargetCurrent = 0;
+	ShmSmartBoxData->SmartChk[_targetConn].IsFetchStart = NO;
+}
+
+void FetchLoopProcessing(byte _targetConn)
+{
+	byte targetGroup = ShmSmartBoxData->Dynamic4Fetch[_targetConn].ShareGroup;
+	if (targetGroup == NONE_GROUP_CAN_SELECTED &&
+			ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep >= _PSU_DYNAMIC_FETCH_STEP_TG_VOL)
+	{
+		ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_FINISH;
+	}
+
+	// 用 target vol 比較好還是用當前火線電壓 ? 可以試試看~
+	float EvVoltage = chargingInfo[_targetConn]->EvBatterytargetVoltage * 10;
+
+	switch(ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep)
+	{
+		case _PSU_DYNAMIC_FETCH_STEP_NONE:
+		case _PSU_DYNAMIC_FETCH_STEP_WAIT:{ } break;
+		case _PSU_DYNAMIC_FETCH_STEP_TG_VOL:
+		{
+			// 該群升壓
+			if (ShmPsuData->PsuGroup[targetGroup].GroupPresentOutputVoltage != 0)
+			{
+				PRINTF_FUNC("EV_ReqVoltage = %f, targetGroup = %d, Group_CurVoltage = %d \n",
+						EvVoltage, targetGroup, ShmPsuData->PsuGroup[targetGroup].GroupPresentOutputVoltage);
+			}
+
+			if (EvVoltage <= PSU_MIN_VOL)
+			{
+				PRINTF_FUNC("***** FETCH_STEP_ABORT ***** (Gun - %d) \n", _targetConn);
+				ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_ABORT;
+			}
+			else if (ShmPsuData->PsuGroup[targetGroup].GroupPresentOutputVoltage >= EvVoltage - PSU_TG_VOL_GAP)
+			{
+				PRINTF_FUNC("***** FETCH_STEP_RELAY ***** (Gun - %d) \n", _targetConn);
+				ShmPsuData->PsuGroup[targetGroup].UsingTarget = _targetConn;
+				ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_RELAY;
+			}
+		}
+			break;
+		case _PSU_DYNAMIC_FETCH_STEP_RELAY:
+		{
+			// 搭上對應的 Relay
+			if (ShmSmartBoxData->Dynamic4Fetch[_targetConn].TargetRelay < ARRAY_SIZE(ShmSmartBoxData->ParallelRelayStatus))
+			{
+				if (ShmSmartBoxData->ParallelRelayStatus[ShmSmartBoxData->Dynamic4Fetch[_targetConn].TargetRelay] == YES)
+				{
+					if (ShmSmartBoxData->RcbParallelStatus[ShmSmartBoxData->Dynamic4Fetch[_targetConn].TargetRelay] == YES)
+					{
+						PRINTF_FUNC("***** FETCH_STEP_CUR_SHARE ***** (Gun - %d) \n", _targetConn);
+						ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_CUR_SHARE;
+					}
+				}
+			}
+		}
+			break;
+		case _PSU_DYNAMIC_FETCH_STEP_CUR_SHARE:
+		{
+			// 均流 : 目標電流 = 當前電流 / (原本輸出群個數 + share group 個數)
+			PRINTF_FUNC("GroupPresent = %d (0.1A), ShareTarget = %d (0.1A), CurrentPresent = %.1f \n",
+					ShmPsuData->PsuGroup[targetGroup].GroupPresentOutputCurrent,
+					ShmSmartBoxData->Dynamic4Fetch[_targetConn].ShareTargetCurrent,
+					chargingInfo[_targetConn]->PresentChargingCurrent);
+
+			if ((ShmPsuData->PsuGroup[targetGroup].GroupPresentOutputCurrent >= ShmSmartBoxData->Dynamic4Fetch[_targetConn].ShareTargetCurrent - PSU_TG_CUR_GAP &&
+					ShmPsuData->PsuGroup[targetGroup].GroupPresentOutputCurrent <= ShmSmartBoxData->Dynamic4Fetch[_targetConn].ShareTargetCurrent + PSU_TG_CUR_GAP) ||
+					chargingInfo[_targetConn]->PresentChargingCurrent <= PSU_MIN_CUR)
+			{
+				PRINTF_FUNC("***** FETCH_STEP_WATI_FINISH ***** (Gun - %d) \n", _targetConn);
+				ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_WATI_FINISH;
+			}
+
+		}
+			break;
+		case _PSU_DYNAMIC_FETCH_STEP_WATI_FINISH:
+		{
+			AddGroup2Connector(_targetConn, targetGroup);
+			GetTimespecFunc(&ShmSmartBoxData->SmartChk[_targetConn].FetchLoopTime);
+			PRINTF_FUNC("***** FETCH_STEP_FINISH ***** (Gun - %d) \n", _targetConn);
+			ShmSmartBoxData->Dynamic4Fetch[_targetConn].ShareGroup = NONE_GROUP_CAN_SELECTED;
+			ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_FINISH;
+		}
+			break;
+		case _PSU_DYNAMIC_FETCH_STEP_FINISH:
+		{
+			// 完成
+			int _t = GetTimeoutValue(&ShmSmartBoxData->SmartChk[_targetConn].FetchLoopTime);
+
+			if (_t >= FETCH_FINISH_WAIT_TIME)
+			{
+				InitializeDynamicFetch(_targetConn);
+				PRINTF_FUNC("***** FETCH_STEP_NONE ***** (Gun - %d) \n", _targetConn);
+				ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_NONE;
+			}
+		}
+			break;
+		case _PSU_DYNAMIC_FETCH_STEP_ABORT:
+		{
+			// 中斷
+			if (ShmPsuData->PsuGroup[targetGroup].IsUsing)
+			{
+				ShmPsuData->PsuGroup[targetGroup].IsUsing = NO;
+				ShmPsuData->PsuGroup[targetGroup].UsingTarget = GUN_CHECK;
+			}
+
+			GetTimespecFunc(&ShmSmartBoxData->SmartChk[_targetConn].FetchLoopTime);
+			ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_FINISH;
+		}
+			break;
+	}
+}
+
+byte CheckRemainPwrByConIndex(byte _targetConn)
+{
+	byte result = NONE_GROUP_CAN_SELECTED;
+
+	// 該槍已經使用的群數量
+	byte usingCount = ShmSmartBoxData->ConnectorUsingGroupCount[_targetConn];
+
+	for (byte Gp = usingCount; Gp < ARRAY_SIZE(ConnectorUsingSeq[_targetConn]); Gp++)
+	{
+		// 判斷是否有該槍下一個可用群的狀態
+		if (ShmPsuData->PsuGroup[ConnectorUsingSeq[_targetConn][Gp]].IsUsing == NO &&
+				ShmPsuData->PsuGroup[ConnectorUsingSeq[_targetConn][Gp]].GroupPresentPsuQuantity > 0)
+		{
+			result = ConnectorUsingSeq[_targetConn][Gp];
+			break;
+		}
+	}
+
+	return result;
+}
+
+void Chk2StopFetchStep(byte _targetConn)
+{
+	// 開始流程後,就讓流程走完吧~
+	if (ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep > _PSU_DYNAMIC_FETCH_STEP_NONE &&
+			ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep < _PSU_DYNAMIC_FETCH_STEP_TG_VOL)
+	{
+		PRINTF_FUNC("***** FETCH_STEP_ABORT ***** (Gun - %d) \n", _targetConn);
+		ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_ABORT;
+	}
+}
+
+void FetchFork()
+{
+	pid_t fetchPid;
+
+	fetchPid = fork();
+
+	if(fetchPid > 0)
+	{
+		bool isPass = false;
+		struct ChargingInfoData *_chargingData[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
+
+		while(!isPass)
+		{
+			isPass = true;
+			for (byte _index = 0; _index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _index++)
+			{
+				if (!FindChargingInfoData(_index, &_chargingData[0]))
+				{
+					DEBUG_ERROR("Smartbox (FetchFork) : FindChargingInfoData false \n");
+					isPass = false;
+					break;
+				}
+			}
+			sleep(1);
+		}
+
+		while(1)
+		{
+			for (byte gun_index = 0; gun_index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; gun_index++)
+			{
+				if (chargingInfo[gun_index]->SystemStatus == SYS_MODE_IDLE ||
+						chargingInfo[gun_index]->SystemStatus == SYS_MODE_RESERVATION ||
+						chargingInfo[gun_index]->SystemStatus == SYS_MODE_MAINTAIN ||
+						chargingInfo[gun_index]->SystemStatus == SYS_MODE_FAULT)
+				{
+					ShmSmartBoxData->ConnectorStatus[gun_index].NeedToFetch = NO;
+
+					if (ShmSmartBoxData->ConnectorStatus[gun_index].ConnectorStaus != _CONNECTOR_STATUS_NONE)
+						ShmSmartBoxData->ConnectorStatus[gun_index].ConnectorStaus = _CONNECTOR_STATUS_NONE;
+				}
+				// 對充電邏輯來說,充電槍只提需求
+				else if (chargingInfo[gun_index]->SystemStatus >= SYS_MODE_MODE_REASSIGN_CHECK &&
+						chargingInfo[gun_index]->SystemStatus <= SYS_MODE_REASSIGN)
+				{
+					// 判斷該群是否被使用中
+					if (ShmPsuData->PsuGroup[gun_index].IsUsing)
+					{
+						// 如果使用中 : 等待把這顆模塊切出
+						ShmSmartBoxData->ConnectorStatus[gun_index].ConnectorStaus = _CONNECTOR_STATUS_WAIT;
+					}
+					else
+					{
+						// 直接同意該群後輸出
+						InitializeDynamicFetch(gun_index);
+						ShmSmartBoxData->ConnectorStatus[gun_index].ConnectorStaus = _CONNECTOR_STATUS_USING;
+					}
+				}
+				else if (chargingInfo[gun_index]->SystemStatus == SYS_MODE_PREPARING)
+				{
+					// 這個階段只會拿到屬於該槍的模塊群
+					if (ShmSysConfigAndInfo->SysInfo.IsAlternatvieConf == YES && gun_index == GUN_RIGHT)
+					{
+						// 壁掛 : 強制使用第零群
+					    AddGroup2Connector(gun_index, _PSU_GROUP_INDEX_0);
+					}
+					else
+					{
+						if (!ShmPsuData->PsuGroup[gun_index].IsUsing)
+						{
+							// 第一個 : Gun index
+							// 第二個 : Psu Group index
+							AddGroup2Connector(gun_index, gun_index);
+						}
+					}
+				}
+				else if (chargingInfo[gun_index]->SystemStatus == SYS_MODE_CHARGING)
+				{
+					// 如果當前輸出接近實際可提供的能量 (距離 <= CAP_GAP_FETCH <3KW>)
+					// 不取 EvBatterytargetVoltage 原因是小板會將該值做不同的處理方式
+					float needPower = chargingInfo[gun_index]->PresentChargingVoltage *
+							chargingInfo[gun_index]->EvBatterytargetCurrent / 100;
+					// 判斷是否可以及需要提供多餘群輸出
+					byte chkRemainGp = NONE_GROUP_CAN_SELECTED;
+
+					if (ShmSmartBoxData->Dynamic4Fetch[gun_index].ShareGroup == NONE_GROUP_CAN_SELECTED)
+						chkRemainGp = CheckRemainPwrByConIndex(gun_index);
+					else
+						chkRemainGp = ShmSmartBoxData->Dynamic4Fetch[gun_index].ShareGroup;
+
+					ShmSmartBoxData->ConnectorStatus[gun_index].NeedToFetch =
+							(needPower > 0 && needPower >= chargingInfo[gun_index]->RealRatingPower - CAP_GAP_FETCH) ? true : false;
+
+					if (ShmDcCommonData->systemType != _SYSTEM_TYPE_SIMPLE &&
+							ShmSmartBoxData->Dynamic4Release[gun_index].ReleaseLoopStep == _PSU_DYNAMIC_RELEASE_STEP_NONE &&
+							((ShmSmartBoxData->ConnectorStatus[gun_index].NeedToFetch &&
+							chkRemainGp != NONE_GROUP_CAN_SELECTED &&
+							ShmSmartBoxData->Dynamic4Fetch[gun_index].FetchLoopStep <= _PSU_DYNAMIC_FETCH_STEP_WAIT) ||
+							ShmDcCommonData->smartFetchRun[gun_index])
+							)
+					{
+						if (!ShmSmartBoxData->SmartChk[gun_index].IsFetchStart)
+						{
+							// 判斷是否可以及需要提供多餘群輸出
+							PRINTF_FUNC("Fetch Target = %d, Target Group = %d \n", gun_index, chkRemainGp);
+							// 鎖定目標群,動態分配開始
+							// 該群模塊即被鎖定, 預防另外一群也進入相同邏輯,預防搶同一個群的情形
+							ShmPsuData->PsuGroup[chkRemainGp].IsUsing = YES;
+
+							ShmSmartBoxData->Dynamic4Fetch[gun_index].ShareGroup = chkRemainGp;
+							PRINTF_FUNC("***** FETCH_STEP_WAIT ***** (Gun - %d) \n", gun_index);
+							ShmSmartBoxData->Dynamic4Fetch[gun_index].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_WAIT;
+
+							// 倒數進入動態分配邏輯 - Fetch loop
+							ShmSmartBoxData->SmartChk [gun_index].IsFetchStart = YES;
+							// 條件成立, 倒數 FETCH_SMART_CHK_TIME <5s>
+							GetTimespecFunc(&ShmSmartBoxData->SmartChk[gun_index].FetchLoopTime);
+						}
+						else
+						{
+							if (ShmSmartBoxData->Dynamic4Fetch[gun_index].FetchLoopStep == _PSU_DYNAMIC_FETCH_STEP_WAIT)
+							{
+								int _t = GetTimeoutValue(&ShmSmartBoxData->SmartChk[gun_index].FetchLoopTime);
+
+								if (_t >= FETCH_SMART_CHK_TIME)
+								{
+									PRINTF_FUNC("***** FETCH_STEP_TG_VOL ***** (Gun - %d) \n", gun_index);
+									ShmSmartBoxData->Dynamic4Fetch[gun_index].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_TG_VOL;
+
+									ShmDcCommonData->smartFetchRun[gun_index] = NO;
+								}
+							}
+						}
+					}
+					else
+					{
+						// 動態分配條件中斷
+						Chk2StopFetchStep(gun_index);
+					}
+				}
+				FetchLoopProcessing(gun_index);
+			}
+
+			usleep(200000);
+		}
+	}
+}
+
+//==========================================
+// Release fork
+//==========================================
+void InitializeDynamicRelease(byte _targetConn)
+{
+	ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseGroup = NONE_GROUP_CAN_SELECTED;
+	ShmSmartBoxData->Dynamic4Release[_targetConn].TargetRelay = NONE_RELAY_SELECTED;
+	ShmSmartBoxData->Dynamic4Release[_targetConn].LimitCurCap = 0;
+	ShmSmartBoxData->Dynamic4Release[_targetConn].LimitPwrCap = 0;
+	ShmSmartBoxData->Dynamic4Release[_targetConn].LimitCur = 0;
+	ShmSmartBoxData->Dynamic4Release[_targetConn].LimitPwr = 0;
+	ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep = _PSU_DYNAMIC_FETCH_STEP_FINISH;
+}
+
+byte CheckReleasePwrByConIndex(byte _targetConn)
+{
+	byte result = NONE_GROUP_CAN_SELECTED;
+
+	// 該槍已經使用的群數量
+	byte usingCount = ShmSmartBoxData->ConnectorUsingGroupCount[_targetConn];
+
+	// 不可把最後一個也拿來釋放
+	if (usingCount - 1 > 0)
+		result = ConnectorUsingSeq[_targetConn][usingCount - 1];
+
+	return result;
+}
+
+void ReleaseLoopProcessing(byte _targetConn)
+{
+	byte targetGroup = ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseGroup;
+
+	switch(ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep)
+	{
+		case _PSU_DYNAMIC_RELEASE_STEP_NONE:
+		case _PSU_DYNAMIC_RELEASE_STEP_WAIT: {} break;
+		case _PSU_DYNAMIC_RELEASE_STEP_LIMIT:
+		{
+			// 應該要通知可輸出的能量與電流
+//			PRINTF_FUNC("_targetConn = %d, LimitCurCap = %.1f, LimitPwrCap = %.1f \n",
+//					_targetConn,
+//					ShmSmartBoxData->Dynamic4Release[_targetConn].LimitCurCap,
+//					ShmSmartBoxData->Dynamic4Release[_targetConn].LimitPwrCap);
+
+			// 通知可輸出的能量與電流
+//			PRINTF_FUNC("_targetConn = %d, LimitCur = %.1f, LimitPwr = %.1f \n",
+//					_targetConn,
+//					ShmSmartBoxData->Dynamic4Release[_targetConn].LimitCur,
+//					ShmSmartBoxData->Dynamic4Release[_targetConn].LimitPwr);
+
+			// 需求能量與電流
+//			PRINTF_FUNC("_targetConn = %d, Req Power = %.1f (kw), Req Vol. = %.1f, Req Cur. = %.1f, Present Cur = %.1f \n",
+//					_targetConn,
+//					(chargingInfo[_targetConn]->EvBatterytargetVoltage * chargingInfo[_targetConn]->EvBatterytargetCurrent) / 100,
+//					chargingInfo[_targetConn]->EvBatterytargetVoltage,
+//					chargingInfo[_targetConn]->EvBatterytargetCurrent,
+//					chargingInfo[_targetConn]->PresentChargingCurrent);
+
+			// if the current and power limits are below their capacity
+			if ((ShmSmartBoxData->Dynamic4Release[_targetConn].LimitCur <= ShmSmartBoxData->Dynamic4Release[_targetConn].LimitCurCap &&
+					ShmSmartBoxData->Dynamic4Release[_targetConn].LimitPwr <= ShmSmartBoxData->Dynamic4Release[_targetConn].LimitPwrCap) ||
+					chargingInfo[_targetConn]->PresentChargingCurrent * 10 <= PSU_LIMIT_CUR)
+			{
+				PRINTF_FUNC("***** RELEASE_STEP_PWROFF ***** (Gun - %d) \n", _targetConn);
+				ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_PWROFF;
+			}
+		}
+			break;
+		case _PSU_DYNAMIC_RELEASE_STEP_PWROFF:
+		{
+//			PRINTF_FUNC("targetGroup = %d, PresentChargingCurrent = %.1f, LimitCur = %.1f \n",
+//				_targetConn,
+//				chargingInfo[_targetConn]->PresentChargingCurrent,
+//				ShmSmartBoxData->Dynamic4Release[_targetConn].LimitCur / 10);
+
+			// if the output current is below their capacity for 5s
+			int _t = GetTimeoutValue(&ShmSmartBoxData->SmartChk[_targetConn].ReleaseLoopTime);
+
+			if (chargingInfo[_targetConn]->PresentChargingCurrent <=
+					ShmSmartBoxData->Dynamic4Release[_targetConn].LimitCur &&
+					_t >= WAIT_FOR_LIMIT_STABLE)
+			{
+				PRINTF_FUNC("***** RELEASE_STEP_RELAYOFF ***** (Gun - %d) \n", _targetConn);
+				ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_RELAYOFF;
+			}
+		}
+			break;
+		case _PSU_DYNAMIC_RELEASE_STEP_RELAYOFF:
+		{
+			// 釋放對應的 Relay
+			PRINTF_FUNC("TargetRelay (%d), targetGroup = %d, ParallelRelayStatus = (%d), RcbParallelStatus = (%d) \n",
+					ShmSmartBoxData->Dynamic4Release[_targetConn].TargetRelay, targetGroup,
+					ShmSmartBoxData->ParallelRelayStatus[ShmSmartBoxData->Dynamic4Release[_targetConn].TargetRelay],
+					ShmSmartBoxData->RcbParallelStatus[ShmSmartBoxData->Dynamic4Release[_targetConn].TargetRelay]);
+
+			if (ShmSmartBoxData->Dynamic4Release[_targetConn].TargetRelay < ARRAY_SIZE(ShmSmartBoxData->ParallelRelayStatus))
+			{
+				if (ShmSmartBoxData->ParallelRelayStatus[ShmSmartBoxData->Dynamic4Release[_targetConn].TargetRelay] == NO)
+				{
+					if (ShmSmartBoxData->RcbParallelStatus[ShmSmartBoxData->Dynamic4Release[_targetConn].TargetRelay] == NO)
+					{
+						PRINTF_FUNC("***** RELEASE_STEP_WATI_FINISH ***** (Gun - %d) \n", _targetConn);
+						ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_WAIT_FINISH;
+					}
+				}
+			}
+		}
+			break;
+		case _PSU_DYNAMIC_RELEASE_STEP_WAIT_FINISH:
+		{
+			if(ReleaseConnectorProcessing(_targetConn, targetGroup))
+			{
+				GetTimespecFunc ( & ShmSmartBoxData->SmartChk [_targetConn].ReleaseLoopTime );
+				PRINTF_FUNC("***** RELEASE_STEP_FINISH ***** (Gun - %d) \n", _targetConn);
+				InitializeDynamicRelease(_targetConn);
+				ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_FINISH;
+			}
+		}
+			break;
+		case _PSU_DYNAMIC_RELEASE_STEP_FINISH:
+		{
+			// 完成
+			int _t = GetTimeoutValue(&ShmSmartBoxData->SmartChk[_targetConn].ReleaseLoopTime);
+
+			if (_t >= RELEASE_FINISH_WAIT_TIME)
+			{
+				PRINTF_FUNC("***** RELEASE_STEP_NONE ***** (Gun - %d) \n", _targetConn);
+				ShmSmartBoxData->SmartChk[_targetConn].IsReleaseStart = NO;
+				ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_NONE;
+			}
+		}
+			break;
+		case _PSU_DYNAMIC_RELEASE_STEP_ABORT:
+		{
+			GetTimespecFunc(& ShmSmartBoxData->SmartChk [_targetConn].ReleaseLoopTime);
+			PRINTF_FUNC("***** RELEASE_STEP_FINISH ***** (Gun - %d) \n", _targetConn);
+			InitializeDynamicRelease(_targetConn);
+			ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_FINISH;
+		}
+			break;
+	}
+}
+
+void Chk2StopReleaseStep(byte _targetConn)
+{
+	// 開始流程後,就讓流程走完吧~
+	if (ShmSmartBoxData->Dynamic4Release [_targetConn].ReleaseGroup > _PSU_DYNAMIC_RELEASE_STEP_NONE &&
+			ShmSmartBoxData->Dynamic4Release [_targetConn].ReleaseGroup < _PSU_DYNAMIC_RELEASE_STEP_LIMIT)
+	{
+		PRINTF_FUNC ( "***** RELEASE_STEP_ABORT ***** (Gun - %d) \n", _targetConn );
+		//ShmSmartBoxData->Dynamic4Release [_targetConn].ReleaseGroup = _PSU_DYNAMIC_RELEASE_STEP_ABORT;
+	}
+	else
+		ShmSmartBoxData->SmartChk[_targetConn].IsReleaseStart = NO;
+}
+
+void ReleaseFork()
+{
+	pid_t releasePid;
+
+	releasePid = fork();
+
+	if(releasePid > 0)
+	{
+		bool isPass = false;
+		struct ChargingInfoData *_chargingData[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
+
+		while(!isPass)
+		{
+			isPass = true;
+			for (byte _index = 0; _index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _index++)
+			{
+				if (!FindChargingInfoData(_index, &_chargingData[0]))
+				{
+					DEBUG_ERROR("Smartbox (ReleaseFork) : FindChargingInfoData false \n");
+					isPass = false;
+					break;
+				}
+			}
+			sleep(1);
+		}
+
+		while(1)
+		{
+			for (byte gun_index = 0; gun_index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; gun_index++)
+			{
+				if (chargingInfo[gun_index]->SystemStatus == SYS_MODE_CHARGING)
+				{
+					// 釋出多餘群 : 要判斷所要釋出群所能提供的最大能量 RealRatingPower
+					// 先找到是否有下一個要釋出的群
+					byte releaseGp = CheckReleasePwrByConIndex(gun_index);
+					if (releaseGp != NONE_GROUP_CAN_SELECTED)
+					{
+						unsigned short releasePwr = ShmPsuData->PsuGroup[releaseGp].TotalRatingPower * 10;
+						float needPower = chargingInfo[gun_index]->PresentChargingVoltage *
+									chargingInfo[gun_index]->EvBatterytargetCurrent / 100;
+
+						if (chargingInfo[gun_index]->Type != _Type_Test &&
+								ShmSmartBoxData->Dynamic4Fetch[gun_index].FetchLoopStep == _PSU_DYNAMIC_FETCH_STEP_NONE &&
+								(ShmSmartBoxData->AnotherConnectorStatus[gun_index].ConnectorStaus == _CONNECTOR_STATUS_WAIT ||
+								(ShmSmartBoxData->AnotherConnectorStatus[gun_index].NeedToFetch &&
+									SMART_MODE && chargingInfo[gun_index]->_TakePsuGpCount > ShmDcCommonData->halfGroupCount) ||
+								(chargingInfo[gun_index]->RealRatingPower > 0 && releasePwr > 0 &&
+									needPower < chargingInfo[gun_index]->RealRatingPower - releasePwr - CAP_GAP_RELEASE) ||
+									ShmDcCommonData->smartReleaseRun[gun_index])
+									)
+						{
+							//PRINTF_FUNC("RealRatingPower = %d \n", chargingInfo[gun_index]->RealRatingPower);
+							//PRINTF_FUNC("releasePwr = %d, needPower = %f \n", releasePwr, needPower);
+
+							if (ShmSmartBoxData->Dynamic4Release[gun_index].ReleaseLoopStep == _PSU_DYNAMIC_RELEASE_STEP_NONE)
+							{
+								if (!ShmSmartBoxData->SmartChk[gun_index].IsReleaseStart)
+								{
+									PRINTF_FUNC("***** Entry release chk (Gun_%d).. ***** \n", gun_index);
+									ShmSmartBoxData->SmartChk[gun_index].IsReleaseStart = YES;
+									ShmSmartBoxData->Dynamic4Release[gun_index].CheckOutPwrIsStable = chargingInfo[gun_index]->PresentChargingPower;
+									GetTimespecFunc(&ShmSmartBoxData->SmartChk[gun_index].ReleaseLoopTime);
+								}
+								else
+								{
+									int _delayt = GetTimeoutValue(&ShmSmartBoxData->SmartChk[gun_index].ReleaseLoopTime);
+
+									// 每五秒看一次輸出能量是否穩定, 穩定則進入分配
+									if (_delayt >= RELEASE_STABLE_CHK_TIME)
+									{
+										if (chargingInfo[gun_index]->PresentChargingPower >
+												ShmSmartBoxData->Dynamic4Release[gun_index].CheckOutPwrIsStable + STABLE_CAP_GAP)
+										{
+											ShmSmartBoxData->Dynamic4Release[gun_index].CheckOutPwrIsStable = chargingInfo[gun_index]->PresentChargingPower;
+											GetTimespecFunc(&ShmSmartBoxData->SmartChk[gun_index].ReleaseLoopTime);
+										}
+										else
+										{
+											// 進入穩定
+											PRINTF_FUNC("***** RELEASE_STEP_WAIT ***** \n");
+											ShmSmartBoxData->Dynamic4Release[gun_index].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_WAIT;
+											GetTimespecFunc(&ShmSmartBoxData->SmartChk[gun_index].ReleaseLoopTime);
+										}
+									}
+								}
+							}
+							else if (ShmSmartBoxData->Dynamic4Release[gun_index].ReleaseLoopStep == _PSU_DYNAMIC_RELEASE_STEP_WAIT)
+							{
+								int _delayt = GetTimeoutValue(&ShmSmartBoxData->SmartChk[gun_index].ReleaseLoopTime);
+
+								// 每五秒看一次輸出能量是否穩定, 穩定則進入分配
+								if (_delayt >= RELEASE_SMART_CHK_TIME)
+								{
+									PRINTF_FUNC("***** RELEASE_STEP_LIMIT ***** \n");
+									ShmSmartBoxData->Dynamic4Release[gun_index].ReleaseGroup = releaseGp;
+									ShmSmartBoxData->Dynamic4Release[gun_index].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_LIMIT;
+									ShmDcCommonData->smartReleaseRun[gun_index] = NO;
+								}
+							}
+						}
+						else
+						{
+							// 動態分配條件中斷
+							Chk2StopReleaseStep(gun_index);
+						}
+					}
+				}
+				else if (chargingInfo[gun_index]->SystemStatus == SYS_MODE_IDLE ||
+						chargingInfo[gun_index]->SystemStatus == SYS_MODE_FAULT ||
+						chargingInfo[gun_index]->SystemStatus == SYS_MODE_RESERVATION ||
+						(chargingInfo[gun_index]->SystemStatus >= SYS_MODE_TERMINATING &&
+							chargingInfo[gun_index]->SystemStatus <= SYS_MODE_ALARM))
+				{
+					if (ShmSmartBoxData->ConnectorStatus[gun_index].ConnectorStaus == _CONNECTOR_STATUS_NONE)
+					{
+						byte totoalUsingGpCount = ShmSmartBoxData->ConnectorUsingGroupCount[gun_index];
+
+						for (byte _gp = 0; _gp < totoalUsingGpCount; _gp++)
+						{
+							PRINTF_FUNC("ConnectorUsingSeq[%d][%d] = %d \n", gun_index, _gp, ConnectorUsingSeq[gun_index][_gp]);
+							ReleaseConnectorProcessing(gun_index, ConnectorUsingSeq[gun_index][_gp]);
+						}
+
+						if (ShmSmartBoxData->Dynamic4Fetch[gun_index].ShareGroup != NONE_GROUP_CAN_SELECTED &&
+								ShmSmartBoxData->Dynamic4Fetch[gun_index].FetchLoopStep < _PSU_DYNAMIC_FETCH_STEP_FINISH)
+							ShmSmartBoxData->Dynamic4Fetch[gun_index].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_ABORT;
+
+						ShmSmartBoxData->Dynamic4Release[gun_index].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_NONE;
+					}
+
+					if (ShmSmartBoxData->ConnectorStatus[gun_index].NeedToFetch)
+						ShmSmartBoxData->ConnectorStatus[gun_index].NeedToFetch = NO;
+				}
+
+				ReleaseLoopProcessing(gun_index);
+			}
+
+			usleep(200000);
+		}
+	}
+}
+
+//==========================================
+// Main Function
+//==========================================
+void TakeAnotherGunStatus(byte target)
+{
+	byte another = 0;
+
+	if (target == 0)
+		another = 1;
+
+	ShmSmartBoxData->AnotherConnectorStatus[another].ConnectorStaus = ShmSmartBoxData->ConnectorStatus[target].ConnectorStaus;
+	ShmSmartBoxData->AnotherConnectorStatus[another].NeedToFetch = ShmSmartBoxData->ConnectorStatus[target].NeedToFetch;
+}
+
+void AssignedPwr2Connector()
+{
+	for(byte _gun = 0; _gun < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _gun++)
+	{
+		byte usingGroupCount = 0;
+		float availablePwr = 0, availableCur = 0, iAvailableCur = 0, totalPsuCount = 0, kwAvailablePwr = 0;
+		float outputVol = 0, outputCur = 0;
+		float limitCur = 0, limitPwr = 0;
+
+		for (byte group = 0; group < ShmPsuData->GroupCount; group++)
+		{
+			if (ShmPsuData->PsuGroup[group].UsingTarget == _gun)
+			{
+				usingGroupCount++;
+				if (group != ShmSmartBoxData->Dynamic4Fetch[_gun].ShareGroup &&
+						(group != ShmSmartBoxData->Dynamic4Release[_gun].ReleaseGroup ||
+							ShmSmartBoxData->Dynamic4Release[_gun].ReleaseLoopStep <= _PSU_DYNAMIC_RELEASE_STEP_WAIT_FINISH))
+				{
+					availablePwr += ShmPsuData->PsuGroup[group].GroupAvailablePower;
+					availableCur += ShmPsuData->PsuGroup[group].GroupAvailableCurrent;
+					iAvailableCur += ShmPsuData->PsuGroup[group].TotalIAvailableCurrent;
+					totalPsuCount += ShmPsuData->PsuGroup[group].GroupPresentPsuQuantity;
+					if (ShmPsuData->PsuGroup[group].TotalRatingPower <= 15 ||
+							ShmPsuData->PsuGroup[group].TotalRatingPower > 30)
+						kwAvailablePwr += (ShmPsuData->PsuGroup[group].GroupAvailablePower) / 10;
+					else
+						kwAvailablePwr += ShmPsuData->PsuGroup[group].TotalRatingPower;
+				}
+
+				// Release Loop 用 : 實際上~ 電流會飄 ....
+				// 這段, 只取還要留住的模塊輸出電流與能量就好
+				if (group != ShmSmartBoxData->Dynamic4Release[_gun].ReleaseGroup &&
+						ShmSmartBoxData->Dynamic4Release[_gun].ReleaseLoopStep == _PSU_DYNAMIC_RELEASE_STEP_LIMIT)
+				{
+					limitCur += ShmPsuData->PsuGroup[group].GroupTargetOutputCurrent;
+					limitPwr += ShmPsuData->PsuGroup[group].TotalRatingPower;
+				}
+
+				outputCur += ShmPsuData->PsuGroup[group].GroupPresentOutputCurrent;
+
+				if (outputVol < ShmPsuData->PsuGroup[group].GroupPresentOutputVoltage ||
+						outputVol == 0)
+					outputVol = ShmPsuData->PsuGroup[group].GroupPresentOutputVoltage;
+			}
+		}
+
+		chargingInfo[_gun]->AvailableChargingPower = availablePwr;
+		chargingInfo[_gun]->AvailableChargingCurrent = availableCur;
+		chargingInfo[_gun]->DeratingChargingCurrent = iAvailableCur;
+		chargingInfo[_gun]->_TotalPsuCount = totalPsuCount;
+		chargingInfo[_gun]->PresentChargingVoltage = outputVol / 10;
+		chargingInfo[_gun]->PresentChargingCurrent = outputCur / 10;
+		chargingInfo[_gun]->RealRatingPower = kwAvailablePwr * 10;
+		chargingInfo[_gun]->_TakePsuGpCount = usingGroupCount;
+
+		// 雙槍需要記得另外一把槍的狀態
+		if (ShmSysConfigAndInfo->SysConfig.TotalConnectorCount > 1)
+			TakeAnotherGunStatus(_gun);
+
+		// 取 Release group 的最大電流
+		if (ShmSmartBoxData->Dynamic4Release[_gun].ReleaseLoopStep == _PSU_DYNAMIC_RELEASE_STEP_LIMIT)
+		{
+			ShmSmartBoxData->Dynamic4Release[_gun].LimitCurCap = limitCur;
+			ShmSmartBoxData->Dynamic4Release[_gun].LimitPwrCap = limitPwr * 10;
+		}
+	}
+}
+
+void CollectGroupInformation(byte group)
+{
+	int _groupPower = 0 , _groupCurrent = 0 , _groupMaxVoltage = 0;
+	int Iavail = 0, Pavail = 0;
+	unsigned short _outputVolBuf = 0, _outputCurBuf = 0;
+
+	for (byte index = 0; index < ShmPsuData->PsuGroup[group].GroupPresentPsuQuantity; index ++)
+	{
+		// Cap
+		_groupCurrent += ShmPsuData->PsuGroup[group].PsuModule[index].AvailableCurrent;
+		_groupPower += ShmPsuData->PsuGroup[group].PsuModule[index].AvailablePower;
+
+		if (ShmPsuData->PsuGroup[group].PsuModule[index].PresentMaxOutputVoltage > _groupMaxVoltage)
+			_groupMaxVoltage = ShmPsuData->PsuGroup[group].PsuModule[index].PresentMaxOutputVoltage;
+
+		// Iavailable
+		Iavail += ShmPsuData->PsuGroup[group].PsuModule[index].IAvailableCurrent;
+		Pavail += ShmPsuData->PsuGroup[group].PsuModule[index].KwAvailablePower;
+
+		// output
+		_outputCurBuf += ShmPsuData->PsuGroup[group].PsuModule[index].PresentOutputCurrent;
+
+		if (_outputVolBuf == 0 ||
+					(ShmPsuData->PsuGroup[group].PsuModule[index].PresentOutputVoltage > PSU_MIN_VOL &&
+					_outputVolBuf < ShmPsuData->PsuGroup[group].PsuModule[index].PresentOutputVoltage))
+		{
+			_outputVolBuf = ShmPsuData->PsuGroup[group].PsuModule[index].PresentOutputVoltage;
+		}
+	}
+
+	ShmPsuData->PsuGroup[group].GroupMaxVoltage = _groupMaxVoltage;
+	ShmPsuData->PsuGroup[group].GroupAvailableCurrent = _groupCurrent;
+	ShmPsuData->PsuGroup[group].GroupAvailablePower = _groupPower;
+
+	ShmPsuData->PsuGroup[group].TotalIAvailableCurrent = Iavail;
+	ShmPsuData->PsuGroup[group].TotalRatingPower = Pavail;
+
+	ShmPsuData->PsuGroup[group].GroupPresentOutputVoltage = _outputVolBuf;
+	ShmPsuData->PsuGroup[group].GroupPresentOutputCurrent = _outputCurBuf;
+}
+
+void CollectPsuInformation()
+{
+	int _sysPwr = 0, _sysCur = 0, _sysVol = 0;
+
+	for (byte group = 0; group < ShmPsuData->GroupCount; group++)
+	{
+		// 取群資訊
+		CollectGroupInformation(group);
+
+		// 整理系統資訊
+		_sysPwr += ShmPsuData->PsuGroup[group].GroupAvailablePower;
+		_sysCur += ShmPsuData->PsuGroup[group].GroupAvailableCurrent;
+
+		if (ShmPsuData->PsuGroup[group].GroupMaxVoltage > _sysVol)
+			_sysVol = ShmPsuData->PsuGroup[group].GroupMaxVoltage;
+	}
+
+	// 系統,電壓,電流,能量
+	ShmPsuData->SystemAvailableCurrent = _sysCur;
+	ShmPsuData->SystemAvailablePower = _sysPwr;
+	GetSystemMaxVoltage();
+}
+
+//==========================================
+// Main Loop
+//==========================================
+int main(void)
+{
+	if(InitShareMemory() == FAIL)
+	{
+		#ifdef SystemLogMessage
+		DEBUG_ERROR("InitShareMemory NG\n");
+		#endif
+		if(ShmStatusCodeData != NULL)
+		{
+			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FailToCreateShareMemory = 1;
+		}
+		sleep(5);
+		return 0;
+	}
+
+	Initialization();
+
+	// 對充電槍操作 : 將模塊切出來與補上剩餘的模塊功率
+	FetchFork();
+	ReleaseFork();
+
+	GetTimespecFunc(&_log_time);
+	while(1)
+	{
+		if (ShmPsuData->Work_Step >= GET_SYS_CAP)
+		{
+			// 收集來自 PSU 的資訊
+			CollectPsuInformation();
+			// 將群資訊分配到對應的使用中充電槍
+			AssignedPwr2Connector();
+
+			int time = GetTimeoutValue(&_log_time);
+
+			if (time < 0)
+				GetTimespecFunc(&_log_time);
+
+			// 低 Priority 的指令
+			if (time > 5000)
+			{
+				//PrintfLog();
+				GetTimespecFunc(&_log_time);
+			}
+		}
+
+		if (ShmDcCommonData->systemType != _SYSTEM_TYPE_SIMPLE &&
+				ShmPsuData->Work_Step == _WORK_CHARGING)
+		{
+			// 橋接控制
+			SmartRelayCheck();
+		}
+		usleep(50000);
+	}
+
+	return -1;
+}
+

+ 75 - 0
EVSE/Projects/DS60-120/Apps/Module_SmartBox.h

@@ -0,0 +1,75 @@
+/*
+ * Module_SmartBox.h
+ *
+ *  Created on: 2022年5月3日
+ *      Author: 7564
+ */
+
+#ifndef MODULE_SMARTBOX_H_
+#define MODULE_SMARTBOX_H_
+
+#include 	<sys/time.h>
+#include 	<sys/timeb.h>
+#include    <sys/types.h>
+#include    <sys/stat.h>
+#include 	<sys/types.h>
+#include 	<sys/ioctl.h>
+#include 	<sys/socket.h>
+#include 	<sys/ipc.h>
+#include 	<sys/shm.h>
+#include 	<sys/mman.h>
+#include 	<linux/wireless.h>
+#include 	<linux/can.h>
+#include 	<linux/can/raw.h>
+#include 	<arpa/inet.h>
+#include 	<netinet/in.h>
+
+#include 	<unistd.h>
+#include 	<stdarg.h>
+#include   <stdio.h>      /*標準輸入輸出定義*/
+#include   <stdlib.h>     /*標準函數庫定義*/
+#include   <unistd.h>     /*Unix 標準函數定義*/
+#include   <fcntl.h>      /*檔控制定義*/
+#include   <termios.h>    /*PPSIX 終端控制定義*/
+#include   <errno.h>      /*錯誤號定義*/
+#include 	<string.h>
+#include	<time.h>
+#include	<ctype.h>
+#include 	<ifaddrs.h>
+#include	<math.h>
+#include	"../../define.h"
+#include 	<stdbool.h>
+
+#define ARRAY_SIZE(A)			(sizeof(A) / sizeof(A[0]))
+#define PASS					1
+#define FAIL					-1
+#define YES						1
+#define NO						0
+#define NONE_GROUP_CAN_SELECTED	255
+#define NONE_RELAY_SELECTED		255
+#define PSU_MIN_VOL				500	// 0.1V
+#define PSU_MIN_CUR				20	// 0.1A
+#define CAP_GAP_FETCH			30	// 0.1kw
+#define CAP_GAP_RELEASE			50	// 0.1kw
+#define STABLE_CAP_GAP			10	// 0.1kw
+#define SMART_MODE				1 	// 0 : FCFS, 1 : Average
+
+// Fetch Loop
+#define PSU_TG_VOL_GAP			100 // 0.1V
+#define PSU_TG_CUR_GAP			50 	// 0.1A
+// Fetch Loop End
+
+// Release Loop
+#define PSU_LIMIT_CUR			50 	// 0.1A
+// Release Loop End
+
+
+#define FETCH_SMART_CHK_TIME		5000	// 1ms
+#define FETCH_FINISH_WAIT_TIME		1000	// 1ms
+
+#define RELEASE_STABLE_CHK_TIME		5000	// 1ms
+#define RELEASE_SMART_CHK_TIME		2000	// 1ms
+#define WAIT_FOR_LIMIT_STABLE		2000	// 1ms
+#define RELEASE_FINISH_WAIT_TIME	1000	// 1ms
+
+#endif /* MODULE_SMARTBOX_H_ */

+ 1 - 1
EVSE/Projects/DS60-120/Apps/OutputTask.c

@@ -319,7 +319,7 @@ int main(void)
 //												0x01,
 //												0x01);
 					}
-					PresentOutputVol(SYSTEM_CMD, VOLTAGE * 10, CURRENT * 10);
+					PresentOutputVol(SYSTEM_CMD, VOLTAGE * 10, CURRENT * 10, 1);
 				}
 					break;
 				case CHARGING_MODE_TERMINATING:

二進制
EVSE/Projects/DS60-120/Apps/ReadCmdline


+ 344 - 39
EVSE/Projects/DS60-120/Apps/ReadCmdline.c

@@ -63,6 +63,9 @@ byte _curAutoRunCount = 0;
 byte _usingAutoRun = 0;
 struct timeval _autoTime;
 
+byte ConnectorUsingSeq[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY][4] =
+{{0, 2, 3, 1}, {1, 3, 2, 0}};
+
 struct timeb 					startChargingTime;
 struct timeb 					endChargingTime;
 int 							_presentChargingTimeBuf;
@@ -81,6 +84,7 @@ struct LedModuleData			*ShmLedModuleData;
 struct PsuData 					*ShmPsuData;
 struct DcCommonInformation		*ShmDcCommonData;
 struct OCPP16Data				*ShmOCPP16Data;
+struct SmartBoxData				*ShmSmartBoxData;
 
 struct ChargingInfoData 		*_chargingData[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
 struct ChargingInfoData 		*ac_chargingInfo[AC_QUANTITY];
@@ -245,6 +249,15 @@ int InitShareMemory()
    		result = FAIL;
    	}
 
+   	if ((MeterSMId = shmget ( ShmSmartBoxKey, sizeof(struct SmartBoxData), IPC_CREAT | 0777 )) < 0)
+   	{
+   		return FAIL;
+   	}
+   	else if ((ShmSmartBoxData = shmat ( MeterSMId, NULL, 0 )) == (void *) - 1)
+   	{
+   		return FAIL;
+   	}
+
    	if ((MeterSMId = shmget(ShmCommonKey, sizeof(struct DcCommonInformation), IPC_CREAT | 0777)) < 0)
    	{
    		result = FAIL;
@@ -294,8 +307,8 @@ void PrintChargingMode(byte mode)
 {
 	switch(mode)
 	{
-		case _MAIN_CHARGING_MODE_MAX: printf("Charging mode = Max \n"); break;
-		case _MAIN_CHARGING_MODE_AVER: printf("Charging mode = Balance \n"); break;
+		case _MAIN_CHARGING_MODE_NORMAL: printf("Charging mode = Max \n"); break;
+		case _MAIN_CHARGING_MODE_BOTH: printf("Charging mode = Balance \n"); break;
 	}
 }
 
@@ -836,6 +849,196 @@ void GetAcInputVol()
 			ShmSysConfigAndInfo->SysInfo.InputVoltageT);
 }
 
+void GetSmartInformation(char *v1, char *v2, char *v3)
+{
+	if(strcmp(v1, "fe") == 0)
+	{
+		int tag = atoi(v2);
+
+		for (int i = 0; i < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; i++)
+		{
+			if (!FindChargingInfoData(i, &_chargingData[0]))
+			{
+				printf ("FindChargingInfoData error\n");
+				continue;
+			}
+		}
+
+		float needPower = _chargingData[tag]->EvBatterytargetVoltage * _chargingData[tag]->EvBatterytargetCurrent / 100;
+		printf("needPower = %.1f (kw), RealRatingPower = %d \n", needPower / 10, _chargingData[tag]->RealRatingPower / 10);
+		printf("FetchLoopStep = %d \n", ShmSmartBoxData->Dynamic4Fetch[tag].FetchLoopStep);
+		printf("ShareGroup = %d \n", ShmSmartBoxData->Dynamic4Fetch[tag].ShareGroup);
+	}
+	else if (strcmp(v1, "re") == 0)
+	{
+		int tag = atoi(v2);
+
+		for (int i = 0; i < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; i ++)
+		{
+			if ( ! FindChargingInfoData ( i, & _chargingData [0] ))
+			{
+				printf ( "FindChargingInfoData error\n" );
+				continue;
+			}
+		}
+
+		printf("ReleaseGroup = %d \n", ShmSmartBoxData->Dynamic4Release[tag].ReleaseGroup);
+		printf("ReleaseLoopStep = %d \n", ShmSmartBoxData->Dynamic4Release[tag].ReleaseLoopStep);
+		printf("TargetRelay = %d \n", ShmSmartBoxData->Dynamic4Release[tag].TargetRelay);
+	}
+	else if (strcmp(v1, "relay") == 0)
+	{
+		printf("ParallelRelayStatus = [%d] [%d] [%d] \n",
+				ShmSmartBoxData->ParallelRelayStatus[0],
+				ShmSmartBoxData->ParallelRelayStatus[1],
+				ShmSmartBoxData->ParallelRelayStatus[2]);
+
+		printf("RcbParallelStatus = [%d] [%d] [%d] \n",
+				ShmSmartBoxData->RcbParallelStatus[0],
+				ShmSmartBoxData->RcbParallelStatus[1],
+				ShmSmartBoxData->RcbParallelStatus[2]);
+	}
+	else if (strcmp(v1, "using") == 0)
+	{
+		for (byte gp = 0; gp < ShmPsuData->GroupCount; gp++)
+		{
+			if (ShmPsuData->PsuGroup[gp].UsingTarget == GUN_LEFT)
+				printf ( "Group_%d IsUsing => Connector - 0 (Vol : %d (0.1V), Cur : %d (0.1A)) \n",
+						gp,
+						ShmPsuData->PsuGroup[gp].GroupPresentOutputVoltage,
+						ShmPsuData->PsuGroup[gp].GroupPresentOutputCurrent);
+			else if (ShmPsuData->PsuGroup[gp].UsingTarget == GUN_RIGHT)
+				printf ( "Group_%d IsUsing => Connector - 1 (Vol : %d (0.1V), Cur : %d (0.1A)) \n",
+						gp,
+						ShmPsuData->PsuGroup[gp].GroupPresentOutputVoltage,
+						ShmPsuData->PsuGroup[gp].GroupPresentOutputCurrent);
+			else
+				printf ( "Group_%d IsUsing = IDLE \n", gp);
+		}
+
+		for (byte conn = 0; conn < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; conn++)
+		{
+			if(ShmSmartBoxData->ConnectorStatus[conn].ConnectorStaus == _CONNECTOR_STATUS_NONE)
+				printf ( "Gun_%d Status = IDLE \n", conn);
+			else if (ShmSmartBoxData->ConnectorStatus[conn].ConnectorStaus == _CONNECTOR_STATUS_WAIT)
+				printf ( "Gun_%d Status = WAIT \n", conn);
+			else if(ShmSmartBoxData->ConnectorStatus[conn].ConnectorStaus == _CONNECTOR_STATUS_USING)
+				printf ( "Gun_%d Status = USING \n", conn);
+		}
+	}
+	else if (strcmp(v1, "info") == 0)
+	{
+		printf ( "****************************************************************** \n" );
+		printf ( "SystemPresentPsuQuantity = %d \n", ShmPsuData->SystemPresentPsuQuantity );
+		printf ( "SystemAvailableCurrent = %d (A) \n", ShmPsuData->SystemAvailableCurrent / 10 );
+		printf ( "SystemAvailablePower = %d (kw) \n", ShmPsuData->SystemAvailablePower / 10 );
+		printf ( "GroupCount = %d \n", ShmPsuData->GroupCount );
+
+		if (ShmDcCommonData->systemType == _SYSTEM_TYPE_SMART)
+			printf ("System Type = Smart \n");
+		else if (ShmDcCommonData->systemType == _SYSTEM_TYPE_STANDARD)
+			printf ("System Type = Standard \n");
+		else if (ShmDcCommonData->systemType == _SYSTEM_TYPE_SIMPLE)
+			printf ("System Type = WallMount / Moveable \n");
+
+
+		for (byte conn = 0; conn < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; conn++)
+		{
+			byte totalUsingGpCount = 0;
+			byte totalQuantity = 0;
+			unsigned short _targetVol = 0 , _targetCur = 0;
+			unsigned short _avaCur = 0 , _avaPow = 0;
+			unsigned short _outputVol = 0 , _outputCur = 0;
+			unsigned short _ratingPow = 0;
+
+			for (byte gp = 0; gp < ShmSmartBoxData->ConnectorUsingGroupCount[conn]; gp++)
+			{
+				if (ShmPsuData->PsuGroup[ConnectorUsingSeq[conn][gp]].UsingTarget == GUN_LEFT)
+				{
+					totalUsingGpCount++;
+					byte tarGp = ConnectorUsingSeq[conn][gp];
+
+					totalQuantity += ShmPsuData->PsuGroup[tarGp].GroupPresentPsuQuantity;
+					_targetVol = ShmPsuData->PsuGroup[tarGp].GroupTargetOutputVoltage / 10;
+					_targetCur += ShmPsuData->PsuGroup[tarGp].GroupTargetOutputCurrent / 10;
+					_avaCur += ShmPsuData->PsuGroup[tarGp].GroupAvailableCurrent / 10;
+					_avaPow += ShmPsuData->PsuGroup[tarGp].GroupAvailablePower / 10;
+					_outputVol = (double)ShmPsuData->PsuGroup[tarGp].GroupPresentOutputVoltage / 10;
+					_outputCur += (double)ShmPsuData->PsuGroup[tarGp].GroupPresentOutputCurrent / 10;
+					_ratingPow += ShmPsuData->PsuGroup[tarGp].TotalRatingPower;
+				}
+			}
+
+			if (!FindChargingInfoData (GUN_LEFT, & _chargingData [0]))
+			{
+				printf ( "FindChargingInfoData error\n" );
+				continue;
+			}
+
+			if (totalUsingGpCount > 0)
+			{
+				printf ( "----------------------------------------------------------------- \n" );
+				printf ( "Group Index = %d, totalUsingGpCount = %d \n", conn, totalUsingGpCount);
+				printf ( "totalQuantity = %d \n", totalQuantity);
+				printf ( "_targetVol = %d (V), _targetCur = %d (A), _needPwr = %.1f (kw) \n", _targetVol, _targetCur,
+						(_chargingData[GUN_LEFT]->PresentChargingVoltage * _chargingData[GUN_LEFT]->PresentChargingCurrent) / 1000 );
+				printf ( "_avaCur = %d (A), _avaPow = %d (kw) \n", _avaCur, _avaPow);
+				printf ( "_outputVol = %d (V), _outputCur = %d (A) \n", _outputVol, _outputCur);
+				printf ( "_ratingPow = %d (KW) \n", _ratingPow);
+			}
+		}
+
+		for (byte conn = 0; conn < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; conn ++)
+		{
+			byte totalUsingGpCount = 0;
+			byte totalQuantity = 0;
+			unsigned short _targetVol = 0 , _targetCur = 0;
+			unsigned short _avaCur = 0 , _avaPow = 0;
+			unsigned short _outputVol = 0 , _outputCur = 0;
+			unsigned short _ratingPow = 0;
+
+			for (byte gp = 0; gp < ShmSmartBoxData->ConnectorUsingGroupCount [conn]; gp ++)
+			{
+				if (ShmPsuData->PsuGroup [ConnectorUsingSeq [conn] [gp]].UsingTarget == GUN_RIGHT)
+				{
+					totalUsingGpCount ++;
+					byte tarGp = ConnectorUsingSeq [conn] [gp];
+
+					totalQuantity += ShmPsuData->PsuGroup [tarGp].GroupPresentPsuQuantity;
+					_targetVol = ShmPsuData->PsuGroup [tarGp].GroupTargetOutputVoltage / 10;
+					_targetCur += ShmPsuData->PsuGroup [tarGp].GroupTargetOutputCurrent / 10;
+					_avaCur += ShmPsuData->PsuGroup [tarGp].GroupAvailableCurrent / 10;
+					_avaPow += ShmPsuData->PsuGroup [tarGp].GroupAvailablePower / 10;
+					_outputVol = (double) ShmPsuData->PsuGroup [tarGp].GroupPresentOutputVoltage / 10;
+					_outputCur += (double) ShmPsuData->PsuGroup [tarGp].GroupPresentOutputCurrent / 10;
+					_ratingPow += ShmPsuData->PsuGroup [tarGp].TotalRatingPower;
+				}
+			}
+
+			if (!FindChargingInfoData (GUN_RIGHT, & _chargingData [0]))
+			{
+				printf ( "FindChargingInfoData error\n" );
+				continue;
+			}
+
+			if (totalUsingGpCount > 0)
+			{
+				printf ( "----------------------------------------------------------------- \n" );
+				printf ( "Group Index = %d, totalUsingGpCount = %d \n", conn, totalUsingGpCount );
+				printf ( "totalQuantity = %d \n", totalQuantity );
+				printf ( "_targetVol = %d (V), _targetCur = %d (A), _needPwr = %.1f (kw) \n", _targetVol, _targetCur,
+						(_chargingData[GUN_RIGHT]->PresentChargingVoltage * _chargingData[GUN_RIGHT]->PresentChargingCurrent) / 1000 );
+				printf ( "_avaCur = %d (A), _avaPow = %d (kw) \n", _avaCur, _avaPow );
+				printf ( "_outputVol = %d (V), _outputCur = %d (A) \n", _outputVol, _outputCur );
+				printf ( "_ratingPow = %d (KW) \n", _ratingPow );
+			}
+		}
+		printf ( "****************************************************************** \n" );
+		GetSmartInformation("using","","");
+		GetSmartInformation("relay","","");
+	}
+}
+
 void GetPsuInformation(char *v1, char *v2, char *v3)
 {
 	printf("**********************AC Contact needed*************************\n");
@@ -848,18 +1051,13 @@ void GetPsuInformation(char *v1, char *v2, char *v3)
 	}
 	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(byte group = 0; group < ShmPsuData->GroupCount; group++)
 		{
-			for (int j = 0; j < ShmPsuData->PsuGroup[i].GroupPresentPsuQuantity; j++)
+			for (byte psuCount = 0; psuCount < ShmPsuData->PsuGroup[group].GroupPresentPsuQuantity; psuCount++)
 			{
-				printf("Group Index = %d, Psu Index = %d, Version = %s \n",
-					i, j, ShmPsuData->PsuGroup[i].PsuModule[j].FwVersion);
+				printf("Group = %d, Psu Index = %d, FwVersion = %s \n",
+						group, psuCount,
+						ShmPsuData->PsuGroup[group].PsuModule[psuCount].FwVersion);
 			}
 		}
 	}
@@ -913,6 +1111,7 @@ void GetPsuInformation(char *v1, char *v2, char *v3)
 		{
 			ShmPsuData->Work_Step = mode;
 		}
+
 	}
 	else if (strcmp(v1, "out") == 0)
 	{
@@ -930,14 +1129,26 @@ void GetPsuInformation(char *v1, char *v2, char *v3)
 			_chargingData[0]->EvBatterytargetCurrent = cur;
 		}
 	}
-	else if (strcmp(v1, "force") == 0)
+	else if (strcmp(v1, "info") == 0)
 	{
-		ShmPsuData->Work_Step = _ALATON_MODE;
-		byte id = atof(v2);
+		int _tgGroup = atoi(v2);
+
+		if (_tgGroup < ShmPsuData->GroupCount)
+		{
+			printf("**************************************************************************** \n");
+			printf("Psu Group = %d \n", _tgGroup);
+			printf("GroupTargetOutputVoltage = %d \n", ShmPsuData->PsuGroup[_tgGroup].GroupTargetOutputVoltage);
+			printf("GroupTargetOutputCurrent = %d \n", ShmPsuData->PsuGroup[_tgGroup].GroupTargetOutputCurrent);
 
-		ShmDcCommonData->for_alston_test_1 = id;
+			printf("GroupAvailableCurrent = %d \n", ShmPsuData->PsuGroup[_tgGroup].GroupAvailableCurrent);
+			printf("GroupAvailablePower = %d \n", ShmPsuData->PsuGroup[_tgGroup].GroupAvailablePower);
+			printf("GroupPresentOutputVoltage = %d \n", ShmPsuData->PsuGroup[_tgGroup].GroupPresentOutputVoltage);
+			printf("GroupPresentOutputCurrent = %d \n", ShmPsuData->PsuGroup[_tgGroup].GroupPresentOutputCurrent);
+			printf("GroupPresentOutputPower = %d \n", ShmPsuData->PsuGroup[_tgGroup].GroupPresentOutputPower);
+			printf("TotalIAvailableCurrent = %d \n", ShmPsuData->PsuGroup[_tgGroup].TotalIAvailableCurrent);
+			printf("**************************************************************************** \n");
+		}
 	}
-	printf("*************************************************\n");
 }
 
 void GetConnectorCapInfo(char *v1)
@@ -978,10 +1189,29 @@ static void get_char(char *word)
     }
 }
 
+void GetNeedCount(byte *needGroupCount, float P1, float P2)
+{
+	byte G1_Need = P1 / 30 + (((int)P1 % 30 > 0) ? 1 : 0);
+	byte G2_Need = P2 / 30 + (((int)P2 % 30 > 0) ? 1 : 0);
+
+	// 總群數 >4
+	if (G1_Need + G2_Need > 4)
+	{
+		if (G1_Need > 2)
+			G1_Need = 2;
+
+		G2_Need = 4 - G1_Need;
+	}
+
+	*needGroupCount = G1_Need;
+	*(needGroupCount + 1) = G2_Need;
+}
+
 void AverageCharging(char *g1_vol, char *g1_cur, char *g2_vol, char *g2_cur)
 {
 	float _Voltage[2];
 	float _Current[2];
+	byte needGroupCount[2] = {0, 0};
 
 	_Voltage[0] = atof(g1_vol);
 	_Current[0] = atof(g1_cur);
@@ -989,8 +1219,11 @@ void AverageCharging(char *g1_vol, char *g1_cur, char *g2_vol, char *g2_cur)
 	_Voltage[1] = atof(g2_vol);
 	_Current[1] = atof(g2_cur);
 
-	printf ("g1_vol = %f, g1_cur = %f pow1 = %f (KW) \n", _Voltage[0], _Current[0], (_Voltage[0] * _Current[0]) / 1000);
-	printf ("g2_vol = %f, g2_cur = %f pow2 = %f (KW) \n", _Voltage[1], _Current[1], (_Voltage[1] * _Current[1]) / 1000);
+	printf ("g1_vol = %.1f, g1_cur = %.1f pow1 = %.1f (KW) \n", _Voltage[0], _Current[0], (_Voltage[0] * _Current[0]) / 1000);
+	printf ("g2_vol = %.1f, g2_cur = %.1f pow2 = %.1f (KW) \n", _Voltage[1], _Current[1], (_Voltage[1] * _Current[1]) / 1000);
+
+	GetNeedCount(needGroupCount, (_Voltage[0] * _Current[0]) / 1000, (_Voltage[1] * _Current[1]) / 1000);
+	printf ("needGroupCount[0] = %d, needGroupCount[1] = %d \n", needGroupCount[0], needGroupCount[1]);
 
 	if(_Voltage[0] > 1000 || _Voltage[0] < 50 ||
 			_Voltage[1] > 1000 || _Voltage[1] < 50)
@@ -1042,9 +1275,28 @@ void AverageCharging(char *g1_vol, char *g1_cur, char *g2_vol, char *g2_cur)
 
 						//等待 AC Relay 搭上且找到模組 (main 在此 statue 其它 task 會去做完)
 				        printf ("wait find module\n");
+
+				        if (ShmDcCommonData->systemType == _SYSTEM_TYPE_STANDARD)
+				        {
+				            ShmSmartBoxData->ConnectorUsingGroupCount[gun_index] = 1;
+				        }
+				        else if (ShmDcCommonData->systemType == _SYSTEM_TYPE_SMART)
+				        {
+				            ShmSmartBoxData->ConnectorUsingGroupCount[gun_index] = needGroupCount[gun_index];
+				        }
+
+						for (byte aGp = 0; aGp < ShmSmartBoxData->ConnectorUsingGroupCount [gun_index]; aGp ++)
+						{
+							if (ShmPsuData->PsuGroup [ConnectorUsingSeq [gun_index] [aGp]].GroupPresentPsuQuantity > 0)
+							{
+								ShmPsuData->PsuGroup [ConnectorUsingSeq [gun_index] [aGp]].IsUsing = YES;
+								ShmPsuData->PsuGroup [ConnectorUsingSeq [gun_index] [aGp]].UsingTarget = gun_index;
+							}
+						}
+						ShmSmartBoxData->ConnectorStatus [gun_index].ConnectorStaus = _CONNECTOR_STATUS_USING;
 				    }
 
-					ShmSysConfigAndInfo->SysInfo.MainChargingMode = _MAIN_CHARGING_MODE_AVER;
+					ShmSysConfigAndInfo->SysInfo.MainChargingMode = _MAIN_CHARGING_MODE_BOTH;
 				    //清除 main timeout 機制
 					_chargingData[gun_index]->TimeoutFlag = 0;
 				}
@@ -1346,7 +1598,7 @@ void RunUnconditionalChargeIndex1(char *v1, char *v2, char *v3)
         	    ShmDcCommonData->StartToChargingFlag[_GunIndex] = 0x01;
                 _chargingData[_GunIndex]->SystemStatus = SYS_MODE_PREPARING;
     		}
-    		break;
+    			break;
 
     		case SYS_MODE_PREPARING:
     		{
@@ -1357,8 +1609,36 @@ void RunUnconditionalChargeIndex1(char *v1, char *v2, char *v3)
         	        printf ("[UnconditionalCharge - S_PREPARNIN]\n");
 
         	        //等待 AC Relay 搭上且找到模組 (main 在此 statue 其它 task 會去做完)
-        	        printf ("wait find module\n");
+        	        printf ("wait find module : SystemType = %d \n", ShmDcCommonData->systemType);
 
+        	        if (ShmDcCommonData->systemType == _SYSTEM_TYPE_SIMPLE)
+        	        {
+        	        	if (ShmSysConfigAndInfo->SysInfo.IsAlternatvieConf == YES && _GunIndex == GUN_RIGHT)
+        	        	{
+							// 直接用到第四個位置~ 第 0 群
+							ShmSmartBoxData->ConnectorUsingGroupCount[_GunIndex] = 4;
+        	        	}
+        	        	else
+        	        		ShmSmartBoxData->ConnectorUsingGroupCount[_GunIndex] = 1;
+        	        }
+        	        else if (ShmDcCommonData->systemType == _SYSTEM_TYPE_STANDARD)
+        	        {
+        	        	ShmSmartBoxData->ConnectorUsingGroupCount[_GunIndex] = 4;
+        	        }
+        	        else if (ShmDcCommonData->systemType == _SYSTEM_TYPE_SMART)
+        	        {
+        	        	ShmSmartBoxData->ConnectorUsingGroupCount[_GunIndex] = 4;
+        	        }
+
+        	        for (byte aGp = 0; aGp < ShmSmartBoxData->ConnectorUsingGroupCount[_GunIndex]; aGp++)
+        	        {
+        	        	if (ShmPsuData->PsuGroup[ConnectorUsingSeq[_GunIndex][aGp]].GroupPresentPsuQuantity > 0)
+        	        	{
+        	        		ShmPsuData->PsuGroup [ConnectorUsingSeq [_GunIndex] [aGp]].IsUsing = YES;
+        	        		ShmPsuData->PsuGroup[ConnectorUsingSeq[_GunIndex][aGp]].UsingTarget = _GunIndex;
+        	        	}
+        	        }
+        	        ShmSmartBoxData->ConnectorStatus[_GunIndex].ConnectorStaus = _CONNECTOR_STATUS_USING;
         	    }
     		    //main 會在此階段判斷以下資料跳到下一個 state
     		    //用來得知 AC 是否有搭上 (搭上模組的資訊才會出來) 因為每次  AC_Contactor
@@ -1376,7 +1656,7 @@ void RunUnconditionalChargeIndex1(char *v1, char *v2, char *v3)
     		    _chargingData[_GunIndex]->Type = 9;
 
     		}
-    		break;
+    			break;
 
     		case SYS_MODE_PREPARE_FOR_EV:
     		{
@@ -1386,8 +1666,8 @@ void RunUnconditionalChargeIndex1(char *v1, char *v2, char *v3)
 
         	        printf ("[UnconditionalCharge - SYS_MODE_PREPARE_FOR_EV]\n");
         	        printf ("ReqVoltage = %f, ReqCurrent = %f \n", _Voltage * 10,_Current * 10);
-
         	    }
+
     		    //清除 main timeout 機制
     		    _chargingData[_GunIndex]->TimeoutFlag = 0;
     		    //不論是什麼 type 的槍都固意設成 Chademo 不跑 Prechage step
@@ -1409,7 +1689,7 @@ void RunUnconditionalChargeIndex1(char *v1, char *v2, char *v3)
     		        _chargingData[_GunIndex]->SystemStatus = SYS_MODE_PREPARE_FOR_EVSE;
     		    }
     		}
-    		break;
+    			break;
 
     		case SYS_MODE_PREPARE_FOR_EVSE:
     		{
@@ -1420,6 +1700,7 @@ void RunUnconditionalChargeIndex1(char *v1, char *v2, char *v3)
         	        printf ("[UnconditionalCharge - SYS_MODE_PREPARE_FOR_EVSE]\n");
 
         	    }
+
         	    //printf ("tar vol = %d \n", _Voltage);
         	    //printf ("tar cur = %d \n", _Current);
 
@@ -1459,7 +1740,7 @@ void RunUnconditionalChargeIndex1(char *v1, char *v2, char *v3)
     		    }
 
     		}
-    		break;
+    			break;
 
     		case SYS_MODE_CHARGING:
     		{
@@ -1532,7 +1813,7 @@ void RunUnconditionalChargeIndex1(char *v1, char *v2, char *v3)
 //    		    	gettimeofday(&_printf_time, NULL);
 //    		    }
     		}
-    		break;
+    			break;
 
      		case SYS_MODE_TERMINATING:
     		{
@@ -1550,7 +1831,7 @@ void RunUnconditionalChargeIndex1(char *v1, char *v2, char *v3)
         	    _chargingData[_GunIndex]->SystemStatus = SYS_MODE_COMPLETE;
         	    return;
     		}
-    		break;
+    			break;
 
     		case SYS_MODE_COMPLETE:
     		{
@@ -1565,7 +1846,7 @@ void RunUnconditionalChargeIndex1(char *v1, char *v2, char *v3)
         	    sleep(3);
         	    return;
     		}
-    		break;
+    			break;
     	}
 
     	char word[128];
@@ -1793,6 +2074,17 @@ int main(void)
 			// 取得 PSU 資訊
 			GetPsuInformation(newString[1], newString[2], newString[3]);
 		}
+		else if(strcmp(newString[0], "smart") == 0)
+		{
+			if (strcmp(newString[1], "-1") == 0 || strcmp(newString[1], "") == 0)
+			{
+				printf ("SMART : Param fail..Please retry again......\n");
+				continue;
+			}
+
+			// 取得 Smart 資訊
+			GetSmartInformation(newString[1], newString[2], newString[3]);
+		}
 		else if (strcmp(newString[0], "cap") == 0)
 		{
 			GetConnectorCapInfo(newString[1]);
@@ -1869,19 +2161,32 @@ int main(void)
 
 			printf ("_isAutoRunTest = %d \n", ShmDcCommonData->_isAutoRunTest);
 		}
+		else if (strcmp(newString[0], "fetch") == 0)
+		{
+			byte id = atof(newString[1]);
+
+			ShmDcCommonData->smartFetchRun[id] = YES;
+			printf("Fetch [%d] = %d ON \n", id, ShmDcCommonData->smartFetchRun[id]);
+		}
+		else if (strcmp(newString[0], "release") == 0)
+		{
+			byte id = atof(newString[1]);
+
+			ShmDcCommonData->smartReleaseRun[id] = YES;
+			printf("Release = %d ON \n", ShmDcCommonData->smartReleaseRun[id]);
+		}
 		else if (strcmp(newString[0], "test") == 0)
 		{
-			if (!FindChargingInfoData(1, &_chargingData[0]))
-			{
-				printf("FindChargingInfoData error\n");
-			}
+//			if (!FindChargingInfoData(1, &_chargingData[0]))
+//			{
+//				printf("FindChargingInfoData error\n");
+//			}
+			if (ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isReq)
+				ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isReq = false;
+			else
+				ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isReq = true;
 
-			// Test Command
-			ShmPsuData->PsuGroup[0].GroupErrorFlag.bits.PsuFailure = YES;
-			ShmPsuData->PsuStopChargeFlag = YES;
-			ShmDcCommonData->_isPsuErrorOccur = YES;
-//			ShmDcCommonData->Customer_SwipToChargingByTime += 10;
-//			printf("Charging Time = %u \n", ShmDcCommonData->Customer_SwipToChargingByTime);
+			printf("isReq = %d \n", ShmSysConfigAndInfo->SysInfo.bazel8.cmdPreAuth.isReq);
 		}
 		else if (strcmp(newString[0], "ocpp") == 0)
 		{

二進制
EVSE/Projects/DS60-120/Apps/UnsafetyOutputTask


+ 3 - 3
EVSE/Projects/DS60-120/Apps/internalComm.c

@@ -361,12 +361,12 @@ unsigned char Query_Relay_Output(unsigned char fd, unsigned char targetAddr, Rel
 		   (rx[3] == tx[3]))
 		{
 			Ret_Buf->relay_event.bits.AC_Contactor = (rx[6] >> 0) & 0x01;
-			Ret_Buf->relay_event.bits.CCS_Precharge = (rx[6] >> 1) & 0x01;
+			Ret_Buf->relay_event.bits.R3_BOTH_K1_K4 = (rx[6] >> 1) & 0x01;
 
 			Ret_Buf->relay_event.bits.Gun1_N = (rx[7] >> 0) & 0x01;
 			Ret_Buf->relay_event.bits.Gun1_P = (rx[7] >> 1) & 0x01;
-			Ret_Buf->relay_event.bits.Gun1_Parallel_N = (rx[7] >> 2) & 0x01;
-			Ret_Buf->relay_event.bits.Gun1_Parallel_P = (rx[7] >> 3) & 0x01;
+			Ret_Buf->relay_event.bits.R5_BOTH_K3_K6 = (rx[7] >> 2) & 0x01;
+			Ret_Buf->relay_event.bits.R4_BOTH_K2_K5 = (rx[7] >> 3) & 0x01;
 
 			Ret_Buf->relay_event.bits.Gun2_N = (rx[8] >> 0) & 0x01;
 			Ret_Buf->relay_event.bits.Gun2_P = (rx[8] >> 1) & 0x01;

+ 4 - 4
EVSE/Projects/DS60-120/Apps/internalComm.h

@@ -108,8 +108,8 @@ typedef struct RELAY
 		struct
 		{
 			unsigned char AC_Contactor :1;		//bit 0
-			unsigned char CCS_Precharge :1;	//bit 1
-			unsigned char :1;  				//bit 2 reserved
+			unsigned char R3_BOTH_K1_K4 :1;		//bit 1
+			unsigned char :1;  					//bit 2 reserved
 			unsigned char :1;					//bit 3 reserved
 			unsigned char :1;					//bit 4 reserved
 			unsigned char :1;					//bit 5 reserved
@@ -118,8 +118,8 @@ typedef struct RELAY
 
 			unsigned char Gun1_N :1;			//bit 0
 			unsigned char Gun1_P :1;			//bit 1
-			unsigned char Gun1_Parallel_N :1;  //bit 2
-			unsigned char Gun1_Parallel_P :1;	//bit 3
+			unsigned char R5_BOTH_K3_K6 :1;  	//bit 2 //Stardard : D-
+			unsigned char R4_BOTH_K2_K5 :1;		//bit 3 //Stardard : D+
 			unsigned char :1;					//bit 4 reserved
 			unsigned char :1;					//bit 5 reserved
 			unsigned char :1;					//bit 6 reserved

二進制
EVSE/Projects/DS60-120/Apps/main


文件差異過大導致無法顯示
+ 387 - 137
EVSE/Projects/DS60-120/Apps/main.c


+ 2 - 1
EVSE/Projects/DS60-120/Apps/timeout.h

@@ -49,7 +49,7 @@ enum Timeout_flag
 	Timeout_EvseCompleteDet = 			9,
 	Timeout_ForCcsPrechargeDet = 		10,
 	Timeout_ReturnToChargingGunDet = 	11,
-	Timeout_AuthorizingForStop = 		12
+	Timeout_AuthorizingForStop = 		12,
 };
 
 // for timeout fork
@@ -64,5 +64,6 @@ unsigned char _ocppProfileChkFlag_2;
 unsigned char _ac_ocppProfileChkFlag;
 unsigned char _4gResetChkFlag;
 bool stopChargingChkByCard;
+struct timespec _tcpDetectStatus_time;
 
 #endif /* TIMEOUT_H_ */

二進制
EVSE/Projects/DS60-120/Images/FactoryDefaultConfig.bin


二進制
EVSE/Projects/DS60-120/Images/ramdisk.gz


二進制
EVSE/rootfs/root/Module_Payment_Bazel8


二進制
EVSE/rootfs/root/Module_PowerSharing


部分文件因文件數量過多而無法顯示