#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 	<arpa/inet.h>
#include 	<netinet/in.h>

#include 	<unistd.h>
#include 	<stdarg.h>
#include    <stdio.h>      /*�зǿ�J��X�w�q*/
#include    <stdlib.h>     /*�зǨ�Ʈw�w�q*/
#include    <unistd.h>     /*Unix �зǨ�Ʃw�q*/
#include    <fcntl.h>      /*�ɱ���w�q*/
#include    <termios.h>    /*PPSIX �׺ݱ���w�q*/
#include    <errno.h>      /*���~���w�q*/
#include 	<string.h>
#include	<time.h>
#include	<ctype.h>
#include 	<ifaddrs.h>
#include 	<math.h>
#include	"../../define.h"
#include	"internalComm.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 STOP				0
#define START				1
#define NORMAL				0
#define	ABNORMAL			1
#define RELAY_CHECK_TIME	5		// s
#define OUTPUT_VOL_CHK_TIME	200 	// ms
#define TEN_MINUTES			600		// s
//#define TEN_MINUTES			10		// s
#define FORCE_STOP_TIME		30
//#define TEN_MINUTES			5
#define ENV_TEMP_MIN		45
#define ENV_TEMP_MAX		50
#define DEFAULT_AC_INDEX	2
#define EQUAL				0
#define COLOR_MAX_LV		100
#define COLOR_MIN_LV		0
#define MIN_OUTPUT_CUR		0
#define	AC_OUTPUT_VOL		220

#define	NO_DEFINE			255
#define	NDEFAULT_AC_INDEX	2

#define OVP_UVP_CHK_COUNT 	3

struct SysConfigAndInfo			*ShmSysConfigAndInfo;
struct StatusCodeData 			*ShmStatusCodeData;
struct FanModuleData			*ShmFanModuleData;
struct RelayModuleData			*ShmRelayModuleData;
struct LedModuleData			*ShmLedModuleData;
struct CcsData					*ShmCcsData;
struct PsuData 					*ShmPsuData;
struct OCPP16Data				*ShmOCPP16Data;
struct OCPP20Data				*ShmOCPP20Data;
struct PrimaryMcuData			*ShmPrimaryMcuData;
struct DcCommonInformation		*ShmDcCommonData;
struct SmartBoxData				*ShmSmartBoxData;

#define VIN_MAX_VOLTAGE_IEC			285	// �j��ӭ� : OVP
#define VIN_MAX_REV_VOLTAGE_IEC		275	// �p����k OVP
#define VIN_MIN_VOLTAGE_IEC			160	// �p��ӭ� : UVP
#define VIN_MIN_REV_VOLTAGE_IEC		170	// �j����k UVP

#define VIN_MAX_VOLTAGE_UL			315	// �j��ӭ� : OVP // ���W (W)
#define VIN_MAX_REV_VOLTAGE_UL		305	// �p����k OVP
#define VIN_MIN_VOLTAGE_UL			210	// �p��ӭ� : UVP
#define VIN_MIN_REV_VOLTAGE_UL 		220	// �j����k UVP

//LWADD
#define VIN_MAX_VOLTAGE_JARI			285	// �j��ӭ� : OVP // ��W (W)
#define VIN_MAX_REV_VOLTAGE_JARI		275	// �p����k OVP
#define VIN_MIN_VOLTAGE_JARI			180	// �p��ӭ� : UVP
#define VIN_MIN_REV_VOLTAGE_JARI 		190	// �j����k UVP

// 50KW �t��
#define VIN_MAX_VOLTAGE_JARI_50KW		250	// �j��ӭ� : OVP // ��W (W)
#define VIN_MAX_REV_VOLTAGE_JARI_50KW	240	// �p����k OVP
#define VIN_MIN_VOLTAGE_JARI_50KW		165	// �p��ӭ� : UVP
#define VIN_MIN_REV_VOLTAGE_JARI_50KW	175	// �j����k UVP

#define VIN_DROP_VOLTAGE	150	// �p��ӭ� : ac drop

#define VOUT_MAX_VOLTAGE	995
#define VOUT_MIN_VOLTAGE	150
#define IOUT_MAX_CURRENT	50

#define MAX_FAN_SPEED		14000
#define MIN_FAN_SPEED		3000
#define NORMAL_FAN_SPEED	7000

// GFD Status
#define GFD_IDLE			0
#define GFD_CABLECHK		1
#define GFD_PRECHARGE		2
#define GFD_CHARGING		3

// LED Intensity (rate)
#define LED_INTENSITY_DARKEST		0.2
#define LED_INTENSITY_MEDIUM		0.6
#define LED_INTENSITY_BRIGHTEST		1

// EE Spec
#define LED_BRIGHTNESS_LV_HIGH		1
#define LED_BRIGHTNESS_LV_MID		0.5
#define LED_BRIGHTNESS_LV_LOW		0.2

// �̤p���� Relay �q��
#define SELF_TO_CHANGE_RELAY_STATUS			600
// �z�L�q���T�{ Relay �O�_�f�W���̾ڹq��
#define CHECK_RELAY_STATUS					300
#define CHECK_RELAY_STATUS_GAP				100
// �w���b����R�q�{�Ǥ��_�} Relay ���q�y
#define SEFETY_SWITCH_RELAY_CUR				50
// �T�{ Relay Welding �q��
#define RELAY_WELDING_DET					300
// CCS minimum precharge voltage
#define CCS_PRECHARGE_VOL					2000
#define CCS_PRECHARGE_STARTU				40

unsigned int _acErrRecord;

byte gunCount;
byte acgunCount;
// �j��T
struct ChargingInfoData *_chargingData[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
struct ChargingInfoData *ac_chargingInfo[AC_QUANTITY];
unsigned short AcChargingRatingCurrent;

float _ChargingProfilePwBuffer[AC_QUANTITY];

byte ac_startTransationFlag;
Relay acOutputRelay;

bool _isOutputNoneMatch[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
struct timespec _checkOutputNoneMatchTimer[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];

//bool _isRelayWelding[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
//struct timeval _checkRelayWeldingTimer[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
bool _isOvpChkTimeFlag[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
struct timespec _checkOutputVolProtectTimer[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];

// SMR1 *2 + SMR2 * 2 + Parallel * 2
struct timespec _relayStateChkTimer[6];

byte _threePhaseOvp[3] = {0, 0, 0};
byte _threePhaseUvp[3] = {0, 0, 0};

bool FindChargingInfoData(byte target, struct ChargingInfoData **chargingData);

int Uart5Fd;
char *relayRs485PortName = "/dev/ttyS5";
unsigned short fanSpeedSmoothValue = 500;

bool isStopChargingCount = false;
struct timespec _close_ac_contactor;

struct timespec _priority_time;
struct timespec _led_priority_time;
struct timespec _led_blink_time;

struct timespec	_ac_charging_comp;
struct timespec	_ac_preparing;
struct timeb 	_ac_startChargingTime;
struct timeb 	_ac_endChargingTime;
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�t��
bool is50kwSystem;

Ver ver;
PresentInputVoltage inputVoltage;
PresentOutputVoltage outputVoltage;
FanSpeed fanSpeed;
Temperature temperature;
AuxPower auxPower;
Gfd gfd_adc;
Gfd_config gfd_config;
Gpio_in gpio_in;
Gpio_out gpio_out;
Relay outputRelay;
Relay regRelay;
Rtc rtc;
Led_Color cur_led_color;
Led_Color led_color;

Ac_Status acStatus;
Ac_Led_Status ledStatus;
Ac_Alarm_code acAlarmCode;
Ac_Charging_energy acChargingEnergy;
Ac_Charging_current acChargingCurrent;
PresentInputVoltage acChargingVoltage;

bool isAcModuleInitComp;
int mask_table[] = {
		0x00000001, 0x00000002, 0x00000004, 0x00000008,
		0x00000010, 0x00000020, 0x00000040, 0x00000080,
		0x00000100, 0x00000200, 0x00000400, 0x00000800,
		0x00001000, 0x00002000, 0x00004000, 0x00008000,
		0x00010000, 0x00020000, 0x00040000, 0x00080000,
		0x00100000, 0x00200000, 0x00400000, 0x00800000,
		0x01000000, 0x02000000, 0x04000000, 0x08000000,
		0x10000000, 0x20000000, 0x40000000, 0x80000000
};

#define L1_AC_OVP						0
#define L1_AC_UVP						1
#define L1_AC_OCP						2
#define AC_OTP							3
#define AC_GMI_FAULT					4
#define AC_CP_ERROR						5
#define AC_AC_LEAKAGE					6
#define AC_DC_LEAKAGE					7
#define AC_SYSTEM_SELFTEST_FAULT		8
#define AC_HANDSHAKE_TIMEOUT			9
#define AC_EMC_STOP						10
#define AC_RELAY_WELDING				11
#define AC_LEAK_MODULE_FAULT			12
#define AC_SHUTTER_FAULT				13
#define AC_LOCKER_FAULT					14
#define AC_POWER_DROP					15
#define L1_AC_CIRCUIT_SHORT				16
#define AC_ROTARY_SWITCH_FAULT			17
#define AC_RELAY_DRIVE_FAULT			18
#define RESERVED_1						19
#define L2_AC_OVP						20
#define L3_AC_OVP						21
#define L2_AC_UVP						22
#define L3_AC_UVP						23
#define L2_AC_OCP						24
#define L3_AC_OCP						25
#define L2_AC_CIRCUIT_SHORT				26
#define L3_AC_CIRCUIT_SHORT				27
#define AC_METER_TIMEOUT				28
#define AC_METER_IC_COMM_TIMEOUT		29
#define AC_CP_NEGATIVE_ERR				30
#define RESERVED_2						31

void PRINTF_FUNC(char *string, ...);

int StoreLogMsg(const char *fmt, ...);
int GetTimeoutValue(struct timespec *startTime);

void ocpp_ac_clear_errorCode_cmd(bool isError);

#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)

long int GetTimeoutMValue(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;
}

void GetTimespecMFunc(struct timespec *time)
{
	clock_gettime(CLOCK_MONOTONIC, time);
}

int GetTimeoutValue(struct timespec *startTime)
{
	struct timespec endTime;

	clock_gettime(CLOCK_MONOTONIC_COARSE, &endTime);
	return endTime.tv_sec - startTime->tv_sec;
}

void GetTimespecFunc(struct timespec *time)
{
	clock_gettime(CLOCK_MONOTONIC_COARSE, time);
}

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;
}

int DiffTimeb(struct timeb ST, struct timeb ET)
{
	//return milli-second
	unsigned int StartTime, StopTime;

	StartTime = (unsigned int) ST.time;
	StopTime = (unsigned int) ET.time;
	//return (StopTime-StartTime)*1000+ET.millitm-ST.millitm;
	return (StopTime - StartTime);
}

unsigned short MaxValue(unsigned short value1, unsigned short value2)
{
	return value1 >= value2 ? value1 : value2;
}

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);
}

//==========================================
// Communication Function
//==========================================
void GetFwAndHwVersion_Fan()
{
	if(Query_FW_Ver(Uart5Fd, Addr.Fan, &ver) == PASS)
	{
		// FanModuleData
		strcpy((char *) ShmFanModuleData->version, ver.Version_FW);
		// SystemInfo
		strcpy((char *) ShmSysConfigAndInfo->SysInfo.FanModuleFwRev, ver.Version_FW);
		//PRINTF_FUNC("GetFwAndHwVersion_Fan s1 = %s \n", ver.Version_FW);
	}

	if (Query_HW_Ver(Uart5Fd, Addr.Fan, &ver) == PASS)
	{
		// SystemInfo
		strcpy((char *) ShmSysConfigAndInfo->SysInfo.FanModuleHwRev, ver.Version_FW);
		//PRINTF_FUNC("GetFwAndHwVersion_Fan s2 = %s \n", ver.Version_HW);
	}
}

void GetFwAndHwVersion_Relay()
{
	if (Query_FW_Ver(Uart5Fd, Addr.Relay, &ver) == PASS)
	{
		// RelayModuleData
		strcpy((char *) ShmRelayModuleData->version, ver.Version_FW);
		// SystemInfo
		strcpy((char *) ShmSysConfigAndInfo->SysInfo.RelayModuleFwRev, ver.Version_FW);
		//PRINTF_FUNC("GetFwAndHwVersion_Relay s1 = %s \n", ver.Version_FW);
	}

	if (Query_HW_Ver(Uart5Fd, Addr.Relay, &ver) == PASS)
	{
		// SystemInfo
		strcpy((char *) ShmSysConfigAndInfo->SysInfo.RelayModuleHwRev, ver.Version_FW);
		//PRINTF_FUNC("GetFwAndHwVersion_Relay s2 = %s \n", ver.Version_HW);
	}
}

void GetFwAndHwVersion_Led()
{
	if (Query_FW_Ver(Uart5Fd, Addr.Led, &ver) == PASS)
	{
		// LedModuleData
		strcpy((char *) ShmLedModuleData->version, ver.Version_FW);
		// SystemInfo
		strcpy((char *) ShmSysConfigAndInfo->SysInfo.LedModuleFwRev, ver.Version_FW);
		ShmLedModuleData->SelfTest_Comp = YES;
	}
	else
	{
		//PRINTF_FUNC("GetFwAndHwVersion_Led fail \n");
	}

//	if (Query_HW_Ver(Uart5Fd, Addr.Led, &ver) == PASS)
//	{
//		// SystemInfo
//		strcpy((char *) ShmSysConfigAndInfo->SysInfo.RelayModuleHwRev, ver.Version_FW);
//		//PRINTF_FUNC("GetFwAndHwVersion_Relay s2 = %s \n", ver.Version_HW);
//	}
}

void GetFwVersion_AC()
{
	if (Query_FW_Ver(Uart5Fd, Addr.AcPlug, &ver) == PASS)
	{
		ac_chargingInfo[0]->SelfTest_Comp = YES;
		strcpy((char *) ac_chargingInfo[0]->version, ver.Version_FW);
	}
}

void GetAcModelName()
{
	memset(ShmSysConfigAndInfo->SysConfig.AcModelName, 0x00, sizeof(ShmSysConfigAndInfo->SysConfig.AcModelName));
	if (Query_Model_Name(Uart5Fd, Addr.AcPlug, ShmSysConfigAndInfo->SysConfig.AcModelName) == PASS)
	{
		PRINTF_FUNC("ac model name = %s \n", ShmSysConfigAndInfo->SysConfig.AcModelName);
	}
}

void SetRtcData_Relay()
{
	struct timeb csuTime;
	struct tm *tmCSU;

	ftime(&csuTime);
	tmCSU = localtime(&csuTime.time);
	//	PRINTF_FUNC("Time : %04d-%02d-%02d %02d:%02d:%02d \n", tmCSU->tm_year + 1900,
	//			tmCSU->tm_mon + 1, tmCSU->tm_mday, tmCSU->tm_hour, tmCSU->tm_min,
	//			tmCSU->tm_sec);

	rtc.RtcData[0] = '0' + (tmCSU->tm_year + 1900) / 1000 % 10;
	rtc.RtcData[1] = '0' + (tmCSU->tm_year + 1900) / 100 % 10;
	rtc.RtcData[2] = '0' + (tmCSU->tm_year + 1900) / 10 % 10;
	rtc.RtcData[3] = '0' + (tmCSU->tm_year + 1900) / 1 % 10;

	rtc.RtcData[4] = '0' + (tmCSU->tm_mon + 1) / 10 % 10;
	rtc.RtcData[5] = '0' + (tmCSU->tm_mon + 1) / 1 % 10;

	rtc.RtcData[6] = '0' + (tmCSU->tm_mday) / 10 % 10;
	rtc.RtcData[7] = '0' + (tmCSU->tm_mday) / 1 % 10;

	rtc.RtcData[8] = '0' + (tmCSU->tm_hour) / 10 % 10;
	rtc.RtcData[9] = '0' + (tmCSU->tm_hour) / 1 % 10;

	rtc.RtcData[10] = '0' + (tmCSU->tm_min) / 10 % 10;
	rtc.RtcData[11] = '0' + (tmCSU->tm_min) / 1 % 10;

	rtc.RtcData[12] = '0' + (tmCSU->tm_sec) / 10 % 10;
	rtc.RtcData[13] = '0' + (tmCSU->tm_sec) / 1 % 10;

	if (Config_Rtc_Data(Uart5Fd, Addr.Relay, &rtc) == PASS)
	{
		//PRINTF_FUNC("SetRtc (RB) sucessfully. \n");
	}
}

void SetModelName_Relay()
{
	if (Config_Model_Name(Uart5Fd, Addr.Relay, ShmSysConfigAndInfo->SysConfig.ModelName) == PASS)
	{
		//PRINTF_FUNC("Set Model name (RB) PASS = %s \n", ShmSysConfigAndInfo->SysConfig.ModelName);
	}
}

void SetRtcData_Fan()
{
	struct timeb csuTime;
	struct tm *tmCSU;

	ftime(&csuTime);
	tmCSU = localtime(&csuTime.time);
	//	PRINTF_FUNC("Time : %04d-%02d-%02d %02d:%02d:%02d \n", tmCSU->tm_year + 1900,
	//			tmCSU->tm_mon + 1, tmCSU->tm_mday, tmCSU->tm_hour, tmCSU->tm_min,
	//			tmCSU->tm_sec);

	rtc.RtcData[0] = '0' + (tmCSU->tm_year + 1900) / 1000 % 10;
	rtc.RtcData[1] = '0' + (tmCSU->tm_year + 1900) / 100 % 10;
	rtc.RtcData[2] = '0' + (tmCSU->tm_year + 1900) / 10 % 10;
	rtc.RtcData[3] = '0' + (tmCSU->tm_year + 1900) / 1 % 10;

	rtc.RtcData[4] = '0' + (tmCSU->tm_mon + 1) / 10 % 10;
	rtc.RtcData[5] = '0' + (tmCSU->tm_mon + 1) / 1 % 10;

	rtc.RtcData[6] = '0' + (tmCSU->tm_mday) / 10 % 10;
	rtc.RtcData[7] = '0' + (tmCSU->tm_mday) / 1 % 10;

	rtc.RtcData[8] = '0' + (tmCSU->tm_hour) / 10 % 10;
	rtc.RtcData[9] = '0' + (tmCSU->tm_hour) / 1 % 10;

	rtc.RtcData[10] = '0' + (tmCSU->tm_min) / 10 % 10;
	rtc.RtcData[11] = '0' + (tmCSU->tm_min) / 1 % 10;

	rtc.RtcData[12] = '0' + (tmCSU->tm_sec) / 10 % 10;
	rtc.RtcData[13] = '0' + (tmCSU->tm_sec) / 1 % 10;

	if (Config_Rtc_Data(Uart5Fd, Addr.Fan, &rtc) == PASS)
	{
		//PRINTF_FUNC("SetRtc (FB) sucessfully. \n");
	}
}

void SetModelName_Fan()
{
	if (Config_Model_Name(Uart5Fd, Addr.Fan, ShmSysConfigAndInfo->SysConfig.ModelName) == PASS)
	{
		//PRINTF_FUNC("Set Model name (FAN) PASS = %s \n", ShmSysConfigAndInfo->SysConfig.ModelName);
	}
}

// AC �T�ۿ�J�q��
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)
		{
			if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP == NO)
			{
				if (inputVoltage.L1N_L12 < VIN_MIN_VOLTAGE_IEC)
				{
					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_IEC)
				{
					ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP = NO;
					_threePhaseUvp[0] = 0;
				}
			}

			if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP == NO)
			{
				if (inputVoltage.L2N_L23 < VIN_MIN_VOLTAGE_IEC)
				{
					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_IEC)
				{
					ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP = NO;
					_threePhaseUvp[1] = 0;
				}
			}

			if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP == NO)
			{
				if (inputVoltage.L3N_L31 < VIN_MIN_VOLTAGE_IEC)
				{
					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_IEC)
				{
					ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP = NO;
					_threePhaseUvp[2] = 0;
				}
			}
		}
		else if (ShmSysConfigAndInfo->SysInfo.ChargerType == _CHARGER_TYPE_UL)
		{
			if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP == NO)
			{
				if (inputVoltage.L1N_L12 < VIN_MIN_VOLTAGE_UL)
				{
					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_UL)
				{
					ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP = NO;
					_threePhaseUvp[0] = 0;
				}
			}

			if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP == NO)
			{
				if (inputVoltage.L2N_L23 < VIN_MIN_VOLTAGE_UL)
				{
					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_UL)
				{
					ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP = NO;
					_threePhaseUvp[1] = 0;
				}
			}

			if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP == NO)
			{
				if (inputVoltage.L3N_L31 < VIN_MIN_VOLTAGE_UL)
				{
					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_UL)
				{
					ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP = NO;
					_threePhaseUvp[2] = 0;
				}
			}
		}
		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)
		{
			if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP == NO)
			{
				if (inputVoltage.L1N_L12 > VIN_MAX_VOLTAGE_IEC)
				{
					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] += 1;
				}
			}
			else
			{
				if (inputVoltage.L1N_L12 < VIN_MAX_REV_VOLTAGE_IEC)
				{
					ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP = NO;
					_threePhaseOvp[0] = 0;
				}
			}

			if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP == NO)
			{
				if (inputVoltage.L2N_L23 > VIN_MAX_VOLTAGE_IEC)
				{
					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] += 1;
				}
			}
			else
			{
				if (inputVoltage.L2N_L23 < VIN_MAX_REV_VOLTAGE_IEC)
				{
					ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP = NO;
					_threePhaseOvp[1] = 0;
				}
			}

			if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP == NO)
			{
				if (inputVoltage.L3N_L31 > VIN_MAX_VOLTAGE_IEC)
				{
					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_IEC)
				{
					ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP = NO;
					_threePhaseOvp[2] = 0;
				}
			}
		}
		else if (ShmSysConfigAndInfo->SysInfo.ChargerType == _CHARGER_TYPE_UL)
		{
			if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP == NO)
			{
				if (inputVoltage.L1N_L12 > VIN_MAX_VOLTAGE_UL)
				{
					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] += 1;
				}
			}
			else
			{
				if (inputVoltage.L1N_L12 < VIN_MAX_REV_VOLTAGE_UL)
				{
					ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP = NO;
					_threePhaseOvp[0] = 0;
				}
			}

			if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP == NO)
			{
				if (inputVoltage.L2N_L23 > VIN_MAX_VOLTAGE_UL)
				{
					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] += 1;
				}
			}
			else
			{
				if (inputVoltage.L2N_L23 < VIN_MAX_REV_VOLTAGE_UL)
				{
					ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP = NO;
					_threePhaseOvp[1] = 0;
				}
			}

			if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP == NO)
			{
				if (inputVoltage.L3N_L31 > VIN_MAX_VOLTAGE_UL)
				{
					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_UL)
				{
					ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP = NO;
					_threePhaseOvp[2] = 0;
				}
			}
		}
		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] += 1;
					}
				}
				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] += 1;
					}
				}
				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] += 1;
					}
				}
				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] += 1;
					}
				}
				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;
					}
				}
			}
		}
	}
}

// ���k�j�� Relay �e�᪺��X�q��
void GetPersentOutputVol()
{
	if (Query_Present_OutputVoltage(Uart5Fd, Addr.Relay, &outputVoltage) == PASS)
	{
//		PRINTF_FUNC("Conn1 fuse 1 = %f \n", outputVoltage.behindFuse_Voltage_C1);
//		PRINTF_FUNC("Conn1 relay 1 = %f \n", outputVoltage.behindRelay_Voltage_C1);
//		PRINTF_FUNC("Conn2 fuse 2 = %f \n", outputVoltage.behindFuse_Voltage_C2);
//		PRINTF_FUNC("Conn2 relay 2 = %f \n", outputVoltage.behindRelay_Voltage_C2);

		//PRINTF_FUNC("outputVoltage.behindFuse_Voltage_C1 = %f \n", outputVoltage.behindFuse_Voltage_C1);
		//PRINTF_FUNC("outputVoltage.behindFuse_Voltage_C2 = %f \n", outputVoltage.behindFuse_Voltage_C2);

		ShmRelayModuleData->Gun1FuseOutputVolt = outputVoltage.behindFuse_Voltage_C1;
		ShmRelayModuleData->Gun1RelayOutputVolt = outputVoltage.behindRelay_Voltage_C1;
		ShmRelayModuleData->Gun2FuseOutputVolt = outputVoltage.behindFuse_Voltage_C2;
		ShmRelayModuleData->Gun2RelayOutputVolt = outputVoltage.behindRelay_Voltage_C2;

		for (int index = 0; index < gunCount; index++)
		{
			if (index == 0)
			{
				if (_chargingData[index]->Evboard_id == 0x01)
				{
					_chargingData[index]->FuseChargingVoltage = ShmRelayModuleData->Gun1FuseOutputVolt;
					_chargingData[index]->FireChargingVoltage = ShmRelayModuleData->Gun1RelayOutputVolt;
				}
				else if (_chargingData[index]->Evboard_id == 0x02)
				{
					_chargingData[index]->FuseChargingVoltage = ShmRelayModuleData->Gun2FuseOutputVolt;
					_chargingData[index]->FireChargingVoltage = ShmRelayModuleData->Gun2RelayOutputVolt;
				}
			}
			else if (index == 1)
			{
				_chargingData[index]->FuseChargingVoltage = ShmRelayModuleData->Gun2FuseOutputVolt;
				_chargingData[index]->FireChargingVoltage = ShmRelayModuleData->Gun2RelayOutputVolt;
			}

			//unsigned short Ovp = 0;
			//unsigned short Ocp = 0;
			//Ovp = MIN [VOUT_MAX_VOLTAGE, EV_BATTERY_VOLTAGE] 	// �̤j��X�q���P�q���q���̤j��
			//Ocp = MIN [IOUT_MAX_CURRENT, EV_CURRENT_REQ]		// �̤j��X�q�y�P�ݨD�q�y�̤p��
			if (_chargingData[index]->Type == _Type_Chademo)
			{
				//Ovp = MaxValue(_chargingData[index]->MaximumChargingVoltage, _chargingData[index]->EvBatteryMaxVoltage);
				//Ocp = MaxValue(_chargingData[index]->PresentChargingCurrent, ShmCHAdeMOData->ev[_chargingData[index]->type_index].ChargingCurrentRequest);
			}
			else if (_chargingData[index]->Type == _Type_CCS)
			{

			}
		}
	}
}

// �����t��
void GetFanSpeed()
{
	//PRINTF_FUNC("Get fan board speed \n");
	if (Query_Fan_Speed(Uart5Fd, Addr.Fan, &fanSpeed) == PASS)
	{
		ShmFanModuleData->PresentFan1Speed = fanSpeed.speed[0];
		ShmFanModuleData->PresentFan2Speed = fanSpeed.speed[1];
		ShmFanModuleData->PresentFan3Speed = fanSpeed.speed[2];
		ShmFanModuleData->PresentFan4Speed = fanSpeed.speed[3];
//		PRINTF_FUNC("SystemFanRotaSpeed_1 = %d \n", fanSpeed.speed[0]);
//		PRINTF_FUNC("SystemFanRotaSpeed_2 = %d \n", fanSpeed.speed[1]);
//		PRINTF_FUNC("SystemFanRotaSpeed_3 = %d \n", fanSpeed.speed[2]);
//		PRINTF_FUNC("SystemFanRotaSpeed_4 = %d \n", fanSpeed.speed[3]);
		// Config_Fan_Speed(Uart5Fd, Addr.Fan, &fanSpeed[0]);
		//SysInfoData (SystemFanRotaSpeed)
	}
}

// Ū�� Relay ���A
void GetRelayOutputStatus()
{
	if (Query_Relay_Output(Uart5Fd, Addr.Relay, &regRelay) == PASS)
	{
		//regRelay.relay_event.bits.AC_Contactor = ShmSysConfigAndInfo->SysInfo.AcContactorStatus;
	}
}

// �T�{ K1 K2 relay �����A
void CheckK1K2RelayOutput(byte index)
{
	if (index == 0)
	{
		if (_chargingData[index]->Evboard_id == 0x01)
		{
			if (regRelay.relay_event.bits.Gun1_N == YES && regRelay.relay_event.bits.Gun1_P == YES)
				_chargingData[index]->RelayK1K2Status = YES;
			else
				_chargingData[index]->RelayK1K2Status = NO;

			if(_chargingData[index]->Type == _Type_CCS)
			{
//				if (gunCount == 1)
//				{
//					if (regRelay.relay_event.bits.Gun1_N == YES	&& regRelay.relay_event.bits.CCS_Precharge == YES)
//						_chargingData[index]->RelayKPK2Status = YES;
//					else
//						_chargingData[index]->RelayKPK2Status = NO;
//				}
//				else
				{
					if (_chargingData[index]->SystemStatus == SYS_MODE_CCS_PRECHARGE_STEP0)
						_chargingData[index]->RelayKPK2Status = YES;
					else
						_chargingData[index]->RelayKPK2Status = NO;
				}
			}
		}
		else if (_chargingData[index]->Evboard_id == 0x02)
		{
			if (regRelay.relay_event.bits.Gun2_N == YES && regRelay.relay_event.bits.Gun2_P == YES)
				_chargingData[index]->RelayK1K2Status = YES;
			else
				_chargingData[index]->RelayK1K2Status = NO;

			if(_chargingData[index]->Type == _Type_CCS)
			{
//				if (regRelay.relay_event.bits.Gun2_N == YES	&& regRelay.relay_event.bits.CCS_Precharge == YES)
//					_chargingData[index]->RelayKPK2Status = YES;
//				else
//					_chargingData[index]->RelayKPK2Status = NO;

				if (_chargingData[index]->SystemStatus == SYS_MODE_CCS_PRECHARGE_STEP0)
					_chargingData[index]->RelayKPK2Status = YES;
				else
					_chargingData[index]->RelayKPK2Status = NO;
			}
		}
	}
	else if (index == 1)
	{
		if (regRelay.relay_event.bits.Gun2_N == YES && regRelay.relay_event.bits.Gun2_P == YES)
			_chargingData[index]->RelayK1K2Status = YES;
		else
			_chargingData[index]->RelayK1K2Status = NO;

		if(_chargingData[index]->Type == _Type_CCS)
		{
//			if (regRelay.relay_event.bits.Gun2_N == YES && regRelay.relay_event.bits.CCS_Precharge == YES)
//				_chargingData[index]->RelayKPK2Status = YES;
//			else
//				_chargingData[index]->RelayKPK2Status = NO;

			if (_chargingData[index]->SystemStatus == SYS_MODE_CCS_PRECHARGE_STEP0)
				_chargingData[index]->RelayKPK2Status = YES;
			else
				_chargingData[index]->RelayKPK2Status = NO;
		}
	}

	if (ShmSmartBoxData->RcbParallelStatus[0] == YES)
	{
		if (regRelay.relay_event.bits.R3_BOTH_K1_K4 == NO)
			ShmSmartBoxData->RcbParallelStatus[0] = NO;
	}
	else if (ShmSmartBoxData->RcbParallelStatus[0] == NO)
	{
		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",
//			index, _chargingData[index]->RelayKPK2Status, ShmSysConfigAndInfo->SysInfo.BridgeRelayStatus);
}

void GetGfdAdc()
{
	// define : �C 0.2 ~ 1 ���@��
	// occur : <= 75k �کi @ 150 - 750 Vdc
	// warning : >= 100 �کi && <= 500 �کi @ 150-750 Vdc
	if (Query_Gfd_Adc(Uart5Fd, Addr.Relay, &gfd_adc) == PASS)
	{
		for (int i = 0; i < gunCount; i++)
		{
			if (_chargingData[i]->Type == 0x09 && !ShmSysConfigAndInfo->SysConfig.AlwaysGfdFlag)
			{
				if (_chargingData[i]->FireChargingVoltage >= VOUT_MIN_VOLTAGE)
					_chargingData[i]->GroundFaultStatus = GFD_PASS;
				continue;
			}

			if (i == 0)
			{
				_chargingData[i]->GroundFaultStatus = gfd_adc.result_conn1;
//				PRINTF_FUNC("GFD ******** Result = %d, Step = %d, R = %d, Vol = %d \n",
//						_chargingData[i]->GroundFaultStatus, gfd_adc.rb_step_1, gfd_adc.Resister_conn1, gfd_adc.voltage_conn1);
				if (_chargingData[i]->GroundFaultStatus == GFD_FAIL)
				{
					PRINTF_FUNC("GFD Fail. index = %d, Step = %d, R = %d, Vol = %d \n",
							i, gfd_adc.rb_step_1, gfd_adc.Resister_conn1, gfd_adc.voltage_conn1);
				}
				else if (_chargingData[i]->GroundFaultStatus == GFD_PASS ||
						_chargingData[i]->GroundFaultStatus == GFD_WARNING)
				{
					if (_chargingData[i]->GroundFaultStatus == GFD_WARNING)
					{
						PRINTF_FUNC("GFD Warning. index = %d, Result = %d, R = %d, Vol = %d \n",
								i, _chargingData[i]->GroundFaultStatus, gfd_adc.Resister_conn1, gfd_adc.voltage_conn1);
					}
				}
			}
			else if (i == 1)
			{
				_chargingData[i]->GroundFaultStatus = gfd_adc.result_conn2;
				if (_chargingData[i]->GroundFaultStatus == GFD_FAIL)
				{
					PRINTF_FUNC("GFD Fail. index = %d, Step = %d, R = %d, Vol = %d \n",
							i, gfd_adc.rb_step_2, gfd_adc.Resister_conn2, gfd_adc.voltage_conn2);
				}
				else if (_chargingData[i]->GroundFaultStatus == GFD_PASS ||
						_chargingData[i]->GroundFaultStatus == GFD_WARNING)
				{
					if (_chargingData[i]->GroundFaultStatus == GFD_WARNING)
					{
						PRINTF_FUNC("GFD Warning. index = %d, Result = %d, R = %d, Vol = %d \n",
							i, _chargingData[i]->GroundFaultStatus, gfd_adc.Resister_conn1, gfd_adc.voltage_conn1);
					}
				}
			}
		}
	}
}

void GetGpioInput()
{
	if (Query_Gpio_Input(Uart5Fd, Addr.Aux, &gpio_in) == PASS)
	{
		// AC Contactor Status
		if (gpio_in.AC_MainBreaker == 1)
		{
			// AC Main Breaker ON
			PRINTF_FUNC("RB AC Main Breaker. \n");
		}

		if (gpio_in.SPD == 1)
		{
			// SPD (�p���O�@) ON
			PRINTF_FUNC("RB SPD. \n");
		}

		if (gpio_in.Door_Open == 1)
		{
			// Door Open
			PRINTF_FUNC("RB Door Open. \n");
		}

		if (gpio_in.GFD[0] == 1)
		{
			// GFD_1 Trigger
		}

		if (gpio_in.GFD[1] == 1)
		{
			// GFD_2 Trigger
		}

		if (gpio_in.AC_Drop == 1)
		{
			// AC Drop
			PRINTF_FUNC("RB AC Drop. \n");
		}

		if (gpio_in.Emergency_IO == 1)
		{
			// Emergency IO ON
			PRINTF_FUNC("RB Emergency IO ON. \n");
		}

		if (gpio_in.Button_Emergency_Press == 1)
		{
			// Emergency button Press
		}

		if (gpio_in.Button_On_Press == 1)
		{
			// On button Press
		}

		if (gpio_in.Button_Off_Press == 1)
		{
			// Off button Press
		}

		if (gpio_in.Key_1_Press == 1)
		{
			// key 1 press
		}

		if (gpio_in.Key_2_Press == 1)
		{
			// key 2 press
		}

		if (gpio_in.Key_3_Press == 1)
		{
			// key 3 press
		}

		if (gpio_in.Key_4_Press == 1)
		{
			// key 4 press
		}
	}
}

// 5V 12V 24V 48V
void GetAuxPower()
{
	if (Query_Aux_PowerVoltage(Uart5Fd, Addr.Fan, &auxPower) == PASS)
	{
		ShmSysConfigAndInfo->SysInfo.AuxPower48V = auxPower.voltage[0];
		ShmSysConfigAndInfo->SysInfo.AuxPower24V = auxPower.voltage[1];
		//ShmSysConfigAndInfo->SysInfo.AuxPower12V = auxPower.voltage[4];
		//ShmSysConfigAndInfo->SysInfo.AuxPower5V = auxPower.voltage[6];
		// aux power voltage
		//PRINTF_FUNC("aux1 = %x, \n", auxPower.voltage[0]);
		//PRINTF_FUNC("aux2 = %x, \n", auxPower.voltage[1]);
	}
}

void SetFanModuleSpeed()
{
	{
		FanSpeed _fanSpeed;

		_setFanSpeed += fanSpeedSmoothValue;

		if (_setFanSpeed >= ShmFanModuleData->SetFan1Speed)
			_setFanSpeed = ShmFanModuleData->SetFan1Speed;

		//printf("_setFanSpeed = %d \n", _setFanSpeed);
		_fanSpeed.speed[0] = _setFanSpeed;

		_fanSpeed.speed[1] = _setFanSpeed;

		_fanSpeed.speed[2] = _setFanSpeed;

		_fanSpeed.speed[3] = _setFanSpeed;

		if (Config_Fan_Speed(Uart5Fd, Addr.Fan, &_fanSpeed) == PASS)
		{
			//PRINTF_FUNC("successfully Fan\n");
		}
	}
}

//==========================================
// Common Function
//==========================================
void SetK1K2RelayStatus(byte index)
{
	if (ShmPsuData->Work_Step >= _TEST_MODE && ShmPsuData->Work_Step <= _TEST_MODE)
	{
		if(regRelay.relay_event.bits.Gun1_N == NO)
			outputRelay.relay_event.bits.Gun1_N = YES;
		else if (regRelay.relay_event.bits.Gun1_P == NO)
			outputRelay.relay_event.bits.Gun1_P = YES;
		return;
	}

	if (_chargingData[index]->SystemStatus < SYS_MODE_PREPARE_FOR_EVSE ||
			_chargingData[index]->SystemStatus == SYS_MODE_FAULT ||
			_chargingData[index]->GroundFaultStatus == GFD_FAIL)
	{
		if (_chargingData[index]->Evboard_id == 0x01)
		{
			outputRelay.relay_event.bits.Gun1_P = NO;
			outputRelay.relay_event.bits.Gun1_N = NO;
		}
		else if (_chargingData[index]->Evboard_id == 0x02)
		{
			outputRelay.relay_event.bits.Gun2_P = NO;
			outputRelay.relay_event.bits.Gun2_N = NO;
		}
	}
	else if ((_chargingData[index]->SystemStatus >= SYS_MODE_PREPARE_FOR_EVSE &&
			_chargingData[index]->SystemStatus <= SYS_MODE_CHARGING))
	{
		//if (_chargingData[index]->RelayWeldingCheck == YES)
		{
			if (_chargingData[index]->Evboard_id == 0x01)
			{
				if(regRelay.relay_event.bits.Gun1_N == NO)
					outputRelay.relay_event.bits.Gun1_N = YES;
				else if (regRelay.relay_event.bits.Gun1_P == NO)
					outputRelay.relay_event.bits.Gun1_P = YES;
			}
			else if (_chargingData[index]->Evboard_id == 0x02)
			{
				if(regRelay.relay_event.bits.Gun2_N == NO)
					outputRelay.relay_event.bits.Gun2_N = YES;
				else if (regRelay.relay_event.bits.Gun2_P == NO)
					outputRelay.relay_event.bits.Gun2_P = YES;
			}
		}
	}
	else if (_chargingData[index]->SystemStatus >= SYS_MODE_TERMINATING &&
			_chargingData[index]->SystemStatus <= SYS_MODE_ALARM)
	{
		if ((_chargingData[index]->PresentChargingCurrent * 10) <= SEFETY_SWITCH_RELAY_CUR)
		{
			if (_chargingData[index]->Evboard_id == 0x01)
			{
				if(regRelay.relay_event.bits.Gun1_P == YES)
					outputRelay.relay_event.bits.Gun1_P = NO;
				else if (regRelay.relay_event.bits.Gun1_N == YES)
					outputRelay.relay_event.bits.Gun1_N = NO;
			}
			else if (_chargingData[index]->Evboard_id == 0x02)
			{
				if(regRelay.relay_event.bits.Gun2_P == YES)
					outputRelay.relay_event.bits.Gun2_P = NO;
				else if (regRelay.relay_event.bits.Gun2_N == YES)
					outputRelay.relay_event.bits.Gun2_N = NO;
			}
		}
	}
	else if (_chargingData[index]->SystemStatus == SYS_MODE_CCS_PRECHARGE_STEP0)
	{
//		if (_chargingData[index]->Evboard_id == 0x01)
//		{
//			if (_chargingData[index]->Type == _Type_CCS_2)
//			{
//				if (gunCount == 1)
//				{
//					if (regRelay.relay_event.bits.CCS_Precharge == NO)
//						outputRelay.relay_event.bits.CCS_Precharge = YES;
//					else if (regRelay.relay_event.bits.CCS_Precharge == YES)
//						outputRelay.relay_event.bits.Gun1_P = NO;
//				}
//			}
//		}
//		else if (_chargingData[index]->Evboard_id == 0x02)
//		{
//			if (_chargingData[index]->Type == _Type_CCS_2)
//			{
//				if (regRelay.relay_event.bits.CCS_Precharge == NO)
//					outputRelay.relay_event.bits.CCS_Precharge = YES;
//				else if (regRelay.relay_event.bits.CCS_Precharge == YES)
//					outputRelay.relay_event.bits.Gun2_P = NO;
//			}
//		}
	}
	else if (_chargingData[index]->SystemStatus == SYS_MODE_CCS_PRECHARGE_STEP1)
	{
//		if (_chargingData[index]->Evboard_id == 0x01)
//		{
//			if (_chargingData[index]->Type == _Type_CCS_2)
//			{
//				if (gunCount == 1)
//				{
//					if (regRelay.relay_event.bits.Gun1_P == NO)
//						outputRelay.relay_event.bits.Gun1_P = YES;
//					else if(regRelay.relay_event.bits.Gun1_P == YES)
//						outputRelay.relay_event.bits.CCS_Precharge = NO;
//				}
//			}
//		}
//		else if (_chargingData[index]->Evboard_id == 0x02)
//		{
//			if (_chargingData[index]->Type == _Type_CCS_2)
//			{
//				if (regRelay.relay_event.bits.Gun2_P == NO)
//					outputRelay.relay_event.bits.Gun2_P = YES;
//				else if(regRelay.relay_event.bits.Gun2_P == YES)
//					outputRelay.relay_event.bits.CCS_Precharge = NO;
//			}
//		}
	}
}

void SetParalleRelayStatus()
{
	// �������j��Ҿ��ءA�������|�W
	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 || !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)))
		{
			// ��l��~ ���f����

		}
		else
		{
			if (ShmSmartBoxData->ParallelRelayStatus[_RELAY_SWITCH_NAME_R3])
			{
				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;
			}
		}
	}
}

unsigned char DetectBitValue(int _value, unsigned char _bit)
{
	return ( _value & mask_table[_bit] ) != 0x00;
}

bool CheckAlarmOccur()
{
	bool isErr = false;
	for(byte count = 0; count < sizeof(mask_table)/sizeof(mask_table[0]); count++)
	{
		byte value = DetectBitValue(acAlarmCode.AcAlarmCode, count);
		if (value == 1)
		{
			isErr = true;
			switch(count)
			{
				case L1_AC_OVP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcSystemInputOVP = YES; break;
				case L1_AC_UVP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcSystemInputUVP = YES; break;
				case L1_AC_OCP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemAcOutputOCP = YES; break;
				case AC_OTP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemAmbientOTP = YES; break;
				case AC_GMI_FAULT: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcGroundfaultFail = YES; break;
				case AC_CP_ERROR: ShmStatusCodeData->InfoCode.InfoEvents.bits.PilotFault = YES; break;
				case AC_AC_LEAKAGE: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.RcdTrip = YES; break;
				case AC_DC_LEAKAGE: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.RcdTrip = YES; break;
				case AC_SYSTEM_SELFTEST_FAULT: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.McuSelftestFail = YES; break;
				case AC_HANDSHAKE_TIMEOUT: break;
				case AC_EMC_STOP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.EmergencyStopTrip = YES; break;
				case AC_RELAY_WELDING: ShmStatusCodeData->FaultCode.FaultEvents.bits.AcOutputRelayWelding = YES; break;
				case AC_LEAK_MODULE_FAULT: ShmStatusCodeData->FaultCode.FaultEvents.bits.RcdSelfTestFail = YES; break;
				case AC_SHUTTER_FAULT: ShmStatusCodeData->FaultCode.FaultEvents.bits.ShutterFault = YES; break;
				case AC_LOCKER_FAULT: ShmStatusCodeData->FaultCode.FaultEvents.bits.AcConnectorLockFail = YES; break;
				case AC_POWER_DROP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputDrop = YES; break;
				case L1_AC_CIRCUIT_SHORT: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CircuitShort = YES; break;
				case AC_ROTARY_SWITCH_FAULT: ShmStatusCodeData->FaultCode.FaultEvents.bits.RotarySwitchFault = YES; break;
				case AC_RELAY_DRIVE_FAULT: ShmStatusCodeData->FaultCode.FaultEvents.bits.AcOutputRelayDrivingFault = YES;break;
				case RESERVED_1: break;
				case L2_AC_OVP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcSystemInputOVP = YES; break;
				case L3_AC_OVP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcSystemInputOVP = YES; break;
				case L2_AC_UVP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcSystemInputUVP = YES; break;
				case L3_AC_UVP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcSystemInputUVP = YES; break;
				case L2_AC_OCP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemAcOutputOCP = YES; break;
				case L3_AC_OCP: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemAcOutputOCP = YES; break;
				case L2_AC_CIRCUIT_SHORT: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CircuitShort = YES; break;
				case L3_AC_CIRCUIT_SHORT: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CircuitShort = YES; break;
				case AC_METER_TIMEOUT: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MeterCommTimeout = YES; break;
				case AC_METER_IC_COMM_TIMEOUT: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MeterIcCommTimeout = YES; break;
				case AC_CP_NEGATIVE_ERR: ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PilotNegativeError = YES; break;
				case RESERVED_2: break;
			}
		}
	}

	if (!isErr)
	{
		if (ac_chargingInfo[0]->SystemStatus == SYS_MODE_IDLE ||
							ac_chargingInfo [0]->SystemStatus == SYS_MODE_MAINTAIN ||
							ac_chargingInfo [0]->SystemStatus == SYS_MODE_RESERVATION)
		{
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcSystemInputOVP = NO;
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcSystemInputUVP = NO;
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemAcOutputOCP = NO;
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemAmbientOTP = NO;
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcGroundfaultFail = NO;
			ShmStatusCodeData->InfoCode.InfoEvents.bits.PilotFault = NO;
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.RcdTrip = NO;
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.McuSelftestFail = NO;
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.EmergencyStopTrip = NO;
			ShmStatusCodeData->FaultCode.FaultEvents.bits.AcOutputRelayWelding = NO;
			ShmStatusCodeData->FaultCode.FaultEvents.bits.RcdSelfTestFail = NO;
			ShmStatusCodeData->FaultCode.FaultEvents.bits.ShutterFault = NO;
			ShmStatusCodeData->FaultCode.FaultEvents.bits.AcConnectorLockFail = NO;
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputDrop = NO;
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CircuitShort = NO;
			ShmStatusCodeData->FaultCode.FaultEvents.bits.RotarySwitchFault = NO;
			ShmStatusCodeData->FaultCode.FaultEvents.bits.AcOutputRelayDrivingFault = NO;
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MeterCommTimeout = NO;
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MeterIcCommTimeout = NO;
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PilotNegativeError = NO;
		}
	}

	ac_chargingInfo[0]->IsErrorOccur = isErr;
	return isErr;
}

bool IsNoneMatchLedColor()
{
	bool result = false;

	if (cur_led_color.Connect_1_Red != led_color.Connect_1_Red ||
		cur_led_color.Connect_1_Green != led_color.Connect_1_Green ||
		cur_led_color.Connect_1_Blue != led_color.Connect_1_Blue ||
		cur_led_color.Connect_2_Red != led_color.Connect_2_Red ||
		cur_led_color.Connect_2_Green != led_color.Connect_2_Green ||
		cur_led_color.Connect_2_Blue != led_color.Connect_2_Blue)
	{
		result = true;
	}

	return result;
}

void SetLedColor(struct ChargingInfoData *chargingData_1, struct ChargingInfoData *chargingData_2)
{
	byte _colorBuf = COLOR_MAX_LV * LED_INTENSITY_BRIGHTEST;

	if (ShmSysConfigAndInfo->SysConfig.LedInfo.Intensity == _LED_INTENSITY_DARKEST)
		_colorBuf = COLOR_MAX_LV * LED_INTENSITY_DARKEST;
	else if (ShmSysConfigAndInfo->SysConfig.LedInfo.Intensity == _LED_INTENSITY_MEDIUM)
		_colorBuf = COLOR_MAX_LV * LED_INTENSITY_MEDIUM;

	if (ShmSysConfigAndInfo->SysWarningInfo.Level == _ALARM_LEVEL_CRITICAL ||
			(chargingData_1->SystemStatus == SYS_MODE_UPDATE && chargingData_2->SystemStatus == SYS_MODE_UPDATE))
	{
		led_color.Connect_1_Green = COLOR_MIN_LV;
		led_color.Connect_1_Blue = COLOR_MIN_LV;
		led_color.Connect_1_Red = _colorBuf;
		led_color.Connect_2_Green = COLOR_MIN_LV;
		led_color.Connect_2_Blue = COLOR_MIN_LV;
		led_color.Connect_2_Red = _colorBuf;
	}
	else
	{
		if (ShmSysConfigAndInfo->SysInfo.IsAlternatvieConf)
		{
			if (ShmDcCommonData->_isPsuErrorOccur)
			{
				led_color.Connect_1_Green = COLOR_MIN_LV;
				led_color.Connect_1_Blue = COLOR_MIN_LV;
				led_color.Connect_1_Red = _colorBuf;
				led_color.Connect_2_Green = COLOR_MIN_LV;
				led_color.Connect_2_Blue = COLOR_MIN_LV;
				led_color.Connect_2_Red = _colorBuf;
			}
			else if ((chargingData_1->SystemStatus == SYS_MODE_BOOTING || chargingData_1->SystemStatus == SYS_MODE_IDLE || chargingData_1->SystemStatus == SYS_MODE_RESERVATION || chargingData_1->SystemStatus == SYS_MODE_MAINTAIN) &&
					(chargingData_2->SystemStatus == SYS_MODE_BOOTING || chargingData_2->SystemStatus == SYS_MODE_IDLE || chargingData_2->SystemStatus == SYS_MODE_RESERVATION || chargingData_2->SystemStatus == SYS_MODE_MAINTAIN))
			{
				led_color.Connect_1_Green = _colorBuf;
				led_color.Connect_1_Blue = COLOR_MIN_LV;
				led_color.Connect_1_Red = COLOR_MIN_LV;
				led_color.Connect_2_Green = _colorBuf;
				led_color.Connect_2_Blue = COLOR_MIN_LV;
				led_color.Connect_2_Red = COLOR_MIN_LV;

				if (chargingData_1->SystemStatus == SYS_MODE_RESERVATION ||
						chargingData_2->SystemStatus == SYS_MODE_RESERVATION)
				{
					if (GetTimeoutValue(&_led_blink_time) > 3)
					{
						led_color.Connect_1_Green = COLOR_MIN_LV;
						led_color.Connect_2_Green = COLOR_MIN_LV;
					}
				}
				else if (chargingData_1->SystemStatus == SYS_MODE_MAINTAIN ||
						chargingData_2->SystemStatus == SYS_MODE_MAINTAIN)
				{
					led_color.Connect_1_Green = COLOR_MIN_LV;
					led_color.Connect_2_Green = COLOR_MIN_LV;
					led_color.Connect_1_Red = _colorBuf;
					led_color.Connect_2_Red = _colorBuf;
				}
			}
			else if ((chargingData_1->SystemStatus >= SYS_MODE_AUTHORIZING && chargingData_1->SystemStatus <= SYS_MODE_COMPLETE) ||
				     	(chargingData_1->SystemStatus >= SYS_MODE_CCS_PRECHARGE_STEP0 && chargingData_1->SystemStatus <= SYS_MODE_CCS_PRECHARGE_STEP1) ||
						(chargingData_2->SystemStatus >= SYS_MODE_AUTHORIZING && chargingData_2->SystemStatus <= SYS_MODE_COMPLETE) ||
						(chargingData_2->SystemStatus >= SYS_MODE_CCS_PRECHARGE_STEP0 && chargingData_2->SystemStatus <= SYS_MODE_CCS_PRECHARGE_STEP1))
			{
				led_color.Connect_1_Green = COLOR_MIN_LV;
				led_color.Connect_1_Blue = _colorBuf;
				led_color.Connect_1_Red = COLOR_MIN_LV;
				led_color.Connect_2_Green = COLOR_MIN_LV;
				led_color.Connect_2_Blue = _colorBuf;
				led_color.Connect_2_Red = COLOR_MIN_LV;
			}
		}
		else
		{
			if (ShmDcCommonData->_isPsuErrorOccur)
			{
				if (chargingData_1->SystemStatus == SYS_MODE_BOOTING ||
						chargingData_1->SystemStatus == SYS_MODE_IDLE ||
						chargingData_1->SystemStatus == SYS_MODE_RESERVATION ||
						chargingData_1->SystemStatus == SYS_MODE_MAINTAIN)
				{
					led_color.Connect_1_Green = COLOR_MIN_LV;
					led_color.Connect_1_Blue = COLOR_MIN_LV;
					led_color.Connect_1_Red = _colorBuf;
				}
			}
			else if (chargingData_1->SystemStatus == SYS_MODE_BOOTING ||
					chargingData_1->SystemStatus == SYS_MODE_IDLE ||
					chargingData_1->SystemStatus == SYS_MODE_RESERVATION ||
					chargingData_1->SystemStatus == SYS_MODE_MAINTAIN)
			{
				led_color.Connect_1_Green = _colorBuf;
				led_color.Connect_1_Blue = COLOR_MIN_LV;
				led_color.Connect_1_Red = COLOR_MIN_LV;

				if (chargingData_1->SystemStatus == SYS_MODE_RESERVATION)
				{
					if (GetTimeoutValue(&_led_blink_time) > 3)
					{
						led_color.Connect_1_Green = COLOR_MIN_LV;
					}
				}
				else if (chargingData_1->SystemStatus == SYS_MODE_MAINTAIN)
				{
					led_color.Connect_1_Green = COLOR_MIN_LV;
					led_color.Connect_1_Red = _colorBuf;
				}
			}
			else if ((chargingData_1->SystemStatus >= SYS_MODE_AUTHORIZING && chargingData_1->SystemStatus <= SYS_MODE_COMPLETE) ||
						(chargingData_1->SystemStatus >= SYS_MODE_CCS_PRECHARGE_STEP0 && chargingData_1->SystemStatus <= SYS_MODE_CCS_PRECHARGE_STEP1))
			{
				led_color.Connect_1_Green = COLOR_MIN_LV;
				led_color.Connect_1_Blue = _colorBuf;
				led_color.Connect_1_Red = COLOR_MIN_LV;
			}

			// --------------------------------------------------------------------------
			if (ShmDcCommonData->_isPsuErrorOccur)
			{
				if (chargingData_2->SystemStatus == SYS_MODE_BOOTING ||
						chargingData_2->SystemStatus == SYS_MODE_IDLE ||
						chargingData_2->SystemStatus == SYS_MODE_RESERVATION ||
						chargingData_2->SystemStatus == SYS_MODE_MAINTAIN)
				{
					led_color.Connect_2_Green = COLOR_MIN_LV;
					led_color.Connect_2_Blue = COLOR_MIN_LV;
					led_color.Connect_2_Red = _colorBuf;
				}
			}
			else if (chargingData_2->SystemStatus == SYS_MODE_BOOTING ||
					chargingData_2->SystemStatus == SYS_MODE_IDLE ||
					chargingData_2->SystemStatus == SYS_MODE_RESERVATION ||
					chargingData_2->SystemStatus == SYS_MODE_MAINTAIN)
			{
				led_color.Connect_2_Green = _colorBuf;
				led_color.Connect_2_Blue = COLOR_MIN_LV;
				led_color.Connect_2_Red = COLOR_MIN_LV;

				if (chargingData_2->SystemStatus == SYS_MODE_RESERVATION)
				{
					if (GetTimeoutValue(&_led_blink_time) > 3)
					{
						led_color.Connect_2_Green = COLOR_MIN_LV;
					}
				}
				else if (chargingData_2->SystemStatus == SYS_MODE_MAINTAIN)
				{
					led_color.Connect_2_Green = COLOR_MIN_LV;
					led_color.Connect_2_Red = _colorBuf;
				}
			}
			else if ((chargingData_2->SystemStatus >= SYS_MODE_AUTHORIZING && chargingData_2->SystemStatus <= SYS_MODE_COMPLETE) ||
						(chargingData_2->SystemStatus >= SYS_MODE_CCS_PRECHARGE_STEP0 && chargingData_2->SystemStatus <= SYS_MODE_CCS_PRECHARGE_STEP1))
			{
				led_color.Connect_2_Green = COLOR_MIN_LV;
				led_color.Connect_2_Blue = _colorBuf;
				led_color.Connect_2_Red = COLOR_MIN_LV;
			}
		}
	}

	if (_checkLedChanged > 0)
	{
		if (Config_Led_Color(Uart5Fd, Addr.Led, &led_color) == PASS)
		{
			_checkLedChanged--;

			cur_led_color.Connect_1_Red 	= led_color.Connect_1_Red;
			cur_led_color.Connect_1_Green 	= led_color.Connect_1_Green;
			cur_led_color.Connect_1_Blue 	= led_color.Connect_1_Blue;
			cur_led_color.Connect_2_Red 	= led_color.Connect_2_Red;
			cur_led_color.Connect_2_Green	= led_color.Connect_2_Green;
			cur_led_color.Connect_2_Blue 	= led_color.Connect_2_Blue;
		}
	}
	else if (IsNoneMatchLedColor())
		_checkLedChanged = 5;
}
//==========================================
// Init all share memory
//==========================================
int InitShareMemory()
{
	int result = PASS;
	int MeterSMId;

	if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo),  0777)) < 0)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("shmget ShmSysConfigAndInfo NG\n");
		#endif
		result = FAIL;
	}
	else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("[shmat ShmSysConfigAndInfo NG\n");
		#endif
		result = FAIL;
	}

	if ((MeterSMId = shmget(ShmStatusCodeKey, sizeof(struct StatusCodeData),  0777)) < 0)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("shmget ShmStatusCodeData 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;
	}

	if(CCS_QUANTITY > 0)
	{
		if ((MeterSMId = shmget(ShmCcsCommKey, sizeof(struct CcsData),	IPC_CREAT | 0777)) < 0)
	   	{
	   		#ifdef SystemLogMessage
	   		DEBUG_ERROR("shmget ShmCcsData NG \n");
	   		#endif
	   		return FAIL;
	   	}
	   	else if ((ShmCcsData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
	    {
	   		#ifdef SystemLogMessage
	   		  	DEBUG_ERROR("shmat ShmCcsData NG \n");
	   		#endif
	   		return FAIL;
	   	}
	}

	if ((MeterSMId = shmget(ShmFanBdKey, sizeof(struct FanModuleData),  0777)) < 0)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("shmget ShmFanModuleData NG\n");
		#endif
		result = FAIL;
	}
	else if ((ShmFanModuleData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("shmat ShmFanModuleData NG\n");
		#endif
		result = FAIL;
	}

	if ((MeterSMId = shmget(ShmRelayBdKey, sizeof(struct RelayModuleData),  0777)) < 0)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("shmget ShmRelayModuleData NG\n");
		#endif
		result = FAIL;
	}
	else if ((ShmRelayModuleData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("shmat ShmRelayModuleData NG\n");
		#endif
		result = FAIL;
	}

	if ((MeterSMId = shmget(ShmLedBdKey, sizeof(struct LedModuleData),  0777)) < 0)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("shmget ShmLedModuleData NG\n");
		#endif
		result = FAIL;
	}
	else if ((ShmLedModuleData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("shmat ShmLedModuleData NG\n");
		#endif
		result = FAIL;
	}

	if ((MeterSMId = shmget(ShmPsuKey, sizeof(struct PsuData),  0777)) < 0)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("shmget ShmPsuData 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(ShmOcppModuleKey, sizeof(struct OCPP16Data), 0777)) < 0)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("shmat ShmOCPP16Data NG \n");
		#endif
		result = FAIL;
	}
	else if ((ShmOCPP16Data = shmat(MeterSMId, NULL, 0)) == (void *) -1)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("shmat ShmOCPP16Data NG \n");
		#endif
		result = FAIL;
	}

	if ((MeterSMId = shmget(ShmOcpp20ModuleKey, sizeof(struct OCPP20Data), IPC_CREAT | 0777)) < 0)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("shmat ShmOCPP20Data NG \n");
		#endif
		result = FAIL;
	}
	else if ((ShmOCPP20Data = shmat(MeterSMId, NULL, 0)) == (void *) -1)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("shmat ShmOCPP20Data NG \n");
		#endif
		result = FAIL;
	}

	if ((MeterSMId = shmget(ShmPrimaryMcuKey, sizeof(struct PrimaryMcuData), 0777)) < 0)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("shmget ShmPrimaryMcuData NG\n");
		#endif
		result = FAIL;
	}
	else if ((ShmPrimaryMcuData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
	{
		#ifdef ShmPrimaryMcuData
		DEBUG_ERROR("shmat ShmPrimaryMcuData 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
   		return 0;
   	}
   	else if ((ShmDcCommonData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
   	{
   		#ifdef SystemLogMessage
   		DEBUG_ERROR("shmat ShmCommonKey NG \n");
   		#endif
   		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;
}

int InitComPort()
{
	int fd;
	struct termios tios;

	fd = open(relayRs485PortName, O_RDWR);
	if(fd <= 0)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("Module_InternalComm. InitComPort NG\n");
		#endif
		if(ShmStatusCodeData!=NULL)
		{
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CsuInitFailed = 1;
		}
		sleep(5);
		return -1;
	}
	ioctl (fd, TCGETS, &tios);
	tios.c_cflag = B115200 | CS8 | CLOCAL | CREAD;
	tios.c_lflag = 0;
	tios.c_iflag = 0;
	tios.c_oflag = 0;
	tios.c_cc[VMIN]=0;
	tios.c_cc[VTIME]=(byte)0;		// timeout 0.5 second
	tios.c_lflag=0;
	tcflush(fd, TCIFLUSH);
	ioctl (fd, TCSETS, &tios);

	return fd;
}

//================================================
// Main process
//================================================
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;
}

bool FindAcChargingInfoData(byte target, struct ChargingInfoData **acChargingData)
{
	if (target < AC_QUANTITY)
	{
		acChargingData[target] = &ShmSysConfigAndInfo->SysInfo.AcChargingData[target];
		return true;
	}

	return false;
}

void Initialization()
{
	bool isPass = false;

	isAcModuleInitComp = false;
	for (byte index = 0; index < ARRAY_SIZE(outputRelay.relay_event.relay_status); index++)
	{
		outputRelay.relay_event.relay_status[index] = 0x00;
	}

	while(!isPass)
	{
		isPass = true;
		for (byte _index = 0; _index < gunCount; _index++)
		{
			if (!FindChargingInfoData(_index, &_chargingData[0]))
			{
				DEBUG_ERROR("InternalComm : FindChargingInfoData false (%d) \n", gunCount);
				isPass = false;
				break;
			}
		}

		sleep(1);
	}

	isPass = false;

	if (acgunCount > 0)
	{
		while(!isPass)
		{
			isPass = true;
			for (byte _index = 0; _index < acgunCount; _index++)
			{
				if (!FindAcChargingInfoData(_index, &ac_chargingInfo[0]))
				{
					DEBUG_ERROR("EvComm : FindAcChargingInfoData false \n");
					isPass = false;
					break;
				}
			}

			sleep(1);
		}
	}
}

void StartCheckRelayInfo(byte _chkIndex, byte toState)
{
	if (ShmDcCommonData->RelayCheckStatus[_chkIndex] == STOP)
	{
		GetTimespecFunc(&_relayStateChkTimer[_chkIndex]);
		ShmDcCommonData->RelayCheckStatus[_chkIndex] = START;
	}
	else
	{
		int _timebuf = GetTimeoutValue(&_relayStateChkTimer[_chkIndex]);

		if (_timebuf < 0)
			GetTimespecFunc(&_relayStateChkTimer[_chkIndex]);
		else
		{
			if (_timebuf > RELAY_CHECK_TIME)
			{
				//PRINTF_FUNC ("relay welding or driving fault = %d \n", _chkIndex);
				if (toState == 1)
					ShmDcCommonData->RelayCheckStatus[_chkIndex] = RELAY_STATUS_ERROR_DRIVING;
				else
					ShmDcCommonData->RelayCheckStatus[_chkIndex] = RELAY_STATUS_ERROR_WELDING;
			}
		}
	}
}

void StopCheckRelayInfo(byte _chkIndex)
{
	if (ShmDcCommonData->RelayCheckStatus[_chkIndex] != STOP)
	{
		ShmDcCommonData->RelayCheckStatus[_chkIndex] = STOP;
	}
}

bool IsNoneMatchRelayStatus()
{
	bool result = false;

	if ((regRelay.relay_event.bits.AC_Contactor != outputRelay.relay_event.bits.AC_Contactor) ||
		(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.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;
	}

	if (regRelay.relay_event.bits.AC_Contactor != outputRelay.relay_event.bits.AC_Contactor)
	{
		//PRINTF_FUNC("AC Contact Relay none match, try to switch to %d \n", outputRelay.relay_event.bits.AC_Contactor);
	}

	if (regRelay.relay_event.bits.Gun1_P != outputRelay.relay_event.bits.Gun1_P)
	{
		StartCheckRelayInfo(RELAY_SMR1_P_STATUS, outputRelay.relay_event.bits.Gun1_P);
		//PRINTF_FUNC("SMR1:D+ Relay none match, try to switch to %d \n", outputRelay.relay_event.bits.Gun1_P);
	}
	else
	{
		StopCheckRelayInfo(RELAY_SMR1_P_STATUS);
		//PRINTF_FUNC("SMR1:D+ Release %d \n");
	}

	if (regRelay.relay_event.bits.Gun1_N != outputRelay.relay_event.bits.Gun1_N)
	{
		StartCheckRelayInfo(RELAY_SMR1_N_STATUS, outputRelay.relay_event.bits.Gun1_N);
		//PRINTF_FUNC("SMR1:D- Relay none match, try to switch to %d \n", outputRelay.relay_event.bits.Gun1_N);
	}
	else
	{
		StopCheckRelayInfo(RELAY_SMR1_N_STATUS);
	}

	if (regRelay.relay_event.bits.Gun2_P != outputRelay.relay_event.bits.Gun2_P)
	{
		StartCheckRelayInfo(RELAY_SMR2_P_STATUS, outputRelay.relay_event.bits.Gun2_P);
		//PRINTF_FUNC("SMR2:D+ Relay none match, try to switch to %d \n", outputRelay.relay_event.bits.Gun2_P);
	}
	else
	{
		StopCheckRelayInfo(RELAY_SMR2_P_STATUS);
	}

	if (regRelay.relay_event.bits.Gun2_N != outputRelay.relay_event.bits.Gun2_N)
	{
		StartCheckRelayInfo(RELAY_SMR2_N_STATUS, outputRelay.relay_event.bits.Gun2_N);
		//PRINTF_FUNC("SMR2:D- Relay none match, try to switch to %d \n", outputRelay.relay_event.bits.Gun2_N);
	}
	else
	{
		StopCheckRelayInfo(RELAY_SMR2_N_STATUS);
	}

	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.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
	{
		StopCheckRelayInfo(RELAY_PARA_P_STATUS);
	}

	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.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
	{
		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;
}

void MatchRelayStatus()
{
	// �]�� AC Contactor �S�� Feedback�A�ҥH�Ȯɥ��o�˳B�z
	//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.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.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()
{
	if (ShmRelayModuleData->Gun1FuseOutputVolt > 0 && ShmRelayModuleData->Gun1RelayOutputVolt > 0 &&
			(ShmRelayModuleData->Gun1FuseOutputVolt == ShmRelayModuleData->Gun1RelayOutputVolt))
	{
		// Relay �e��q���@�P
		_chargingData[0]->RelayK1K2Status = 0x01;
	}
	else
		_chargingData[0]->RelayK1K2Status = 0x00;

	if (ShmRelayModuleData->Gun2FuseOutputVolt > 0 && ShmRelayModuleData->Gun2RelayOutputVolt > 0 &&
				(ShmRelayModuleData->Gun2FuseOutputVolt == ShmRelayModuleData->Gun2RelayOutputVolt))
	{
		// Relay �e��q���@�P
		_chargingData[1]->RelayK1K2Status = 0x01;
	}
	else
		_chargingData[1]->RelayK1K2Status = 0x00;
}

void SetGfdConfig(byte index, byte resister)
{
	gfd_config.index = index;
	gfd_config.state = resister;

	//PRINTF_FUNC("************************GFD Vol = %d, GFD Res = %d \n", gfd_config.reqVol, gfd_config.resister);
	if (Config_Gfd_Value(Uart5Fd, Addr.Relay, &gfd_config) == PASS)
	{
//		PRINTF_FUNC("Set reqVol = %f, resister = %d \n",
//				gfd_config.reqVol,
//				gfd_config.resister);
	}
}

//===============================================
// Common Detect Chk - CCS
//===============================================
byte isPrechargeStatus_ccs(byte gunIndex)
{
	byte result = 0x00;

	if (ShmCcsData->CommProtocol == _CCS_COMM_V2GMessage_DIN70121)
	{
		result = ShmCcsData->V2GMessage_DIN70121[_chargingData[gunIndex]->type_index].PresentMsgFlowStatus;
	}

	return result;
}

void CableCheckDetected(byte index)
{
	// Cable Check
	// �����u�W���q�� = ���ݭn�D���q���q�y
	// _chargingData[targetGun]->EvBatterytargetVoltage
	// �D�n���Ҫ��Ȭ� 100 �P 500 ���p�� 100 * 950 �ɡA�� Alarm�A���� 100 * 950 �P 500 * 950 �ɬ� Warning
	// 950 ���t�γ̤j�q��
	// Alarm : Rgfd <= 95K
	// Warning : 95K < Rgfd <= 475
	// Normal : Rgfd > 475K
	if ((_chargingData[index]->Type >= _Type_Chademo && _chargingData[index]->Type <= _Type_GB) ||
			(_chargingData[index]->Type == 0x09 && ShmSysConfigAndInfo->SysConfig.AlwaysGfdFlag))
	{
		if ((_chargingData[index]->SystemStatus >= SYS_MODE_PREPARE_FOR_EVSE && _chargingData[index]->SystemStatus < SYS_MODE_TERMINATING) ||
			(_chargingData[index]->SystemStatus >= SYS_MODE_CCS_PRECHARGE_STEP0 && _chargingData[index]->SystemStatus <= SYS_MODE_CCS_PRECHARGE_STEP1))
		{
			if (_chargingData[index]->SystemStatus == SYS_MODE_PREPARE_FOR_EVSE)
			{
				SetGfdConfig(index, GFD_CABLECHK);
			}
			else if (_chargingData[index]->SystemStatus >= SYS_MODE_CCS_PRECHARGE_STEP0 &&
					_chargingData[index]->SystemStatus <= SYS_MODE_CCS_PRECHARGE_STEP1 &&
					_chargingData[index]->PresentChargingVoltage >= CCS_PRECHARGE_VOL &&
					isPrechargeStatus_ccs(index) >= CCS_PRECHARGE_STARTU)
			{
				SetGfdConfig(index, GFD_PRECHARGE);
			}
			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)
					SetGfdConfig(index, GFD_IDLE);
				else
					SetGfdConfig(index, GFD_CHARGING);
			}
		}
		else
		{
			SetGfdConfig(index, GFD_IDLE);
		}
	}
}

void CheckOutputPowerOverCarReq(byte index)
{
	float fireV = _chargingData[index]->FireChargingVoltage;
	float carV = _chargingData[index]->EvBatteryMaxVoltage * 10 > _chargingData[index]->ConnectorMaxVoltage ?
			_chargingData[index]->ConnectorMaxVoltage : _chargingData[index]->EvBatteryMaxVoltage * 10;

	if ((_chargingData[index]->EvBatterytargetVoltage * 10) > 1500 &&
			(_chargingData[index]->Type == _Type_Chademo ||
				_chargingData[index]->Type == _Type_CCS ||
				_chargingData[index]->Type == _Type_GB))
	{
		if (fireV >= (carV + (carV * 0.02)))
		{
			if (!_isOvpChkTimeFlag[index])
			{
				if ((_chargingData[index]->PresentChargingVoltage * 10) >= VOUT_MIN_VOLTAGE * 10)
				{
					GetTimespecMFunc(&_checkOutputVolProtectTimer[index]);
					_isOvpChkTimeFlag[index] = YES;
					PRINTF_FUNC("First time : CheckOutputPowerOverCarReq NG : fire = %f, req = %f, max-battery = %f \n",
							_chargingData[index]->FireChargingVoltage, (_chargingData[index]->EvBatterytargetVoltage * 10), carV);
				}
			}
			else
			{
				int _timebuf = GetTimeoutMValue(&_checkOutputVolProtectTimer[index]);

				if (_timebuf < 0)
					GetTimespecMFunc(&_checkOutputVolProtectTimer[index]);
				else
				{
					if (GetTimeoutMValue(&_checkOutputVolProtectTimer[index]) >= OUTPUT_VOL_CHK_TIME)
					{
						PRINTF_FUNC("[Module_InternalComm]CheckOutputPowerOverCarReq NG : fire = %f, req = %f, max-battery = %f \n",
								_chargingData[index]->FireChargingVoltage, (_chargingData[index]->EvBatterytargetVoltage * 10), carV);
						DEBUG_ERROR("[Module_InternalComm]CheckOutputPowerOverCarReq NG : fire = %f, req = %f, max-battery = %f \n",
								_chargingData[index]->FireChargingVoltage, (_chargingData[index]->EvBatterytargetVoltage * 10), carV);

						if (_chargingData[index]->Type == _Type_Chademo)
						{
							ShmDcCommonData->ConnectErrList[index].GunBits.ChaConnectOVP = YES;
							if (strncmp((char *)_chargingData[index]->ConnectorAlarmCode, "", 6) == EQUAL)
								memcpy(_chargingData[index]->ConnectorAlarmCode, "012217", 6);
						}
						else if (_chargingData[index]->Type == _Type_CCS)
						{
							ShmDcCommonData->ConnectErrList[index].GunBits.CCSConnectOVP = YES;
							if (strncmp((char *)_chargingData[index]->ConnectorAlarmCode, "", 6) == EQUAL)
								memcpy(_chargingData[index]->ConnectorAlarmCode, "012219", 6);
						}
						else if (_chargingData[index]->Type == _Type_GB)
						{
							ShmDcCommonData->ConnectErrList[index].GunBits.GBTConnectOVP = YES;
							if (strncmp((char *)_chargingData[index]->ConnectorAlarmCode, "", 6) == EQUAL)
								memcpy(_chargingData[index]->ConnectorAlarmCode, "012221", 6);
						}

						_chargingData[index]->StopChargeFlag = YES;
					}
				}
			}
		}
		else
			_isOvpChkTimeFlag[index] = NO;
	}
}

void CheckOutputVolNoneMatchFire(byte index)
{
	if (((_chargingData[index]->EvBatterytargetVoltage * 10) > 1500 ||
			_chargingData[index]->RelayK1K2Status == NO) &&
			(_chargingData[index]->Type == _Type_CCS))
	{
		if (((_chargingData[index]->PresentChargingVoltage * 10) < _chargingData[index]->FireChargingVoltage - 300) ||
				((_chargingData[index]->PresentChargingVoltage * 10) > _chargingData[index]->FireChargingVoltage + 300))
		{
			if (!_isOutputNoneMatch[index])
			{
				_isOutputNoneMatch[index] = YES;
				GetTimespecFunc(&_checkOutputNoneMatchTimer[index]);
			}
			else
			{
				if (GetTimeoutValue(&_checkOutputNoneMatchTimer[index]) >= 2)
				{
					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 == 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 == GUN_RIGHT)
					{
						ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AbnormalVoltageOnOutputLine_2 = YES;
						if (strncmp((char *)_chargingData[index]->ConnectorAlarmCode, "", 6) == EQUAL)
								memcpy(_chargingData[index]->ConnectorAlarmCode, "012325", 6);
					}

					_chargingData[index]->StopChargeFlag = YES;
				}
			}
		}
		else
			_isOutputNoneMatch[index] = NO;
	}
}

void GetPsuTempForFanSpeed()
{
	char temp = 0;

	for (byte index = 0; index < ShmPsuData->GroupCount; index++)
	{
		for (byte count = 0; count < ShmPsuData->PsuGroup[index].GroupPresentPsuQuantity; count++)
		{
			if (temp < ShmPsuData->PsuGroup[index].PsuModule[count].ExletTemp)
				temp = ShmPsuData->PsuGroup[index].PsuModule[count].ExletTemp;
		}
	}

	ShmSysConfigAndInfo->SysInfo.SystemAmbientTemp = temp;

	if (ShmSysConfigAndInfo->SysConfig.SwitchDebugFlag == NO)
	{
		if (ShmFanModuleData->TestFanSpeed == NORMAL_FAN_SPEED)
		{
			if (temp >= ENV_TEMP_MAX)
				ShmFanModuleData->TestFanSpeed = MAX_FAN_SPEED;
		}
		else if (ShmFanModuleData->TestFanSpeed == MAX_FAN_SPEED)
		{
			if (temp <= ENV_TEMP_MIN)
				ShmFanModuleData->TestFanSpeed = NORMAL_FAN_SPEED;
		}
		else
			ShmFanModuleData->TestFanSpeed = NORMAL_FAN_SPEED;
	}
}

void GetFanSpeedByFunction()
{
	// �����ק� :
	// ******************************************************* //
	//
	//       ���ePSU��X�` KW       PSU Temp
	// 50 x -------------------- x ---------- + 0.5 x (PSU Temp - 70)
	//       ���e�γ̤j�\�v KW         50
	//
	// ******************************************************* //

	// ���e�γ̤j�\�v KW : ShmPsuData->SystemAvailablePower
	unsigned int _maxPower = ShmPsuData->SystemAvailablePower;
	// ���ePSU��X�` KW & PSU Temp :
	unsigned char temp = 0;
	float power = 0;

	for (byte index = 0; index < ShmPsuData->GroupCount; index++)
	{
		for (byte count = 0; count < ShmPsuData->PsuGroup[index].GroupPresentPsuQuantity; count++)
		{
			if (temp < ShmPsuData->PsuGroup[index].PsuModule[count].ExletTemp)
				temp = ShmPsuData->PsuGroup[index].PsuModule[count].ExletTemp;
		}
	}

	for (byte gunIndex = 0; gunIndex < gunCount; gunIndex++)
	{
		power += (_chargingData[gunIndex]->PresentChargingPower * 10);
	}

	double _pw_rate = 0;
	if (_maxPower > 0)
		_pw_rate = power / (double)_maxPower;
	double _temp_rate = 0;
	if (temp > 0)
		_temp_rate = (double)temp / 50;
	unsigned char _temp_diff = 0;
	if (temp > 70)
		_temp_diff = temp - 70;

	// debug mode �����L�X��T�����}
	if (ShmSysConfigAndInfo->SysConfig.SwitchDebugFlag == YES)
	{
//		printf("Fan Speed Information: power = %f, _maxPower = %d, temp = %d -- _pw_rate = %f, _temp_rate = %f, _temp_diff = %d \n",
//				power, _maxPower, temp, _pw_rate, _temp_rate, _temp_diff);
		return;
	}

	ShmFanModuleData->TestFanSpeed = (((50 * _pw_rate * _temp_rate) + (0.5 * _temp_diff)) / 100) * MAX_FAN_SPEED;
	// ��W 50KW �t��~ �u�୭�� 3000 ���X
	if (ShmSysConfigAndInfo->SysInfo.ChargerType == _CHARGER_TYPE_JARI)
	{
		if (is50kwSystem)
		{
			// 50KW �t�ΡA�ϥ� 14000 �୷��
			// �p�G��X�j�� 2.5KW
			if (ShmFanModuleData->TestFanSpeed > 5000 ||
					power >= 25)
				ShmFanModuleData->TestFanSpeed = 5000;
		}
		else
		{
			// ��W��L�t�ΡA�ϥ� 4400 �୷��
			if (ShmFanModuleData->TestFanSpeed > 9545)
				ShmFanModuleData->TestFanSpeed = 9545;
		}
	}

	if (ShmFanModuleData->TestFanSpeed > MAX_FAN_SPEED)
		ShmFanModuleData->TestFanSpeed = MAX_FAN_SPEED;

	if (ShmFanModuleData->TestFanSpeed < 0)
			ShmFanModuleData->TestFanSpeed = 0;

// -----------------------------------------------------------------------
//	printf("power = %f \n", power);
//	printf("_maxPower = %d \n", _maxPower);
//	printf("temp = %d \n", temp);
//
//	printf("_pw_rate = %f \n", _pw_rate);
//	printf("_temp_rate = %f \n", _temp_rate);
//	printf("_temp_diff = %d \n", _temp_diff);
//	printf("fan rate = %f \n", (30 * _pw_rate * _temp_rate + 14 * _temp_diff));
//	printf("ShmFanModuleData->TestFanSpeed = %d \n", ShmFanModuleData->TestFanSpeed);
}

bool GetAcStatus()
{
	bool isPass = false;
	if (Query_AC_Status(Uart5Fd, Addr.AcPlug, &acStatus) == PASS)
	{
		if (acStatus.CpStatus != AC_SYS_NONE)
		{
			ShmSysConfigAndInfo->SysConfig.AcRatingCurrent = (unsigned short)acStatus.MaxCurrent;

			//if(ShmSysConfigAndInfo->SysConfig.AcMaxChargingCurrent == 0)
			//ShmSysConfigAndInfo->SysConfig.AcMaxChargingCurrent = ShmSysConfigAndInfo->SysConfig.AcRatingCurrent;
			AcChargingRatingCurrent = ShmSysConfigAndInfo->SysConfig.AcRatingCurrent;

			ac_chargingInfo[0]->ConnectorPlugIn = acStatus.CpStatus;
			ShmSysConfigAndInfo->SysInfo.AcChargingData[0].PilotState = acStatus.CpStatus;
			isPass = true;
		}

//		if (acStatus.CpStatus == AC_SYS_F)
//		{
//			printf("PilotVol_P = %d \n", acStatus.PilotVol_P);
//			printf("PilotVol_N = %d \n", acStatus.PilotVol_N);
//		}
//		PRINTF_FUNC("CpStatus = %d \n", acStatus.CpStatus);
//					printf("CurLimit = %d \n", acStatus.CurLimit);
//					printf("PilotVol_P = %d \n", acStatus.PilotVol_P);
//					printf("PilotVol_N = %d \n", acStatus.PilotVol_N);
//					printf("LockStatus = %d \n", acStatus.LockStatus);
//					printf("RelayStatus = %d \n", acStatus.RelayStatus);
//					printf("ShutterStatus = %d \n", acStatus.ShutterStatus);
//					printf("MeterStatus = %d \n", acStatus.MeterStatus);
//					printf("PpStatus = %d \n", acStatus.PpStatus);
//					printf("MaxCurrent = %d \n", acStatus.MaxCurrent);
//					printf("RotateSwitchStatus = %d \n", acStatus.RelayStatus);
//					printf("============================== \n");

					//ac_chargingInfo[0]->SystemStatus = acStatus.CpStatus;
	}
//	else
//		PRINTF_FUNC("GetAcStatus return fail. \n");
	return isPass;
}

void GetAcAlarmCode()
{
	if (Query_AC_Alarm_Code(Uart5Fd, Addr.AcPlug, &acAlarmCode) == PASS)
	{
		ocpp_ac_clear_errorCode_cmd(CheckAlarmOccur());
	}
}

unsigned char GetChargingEnergy()
{
	return Query_Charging_Energy(Uart5Fd, Addr.AcPlug, &acChargingEnergy);
}

unsigned char GetAcChargingVoltage()
{
	return Query_Present_InputVoltage(Uart5Fd, Addr.AcPlug, &acChargingVoltage);
}

unsigned char GetAcChargingCurrent()
{
	return Query_Charging_Current(Uart5Fd, Addr.AcPlug, &acChargingCurrent);
}

void ChangeLedStatus()
{
	if (ac_chargingInfo[0]->SystemStatus == SYS_MODE_IDLE)
		ledStatus.ActionMode = 1;
	else if (ac_chargingInfo[0]->SystemStatus == SYS_MODE_PREPARING)
		ledStatus.ActionMode = 3;
	else if (ac_chargingInfo[0]->SystemStatus == SYS_MODE_CHARGING)
		ledStatus.ActionMode = 4;

	Config_LED_Status(Uart5Fd, Addr.AcPlug, &ledStatus);
}

void SetLegacyReq(byte _switch)
{
	if (Config_Legacy_Req(Uart5Fd, Addr.AcPlug, _switch))
	{
		PRINTF_FUNC("SetLegacyReq Pass. \n");
	}
	else
	{
		PRINTF_FUNC("SetLegacyReq Fail. \n");
	}
}

void SetCpDuty(byte _value)
{
	if (_ac_duty != _value)
	{
		_ac_duty = _value;
		PRINTF_FUNC("********Duty : %d \n", _ac_duty);
	}

	Config_Ac_Duty(Uart5Fd, Addr.AcPlug, _value);
}

void ResetMcuReqAC()
{
	Config_Reset_MCU(Uart5Fd, Addr.AcPlug);
}

void SetModelName_AC()
{
	if (Config_Model_Name(Uart5Fd, Addr.AcPlug, ShmSysConfigAndInfo->SysConfig.ModelName) == PASS)
	{
		PRINTF_FUNC("Set Model name (AC) PASS = %s \n", ShmSysConfigAndInfo->SysConfig.ModelName);
	}
}

void ChangeToCsuMode()
{
	ac_chargingInfo[0]->IsModeChagned = Config_CSU_Mode(Uart5Fd, Addr.AcPlug);

//	if (ac_chargingInfo[0]->IsModeChagned == PASS)
//	{
//		Config_Reset_MCU(Uart5Fd, Addr.AcPlug);
//	}
}

void ChangeStartOrStopDateTime(byte isStart)
{
	char cmdBuf[32];
	struct timeb csuTime;
	struct tm *tmCSU;

	ftime(&csuTime);
	tmCSU = localtime(&csuTime.time);

	sprintf(cmdBuf, "%04d-%02d-%02d %02d:%02d:%02d", tmCSU->tm_year + 1900,
			tmCSU->tm_mon + 1, tmCSU->tm_mday, tmCSU->tm_hour, tmCSU->tm_min,
			tmCSU->tm_sec);
	if (isStart)
		strcpy((char *)ac_chargingInfo[0]->StartDateTime, cmdBuf);
	else
		strcpy((char *)ac_chargingInfo[0]->StopDateTime, cmdBuf);
}

unsigned char isModeChange()
{
	unsigned char result = NO;

	if(ac_chargingInfo[0]->SystemStatus != ac_chargingInfo[0]->PreviousSystemStatus)
	{
		result = YES;
		ac_chargingInfo[0]->PreviousSystemStatus = ac_chargingInfo[0]->SystemStatus;
	}

	return result;
}

void SetAcModuleRelay(byte value)
{
	acOutputRelay.relay_event.bits.AC_L1_Relay = value;
	acOutputRelay.relay_event.bits.AC_L2_Relay = value;
	acOutputRelay.relay_event.bits.AC_L3_Relay = value;

	Config_Relay_Output(Uart5Fd, Addr.AcPlug, &acOutputRelay);
}

//===============================================
// AC OCPP routine
//===============================================

void ocpp_ac_startTransation_cmd()
{
	byte hasDc = ((ShmSysConfigAndInfo->SysConfig.TotalConnectorCount > 0) ? 1 : 0);

	if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16)
	{
		if(strcmp((char *)ac_chargingInfo[0]->StartUserId, "") == EQUAL)
			strcpy((char *)ac_chargingInfo[0]->StartUserId, (char *)ShmOCPP16Data->StartTransaction[hasDc].IdTag);
		else
			strcpy((char *)ShmOCPP16Data->StartTransaction[hasDc].IdTag, (char *)ac_chargingInfo[0]->StartUserId);

		PRINTF_FUNC("AC IdTag = %s \n", ShmOCPP16Data->StartTransaction[hasDc].IdTag);
		ShmOCPP16Data->CpMsg.bits[hasDc].StartTransactionReq = YES;
	}
	else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20)
	{
		if(strcmp((char *)ac_chargingInfo[0]->StartUserId, "") == EQUAL)
			strcpy((char *)ShmOCPP20Data->TransactionEvent[hasDc].idToken.idToken, (char *)ShmOCPP20Data->TransactionEvent[hasDc].idToken.idToken);
		else
			strcpy((char *)ShmOCPP20Data->TransactionEvent[hasDc].idToken.idToken, (char *)ac_chargingInfo[0]->StartUserId);

		PRINTF_FUNC("AC IdTag = %s \n", ShmOCPP20Data->TransactionEvent[hasDc].idToken.idToken);
		ShmOCPP20Data->CpMsg.bits[hasDc].TransactionEventReq = YES;
	}
}

void ocpp_ac_stopTransation_cmd()
{
	byte hasDc = ((ShmSysConfigAndInfo->SysConfig.TotalConnectorCount > 0) ? 1 : 0);

	if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16)
	{
		if(strcmp((char *)ac_chargingInfo[0]->StartUserId, "") == EQUAL)
			strcpy((char *)ShmOCPP16Data->StopTransaction[hasDc].IdTag, (char *)ShmOCPP16Data->StopTransaction[hasDc].IdTag);
		else
			strcpy((char *)ShmOCPP16Data->StopTransaction[hasDc].IdTag, (char *)ac_chargingInfo[0]->StartUserId);

		PRINTF_FUNC("AC IdTag = %s \n", ShmOCPP16Data->StopTransaction[hasDc].IdTag);
		ShmOCPP16Data->CpMsg.bits[hasDc].StopTransactionReq = YES;
	}
	else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20)
	{
		if(strcmp((char *)ac_chargingInfo[0]->StartUserId, "") == EQUAL)
			strcpy((char *)ShmOCPP20Data->TransactionEvent[hasDc].idToken.idToken, (char *)ShmOCPP20Data->TransactionEvent[hasDc].idToken.idToken);
		else
			strcpy((char *)ShmOCPP20Data->TransactionEvent[hasDc].idToken.idToken, (char *)ac_chargingInfo[0]->StartUserId);

		PRINTF_FUNC("AC IdTag = %s \n", ShmOCPP20Data->TransactionEvent[hasDc].idToken.idToken);
		ShmOCPP20Data->CpMsg.bits[hasDc].TransactionEventReq = YES;
	}
}

bool ocpp_ac_remoteStopReq_cmd()
{
	byte hasDc = ((ShmSysConfigAndInfo->SysConfig.TotalConnectorCount > 0) ? 1 : 0);
	bool result = false;

	if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16)
	{
		result = ShmOCPP16Data->CsMsg.bits[hasDc].RemoteStopTransactionReq;

		if (ShmOCPP16Data->CsMsg.bits[hasDc].RemoteStopTransactionReq == YES)
		{
			strcpy((char *)ShmOCPP16Data->StopTransaction[hasDc].StopReason, "Remote");
			ShmOCPP16Data->CsMsg.bits[hasDc].RemoteStopTransactionReq = NO;
		}
	}
	else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20)
	{
		result = ShmOCPP20Data->CsMsg.bits[hasDc].RequestStopTransactionReq;

		if (ShmOCPP20Data->CsMsg.bits[hasDc].RequestStopTransactionReq == YES)
		{
			strcpy((char *)ShmOCPP20Data->TransactionEvent[hasDc].transactionInfo.stoppedReason, "Remote");
			ShmOCPP20Data->CsMsg.bits[hasDc].RequestStopTransactionReq = NO;
		}
	}
	return result;
}

bool ocpp_ac_is_resPass_StartTransationConf()
{
	bool result = false;
	byte hasDc = ((ShmSysConfigAndInfo->SysConfig.TotalConnectorCount > 0) ? 1 : 0);

	if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16)
	{
		result = ShmOCPP16Data->CpMsg.bits[hasDc].StartTransactionConf;
	}
	else if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20)
	{
		result = ShmOCPP20Data->CpMsg.bits[hasDc].TransactionEventConf;
	}

	return result;
}

bool ocpp_ac_chk_invalid_id_cmd()
{
	byte hasDc = ((ShmSysConfigAndInfo->SysConfig.TotalConnectorCount > 0) ? 1 : 0);

	if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16)
	{
		if (strstr((char *) ShmOCPP16Data->ConfigurationTable.CoreProfile[StopTransactionOnInvalidId].ItemData, "TRUE"))
		{
			if (strcmp((char *)ShmOCPP16Data->StartTransaction[hasDc].ResponseIdTagInfo.Status, "Blocked") == EQUAL ||
					strcmp((char *)ShmOCPP16Data->StartTransaction[hasDc].ResponseIdTagInfo.Status, "Expired") == EQUAL ||
					strcmp((char *)ShmOCPP16Data->StartTransaction[hasDc].ResponseIdTagInfo.Status, "Invalid") == EQUAL)
				return true;
		}
	}
	else if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20)
	{
		if (strstr((char *) ShmOCPP20Data->ControllerComponentVariable[TxCtrlr_StopTxOnInvalidId].variableAttribute[0].value, "TRUE"))
		{
			if (strcmp((char *)ShmOCPP20Data->TransactionEvent[hasDc].Response_idTokenInfo.status, "Blocked") == EQUAL ||
					strcmp((char *)ShmOCPP20Data->TransactionEvent[hasDc].Response_idTokenInfo.status, "Expired") == EQUAL ||
					strcmp((char *)ShmOCPP20Data->TransactionEvent[hasDc].Response_idTokenInfo.status, "Invalid") == EQUAL ||
					strcmp((char *)ShmOCPP20Data->TransactionEvent[hasDc].Response_idTokenInfo.status, "NoCredit") == EQUAL ||
					strcmp((char *)ShmOCPP20Data->TransactionEvent[hasDc].Response_idTokenInfo.status, "NotAllowedTypeEVSE") == EQUAL ||
					strcmp((char *)ShmOCPP20Data->TransactionEvent[hasDc].Response_idTokenInfo.status, "NotAtThisLocation") == EQUAL ||
					strcmp((char *)ShmOCPP20Data->TransactionEvent[hasDc].Response_idTokenInfo.status, "NotAtThisTime") == EQUAL ||
					strcmp((char *)ShmOCPP20Data->TransactionEvent[hasDc].Response_idTokenInfo.status, "Unknown") == EQUAL)
				return true;
		}
	}

	return false;
}

bool ocpp_ac_get_startTransation_req()
{
	bool result = false;
	byte hasDc = ((ShmSysConfigAndInfo->SysConfig.TotalConnectorCount > 0) ? 1 : 0);

	// �p�G�� AC �j�A�Ӳ{�b�O DC �ĤG��j�i�J�R�q
	if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16)
	{
		result = ShmOCPP16Data->CpMsg.bits[hasDc].StartTransactionReq;
	}
	else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20)
	{
		result = ShmOCPP20Data->CpMsg.bits[hasDc].TransactionEventReq;
	}

	return result;
}

void ocpp_ac_set_stopReason_by_cmd(char *reason)
{
	byte hasDc = ((ShmSysConfigAndInfo->SysConfig.TotalConnectorCount > 0) ? 1 : 0);

	if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16)
	{
		if (strcmp((char *)ShmOCPP16Data->StopTransaction[hasDc].StopReason, "") == EQUAL)
		{
			strcpy((char *)ShmOCPP16Data->StopTransaction[hasDc].StopReason, reason);
		}
	}
	else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20)
	{
		if (strcmp((char *)ShmOCPP20Data->TransactionEvent[hasDc].transactionInfo.stoppedReason, "") == EQUAL)
		{
			strcpy((char *)ShmOCPP20Data->TransactionEvent[hasDc].transactionInfo.stoppedReason, reason);
		}
	}
}

void ocpp_ac_auto_response_StartTransationConf()
{
	byte hasDc = ((ShmSysConfigAndInfo->SysConfig.TotalConnectorCount > 0) ? 1 : 0);

	if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16)
	{
		if (ShmOCPP16Data->CpMsg.bits[hasDc].StartTransactionConf)
			ShmOCPP16Data->CpMsg.bits[hasDc].StartTransactionConf = NO;
	}
	else if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20)
	{
		if (ShmOCPP20Data->CpMsg.bits[hasDc].TransactionEventConf)
			ShmOCPP20Data->CpMsg.bits[hasDc].TransactionEventConf = NO;
	}
}

void ocpp_ac_set_errCode_cmd()
{
	byte hasDc = ((ShmSysConfigAndInfo->SysConfig.TotalConnectorCount > 0) ? 1 : 0);

	if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16)
	{
		strcpy((char *)ShmOCPP16Data->StatusNotification[hasDc].ErrorCode, "InternalError");
		strcpy((char *)ShmOCPP16Data->StatusNotification[hasDc].VendorErrorCode, (char *)ac_chargingInfo[0]->ConnectorAlarmCode);
	}
	else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20)
	{

	}
}

void ocpp_ac_clear_errorCode_cmd(bool isError)
{
	byte hasDc = ((ShmSysConfigAndInfo->SysConfig.TotalConnectorCount > 0) ? 1 : 0);

	if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16)
	{
		if (strcmp((char *)ShmOCPP16Data->StatusNotification[hasDc].ErrorCode, "NoError") != EQUAL)
			strcpy((char *)ShmOCPP16Data->StatusNotification[hasDc].ErrorCode, "NoError");

		if (strcmp((char *)ShmOCPP16Data->StatusNotification[hasDc].VendorErrorCode, "") != EQUAL)
			strcpy((char *)ShmOCPP16Data->StatusNotification[hasDc].VendorErrorCode, "");
	}
	else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20)
	{

	}
}

void ocpp_ac_clear_stopReason()
{
	byte hasDc = ((ShmSysConfigAndInfo->SysConfig.TotalConnectorCount > 0) ? 1 : 0);

	if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16)
		strcpy((char *)ShmOCPP16Data->StopTransaction[hasDc].StopReason, "");
	else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20)
		strcpy((char *)ShmOCPP20Data->TransactionEvent[hasDc].transactionInfo.stoppedReason, "");
}

void ocpp_ac_set_remoteStart_transaction_req(bool result)
{
	byte hasDc = ((ShmSysConfigAndInfo->SysConfig.TotalConnectorCount > 0) ? 1 : 0);

	if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16)
		ShmOCPP16Data->CsMsg.bits [hasDc].RemoteStartTransactionReq = result;
	else if (ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_20)
		ShmOCPP20Data->CsMsg.bits [hasDc].RequestStartTransactionReq = result;
}

//===============================================
// AC Main Process
//===============================================
byte _SystemStatus = 255;
byte _CpStatus = 255;

byte GetMaxChargingDuty()
{
	// �@�}�l���]�w�̤j�q�y���w��̤j�i�䴩�q�y
	byte result = AcChargingRatingCurrent;

	// ChargingProfileCurrent => charging profile
	// AcMaxChargingCurrent => ����
	// AcChargingRatingCurrent => �w�魭��̤j�i��X�q�y
	if (ShmSysConfigAndInfo->SysConfig.AcMaxChargingCurrent > 0)
	{
		if (ShmSysConfigAndInfo->SysConfig.AcMaxChargingCurrent <= result)
			result = ShmSysConfigAndInfo->SysConfig.AcMaxChargingCurrent;
	}

	if (ac_chargingInfo[0]->ChargingProfileCurrent > 0)
	{
		if (ac_chargingInfo[0]->ChargingProfileCurrent <= result)
			result = ac_chargingInfo[0]->ChargingProfileCurrent;
	}

	if (result >= 1 && result <= 5)
		result = AC_MINIMUM_DUTY;
	else if (result == 0)
		result = AC_STOP_DUTY;

	return result;
}

void AcChargeTypeProcess()
{
	if (acgunCount > 0)
	{
		//ac_chargingInfo[0]->SelfTest_Comp = YES;
		//ac_chargingInfo[0]->IsModeChagned = PASS;
		//---------------------------------------------
		if (ac_chargingInfo[0]->SelfTest_Comp == NO)
		{
			ac_chargingInfo[0]->IsModeChagned = NO;
			ResetMcuReqAC();
			SetModelName_AC();
			GetFwVersion_AC();
			GetAcModelName();
		}
		else if (ac_chargingInfo[0]->SelfTest_Comp == YES)
		{
			if (isAcModuleInitComp == NO)
			{
				isAcModuleInitComp = YES;
				ac_chargingInfo[0]->SystemStatus = SYS_MODE_IDLE;
			}

			GetAcAlarmCode();

			if (GetAcStatus())
			{
				byte _status = SYS_MODE_BOOTING;

				if (ac_chargingInfo[0]->IsAvailable == NO)
				{
					_status = SYS_MODE_MAINTAIN;
				}

				//printf("SystemStatus = %d, err = %d \n", ac_chargingInfo[0]->SystemStatus, ac_chargingInfo[0]->IsErrorOccur);
				if ((ac_chargingInfo[0]->SystemStatus == SYS_MODE_IDLE || ac_chargingInfo[0]->SystemStatus == SYS_MODE_MAINTAIN) &&
						ac_chargingInfo[0]->IsErrorOccur)
				{
					_status = SYS_MODE_FAULT;
				}
				else if (ac_chargingInfo[0]->SystemStatus == SYS_MODE_CHARGING &&
						ac_chargingInfo[0]->IsErrorOccur)
				{
					_status = SYS_MODE_ALARM;
				}
				else if (_status == SYS_MODE_MAINTAIN)
				{
					// do nothing
				}
				else if (acStatus.CpStatus == AC_SYS_A)
				{
					if (ac_chargingInfo[0]->IsErrorOccur &&
							(ac_chargingInfo[0]->SystemStatus >= SYS_MODE_PREPARING ||
							ac_chargingInfo[0]->SystemStatus <= SYS_MODE_CHARGING))
						_status = SYS_MODE_ALARM;
					else if (!ac_chargingInfo[0]->IsErrorOccur &&
							(ac_chargingInfo[0]->SystemStatus >= SYS_MODE_TERMINATING ||
							ac_chargingInfo[0]->SystemStatus <= SYS_MODE_ALARM))
					{
						if (GetTimeoutValue(&_ac_charging_comp) >= 10 && acStatus.CpStatus == AC_SYS_A)
							_status = SYS_MODE_IDLE;
					}
				}
				else if (ac_chargingInfo[0]->SystemStatus >= SYS_MODE_PREPARING &&
							ac_chargingInfo[0]->SystemStatus < SYS_MODE_CHARGING)
				{
					if (acStatus.CpStatus == AC_SYS_C)
						_status = SYS_MODE_CHARGING;
					else if (GetTimeoutValue(&_ac_preparing) >= 120)
						_status = SYS_MODE_IDLE;
				}
				else if ((acStatus.CpStatus == AC_SYS_B || ac_chargingInfo[0]->ConnectorPlugIn == AC_SYS_B) &&
						ac_chargingInfo[0]->IsAvailable &&
						!ac_chargingInfo[0]->IsErrorOccur &&
						ac_chargingInfo[0]->SystemStatus == SYS_MODE_IDLE &&
						(ShmSysConfigAndInfo->SysInfo.WaitForPlugit == YES ||
							ShmSysConfigAndInfo->SysConfig.AuthorisationMode == AUTH_MODE_DISABLE))
				{
					if (ac_chargingInfo[0]->RemoteStartFlag == YES)
					{
						PRINTF_FUNC("** AC Remote \n");
						ac_chargingInfo[0]->RemoteStartFlag = NO;
						ac_chargingInfo[0]->isRemoteStart = YES;
						strcpy((char *)ac_chargingInfo[0]->StartUserId, "");
						ShmSysConfigAndInfo->SysInfo.WaitForPlugit = NO;
						ocpp_ac_set_remoteStart_transaction_req(NO);
						_status = SYS_MODE_PREPARING;
					}
					else if (ac_chargingInfo[0]->ReservedStartFlag == YES)
					{
						ac_chargingInfo[0]->ReservedStartFlag = NO;
						strcpy ( (char *) ac_chargingInfo[0]->StartUserId,
								(char *) ShmDcCommonData->_reserved_ac_UserId [0] );
						PRINTF_FUNC ( "AC Start Charging : Reserved CardNumber = %s \n", ac_chargingInfo[0]->StartUserId );
						strcpy ( (char *) ShmSysConfigAndInfo->SysConfig.UserId, "" );
						strcpy ( (char *) ShmDcCommonData->_reserved_ac_UserId [0], "" );
						// ���e�ާ@���j���A�i�J Preparing
						ShmSysConfigAndInfo->SysInfo.WaitForPlugit = NO;
					}
					else if (ShmSysConfigAndInfo->SysConfig.AuthorisationMode == AUTH_MODE_DISABLE)
					{
						PRINTF_FUNC ( "Conn AC Start Charging : Plug and charing \n" );
						byte hasDc = ((ShmSysConfigAndInfo->SysConfig.TotalConnectorCount > 0) ? 1 : 0);

						strncpy ( (char *) ShmOCPP16Data->StartTransaction [hasDc].IdTag,
								(char *) ShmSysConfigAndInfo->SysConfig.SerialNumber,
								sizeof(ShmOCPP16Data->StartTransaction [hasDc].IdTag) );

						ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc = DEFAULT_AC_INDEX;
						_status = SYS_MODE_PREPARING;
					}
					else if (ShmSysConfigAndInfo->SysInfo.OrderCharging == NO_DEFINE)
					{
						PRINTF_FUNC("** UserId = %s \n", ShmSysConfigAndInfo->SysConfig.UserId);
						strcpy((char *)ac_chargingInfo[0]->StartUserId, (char *)ShmSysConfigAndInfo->SysConfig.UserId);
						PRINTF_FUNC("** CardNumber = %s \n", ac_chargingInfo[0]->StartUserId);
						strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
						ShmSysConfigAndInfo->SysInfo.WaitForPlugit = NO;
						_status = SYS_MODE_PREPARING;
					}
				}

				if (ac_chargingInfo[0]->SystemStatus == SYS_MODE_PREPARING ||
						ac_chargingInfo[0]->SystemStatus == SYS_MODE_CHARGING)
				{
					if (ocpp_ac_remoteStopReq_cmd())
					{
						ocpp_ac_set_stopReason_by_cmd("Remote");
						_status = SYS_MODE_TERMINATING;
					}
					else if (ac_chargingInfo[0]->StopChargeFlag ||
							acStatus.CpStatus == AC_SYS_F)
					{
						_status = SYS_MODE_TERMINATING;
					}
				}

				if (_status != SYS_MODE_BOOTING && ac_chargingInfo[0]->SystemStatus != _status)
				{
					ac_chargingInfo[0]->SystemStatus = _status;

					if (ac_chargingInfo [0]->SystemStatus != _SystemStatus)
					{
						PRINTF_FUNC ( "ac_chargingInfo[0]->SystemStatus = %d \n", ac_chargingInfo [0]->SystemStatus );
						_SystemStatus = ac_chargingInfo [0]->SystemStatus;
					}
				}

				if (acStatus.CpStatus != _CpStatus &&
						_CpStatus != SYS_MODE_BOOTING)
				{
					PRINTF_FUNC("acStatus.CpStatus = %d", acStatus.CpStatus);
					_CpStatus = acStatus.CpStatus;
				}

				// �]�w����̤j�R�q�q�y >= 6 ~ <= 32
				switch(ac_chargingInfo[0]->SystemStatus)
				{
					case SYS_MODE_IDLE:
					case SYS_MODE_MAINTAIN:
					case SYS_MODE_RESERVATION:
					case SYS_MODE_FAULT:
					{
						if (isModeChange())
						{
							if (ac_chargingInfo[0]->SystemStatus == SYS_MODE_IDLE)
							{
								PRINTF_FUNC("================== SYS_MODE_IDLE (AC Gun) ================ \n");
								ac_chargingInfo [0]->ReservationId = -1;
							}
							else if (ac_chargingInfo[0]->SystemStatus == SYS_MODE_MAINTAIN)
								PRINTF_FUNC("================== SYS_MODE_MAINTAIN (AC Gun) ================ \n");
							else if (ac_chargingInfo[0]->SystemStatus == SYS_MODE_RESERVATION)
							{
								PRINTF_FUNC("================== SYS_MODE_RESERVATION (AC Gun) ================ \n");
								PRINTF_FUNC("================= Id : %s ================  \n", ShmDcCommonData->_reserved_ac_UserId[0]);
							}
							else if (ac_chargingInfo[0]->SystemStatus == SYS_MODE_FAULT)
								PRINTF_FUNC("================== SYS_MODE_FAULT (AC Gun) ================ \n");

							SetCpDuty(100);

							ac_chargingInfo [0]->PresentChargedDuration = 0;
							ac_chargingInfo [0]->RemainChargingDuration = 0;
							ac_chargingInfo [0]->PresentChargingCurrent = 0;
							ac_chargingInfo[0]->PresentChargedEnergy = 0.0;
							ac_chargingInfo[0]->PresentChargingVoltage = 0;
							ac_chargingInfo[0]->ChargingFee = 0.0;
							ac_chargingInfo[0]->isRemoteStart = NO;
							strcpy((char *)ac_chargingInfo[0]->StartDateTime, "");
							strcpy((char *)ac_chargingInfo[0]->StopDateTime, "");
							strcpy ( (char *) ac_chargingInfo [0]->StartUserId, "" );
							_beforeChargingTotalEnergy = 0.0;
							ocpp_ac_clear_stopReason();
							ocpp_ac_auto_response_StartTransationConf();
							ac_startTransationFlag = START_TRANSATION_STATUS_WAIT;
						}

						ac_chargingInfo[0]->ChargingProfilePower = -1;
						ac_chargingInfo[0]->ChargingProfileCurrent = -1;

						ac_chargingInfo[0]->StopChargeFlag = NO;
						ChangeLedStatus();
					}
						break;
					case SYS_MODE_PREPARING:
					{
						if (isModeChange())
						{
							PRINTF_FUNC("================== SYS_MODE_PREPARING (AC Gun) ================ \n");

							SetLegacyReq(YES);
							ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_NONE;
							ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc = DEFAULT_AC_INDEX;
							if (ShmSysConfigAndInfo->SysInfo.OrderCharging != NO_DEFINE)
								ShmSysConfigAndInfo->SysInfo.OrderCharging = NO_DEFINE;

							ocpp_ac_startTransation_cmd();
							GetTimespecFunc(&_ac_preparing);
						}

						if (GetChargingEnergy() == PASS)
						{
							//ac_chargingInfo[0]->PresentChargedEnergy = acChargingEnergy.Energy / 100;
							_beforeChargingTotalEnergy = ((float)acChargingEnergy.Energy) / 10000;
						}

						ac_startTransationFlag = ocpp_ac_is_resPass_StartTransationConf();

						if (ac_startTransationFlag == START_TRANSATION_STATUS_PASS)
						{
							if (ocpp_ac_chk_invalid_id_cmd())
								ac_startTransationFlag = START_TRANSATION_STATUS_FAIL;
						}
						else
						{
							if (ShmSysConfigAndInfo->SysInfo.OcppConnStatus == NO)
							{
								if (ShmSysConfigAndInfo->SysConfig.OfflinePolicy == _OFFLINE_POLICY_FREE_CHARGING ||
										ShmSysConfigAndInfo->SysConfig.AuthorisationMode == AUTH_MODE_DISABLE ||
										!ocpp_ac_get_startTransation_req() ||
										strcmp((char *)ac_chargingInfo[0]->StartUserId, "") != EQUAL)
								{
									ac_startTransationFlag = START_TRANSATION_STATUS_PASS;
								}
							}
						}

						if (ac_startTransationFlag == START_TRANSATION_STATUS_PASS)
						{
							// �R�q�e���� duty : �̷� Charging profile
							SetCpDuty(GetMaxChargingDuty());
						}
						else if (ac_startTransationFlag == START_TRANSATION_STATUS_FAIL ||
								(ac_startTransationFlag == START_TRANSATION_STATUS_WAIT && GetTimeoutValue(&_ac_preparing) > 10))
						{
							PRINTF_FUNC("StartTransaction Fail / Timeout. \n");
							ac_chargingInfo[0]->StopChargeFlag = YES;
						}
						ChangeLedStatus();
					}
						break;
					case SYS_MODE_CHARGING:
					{
						if (isModeChange())
						{
							PRINTF_FUNC("================== SYS_MODE_CHARGING (AC Gun) ================ \n");
							ftime(&_ac_startChargingTime);
							ChangeStartOrStopDateTime(YES);
							ShmSysConfigAndInfo->SysInfo.CurGunSelectedByAc = DEFAULT_AC_INDEX;
						}
						// �ΥH�P�_�O�_���b��X
						ac_chargingInfo[0]->IsCharging = acStatus.RelayStatus;

						ftime(&_ac_endChargingTime);
						ac_chargingInfo[0]->PresentChargedDuration = DiffTimeb(_ac_startChargingTime, _ac_endChargingTime);

						if (ac_chargingInfo[0]->IsCharging)
						{
							if (GetChargingEnergy() == PASS)
							{
								if ((acChargingEnergy.Energy - _beforeChargingTotalEnergy) > 0)
								{
									// �p���I�����
									ac_chargingInfo[0]->PresentChargedEnergy += (((float)acChargingEnergy.Energy) / 10000 - _beforeChargingTotalEnergy);
									if (ShmSysConfigAndInfo->SysConfig.BillingData.isBilling)
									{
										ac_chargingInfo[0]->ChargingFee += ac_chargingInfo[0]->PresentChargedEnergy * ShmSysConfigAndInfo->SysConfig.BillingData.Cur_fee;
									}
								}

								_beforeChargingTotalEnergy = ((float)acChargingEnergy.Energy) / 10000;
							}

							//GetAcChargingPower();
							GetAcChargingVoltage();
							GetAcChargingCurrent();

							{
	//							PRINTF_FUNC("L1N_L12 = %f, L1N_L12 = %f, L1N_L12 = %f \n",
	//									acChargingVoltage.L1N_L12,
	//									acChargingVoltage.L2N_L23,
	//									acChargingVoltage.L3N_L31);
	//							PRINTF_FUNC("c1 = %d, c2 = %d, c3 = %d \n",
	//									acChargingCurrent.OuputCurrentL1,
	//									acChargingCurrent.OuputCurrentL2,
	//									acChargingCurrent.OuputCurrentL3);

								// �Y�ɿ�X�\�v
								ac_chargingInfo[0]->PresentChargingPower =
										(float)(acChargingVoltage.L1N_L12 * acChargingCurrent.OuputCurrentL1 +
										acChargingVoltage.L2N_L23 * acChargingCurrent.OuputCurrentL2 +
										acChargingVoltage.L3N_L31 * acChargingCurrent.OuputCurrentL3) / 1000;
							}
							// �ֿn��X�\�v
							//ac_chargingInfo[0]->PresentChargedEnergy
							ac_chargingInfo[0]->PresentChargingVoltage = (float)acChargingVoltage.L1N_L12;
							ac_chargingInfo[0]->PresentChargingCurrent = (float)(acChargingCurrent.OuputCurrentL1 + acChargingCurrent.OuputCurrentL2 + acChargingCurrent.OuputCurrentL3);

							// �R�q������ duty : �̷� Charging profile
							SetCpDuty(GetMaxChargingDuty());
						}
						else
						{
							// �f�W relay
							if (acStatus.CpStatus == AC_SYS_C &&
									!ac_chargingInfo[0]->IsErrorOccur)
							{
								PRINTF_FUNC("Set relay ON (AC Type). \n");
								SetAcModuleRelay(YES);
							}
						}

						ChangeLedStatus();
					}
						break;
					case SYS_MODE_TERMINATING:
					case SYS_MODE_ALARM:
					{
						//ocpp_set_errCode_cmd
						if (isModeChange())
						{
							if (ac_chargingInfo[0]->SystemStatus == SYS_MODE_TERMINATING)
								PRINTF_FUNC("================== SYS_MODE_TERMINATING (AC Gun) ================ \n");
							else if (ac_chargingInfo[0]->SystemStatus == SYS_MODE_ALARM)
								PRINTF_FUNC("================== SYS_MODE_ALARM (AC Gun) ================ \n");

							ChangeStartOrStopDateTime(NO);
							GetTimespecFunc(&_ac_charging_comp);
							ocpp_ac_set_stopReason_by_cmd("Local");
							SetCpDuty(100);

							if (ac_chargingInfo[0]->SystemStatus == SYS_MODE_TERMINATING)
								PRINTF_FUNC("================== SYS_MODE_TERMINATING (AC Gun) ================ \n");
							else if (ac_chargingInfo[0]->SystemStatus == SYS_MODE_ALARM)
							{
								ftime(&_ac_endChargingTime);

								ocpp_ac_set_errCode_cmd();
								if (strcmp((char *)ac_chargingInfo[0]->StartDateTime, "") != EQUAL)
								{
									ocpp_ac_auto_response_StartTransationConf();
									// AC �T�w����2��j
									ocpp_ac_stopTransation_cmd();
								}
							}
						}

						SetLegacyReq(NO);
						if (acStatus.RelayStatus == NO)
						{
							if (ac_chargingInfo[0]->SystemStatus == SYS_MODE_TERMINATING)
								ac_chargingInfo[0]->SystemStatus = SYS_MODE_COMPLETE;
						}
						else
						{
							// �f�W relay
							PRINTF_FUNC("Set relay OFF (AC Type). \n");
							SetAcModuleRelay(NO);
						}

						if (ac_chargingInfo[0]->SystemStatus == SYS_MODE_ALARM)
							ac_chargingInfo[0]->PresentChargedDuration = DiffTimeb(_ac_startChargingTime, _ac_endChargingTime);
					}
						break;
					case SYS_MODE_COMPLETE:
					{
						if (isModeChange())
						{
							PRINTF_FUNC("================== SYS_MODE_COMPLETE (AC Gun) ================ \n");

							GetTimespecFunc(&_ac_charging_comp);
							ftime(&_ac_endChargingTime);
							ocpp_ac_set_errCode_cmd();
							if (strcmp((char *)ac_chargingInfo[0]->StartDateTime, "") != EQUAL)
							{
								ocpp_ac_auto_response_StartTransationConf();
								// AC �T�w����2��j
								ocpp_ac_stopTransation_cmd();
							}

							ChangeStartOrStopDateTime(NO);
							ac_chargingInfo[0]->PresentChargedDuration = DiffTimeb(_ac_startChargingTime, _ac_endChargingTime);
						}
					}
						break;
				}
			}
		}
	}
}

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)
	{
		isCriticalStop = YES;
		GetTimespecFunc(&_psuCriticalStop);
	}
	else
	{
		int _timebuf = GetTimeoutValue(&_psuCriticalStop);

		if (_timebuf < 0)
			GetTimespecFunc(&_psuCriticalStop);
		else
		{
			if (_timebuf >= FORCE_STOP_TIME)
			{
				isCriticalStop = NO;
				ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuFailureAlarm = NORMAL;
				ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuComminicationErrWithCSU = NORMAL;
				system("/usr/bin/run_evse_restart.sh");
			}
		}
	}
}

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;
	}

	gunCount = ShmSysConfigAndInfo->SysConfig.TotalConnectorCount;
	acgunCount = ShmSysConfigAndInfo->SysConfig.AcConnectorCount;
	// Open Uart5 for RB
	Uart5Fd = InitComPort();
	Initialization();
	is50kwSystem = Is50kwSystemChk();

	sleep(1);

	if(Uart5Fd < 0)
	{
		PRINTF_FUNC("(Internal) open port error. \n");
		return 0;
	}

	if (acgunCount > 0)
	{
		acOutputRelay.relay_event.bits.AC_L1_Relay = 0x00;
		acOutputRelay.relay_event.bits.AC_L2_Relay = 0x00;
		acOutputRelay.relay_event.bits.AC_L3_Relay = 0x00;
		Config_Relay_Output(Uart5Fd, Addr.AcPlug, &acOutputRelay);
	}

	outputRelay.relay_event.bits.AC_Contactor = 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;				// ���j D+ (R1 +)
	outputRelay.relay_event.bits.Gun1_N = 0x00;				// ���j D- (R1 -)
	outputRelay.relay_event.bits.Gun2_N = 0x00;				// �k�j D- (R2 -)
	outputRelay.relay_event.bits.Gun2_P = 0x00;				// �k�j 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;
	cur_led_color.Connect_2_Red = COLOR_MIN_LV;
	cur_led_color.Connect_2_Green = COLOR_MIN_LV;
	cur_led_color.Connect_2_Blue = COLOR_MIN_LV;

	relayMatchFlag = NO;
	isCriticalStop = NO;
	isSelftestComp = NO;
	GetTimespecFunc(&_led_blink_time);

	for(;;)
	{
		bool isCharging = false;
		// �{�Ƕ}�l���e~ �������T�w FW �����P�w�骩���A�T�{��!!~ �ӼҲդ~��O�u���� Initial Comp.
		if (ShmRelayModuleData->SelfTest_Comp == NO)
		{
			GetFwAndHwVersion_Relay();
			SetModelName_Relay();
			SetRtcData_Relay();
			sleep(1);
		}

		if (ShmFanModuleData->SelfTest_Comp == NO)
		{
			GetFwAndHwVersion_Fan();
			SetModelName_Fan();
			SetRtcData_Fan();
			sleep(1);
			GetTimespecFunc(&_priority_time);
		}

		// ���˶��q�B�z�A���˶��q�p�GŪ���쪩���h�N���Өt�ΨS�����O�O
		if (ShmLedModuleData->SelfTest_Comp == NO)
		{
			// ���˶��q
			if (ShmSysConfigAndInfo->SysInfo.SelfTestSeq <= _STEST_PSU_CAP)
			{
				GetFwAndHwVersion_Led();
				sleep(1);
				GetTimespecFunc(&_led_priority_time);
			}
			else
			{
				// ���˶��q�S���ݨ쪩��
				if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.LedboardStestFail == NO)
					ShmStatusCodeData->AlarmCode.AlarmEvents.bits.LedboardStestFail = YES;
			}
		}

		AcChargeTypeProcess();

		if (ShmRelayModuleData->SelfTest_Comp == YES)
		{
			if (ShmSysConfigAndInfo->SysInfo.PageIndex == _LCM_IDLE && !isSelftestComp)
				isSelftestComp = true;
			// ==============�u���v�̰� 10 ms ==============
			// ��X�q��
			GetPersentOutputVol();

			// �T�ۿ�J�q��
			GetPresentInputVol();

			// Ū�����e AC relay ���A
			regRelay.relay_event.bits.AC_Contactor = ShmSysConfigAndInfo->SysInfo.AcContactorStatus;
			GetRelayOutputStatus();

			for (int i = 0; i < gunCount; i++)
			{
				// Cable check (Set)
				CableCheckDetected(i);

				// check k1 k2 relay ���A
				CheckK1K2RelayOutput(i);

				// �̾ڷ��e�U�j�����A��� �f�W/��} Relay
				SetK1K2RelayStatus(i);

				if (_chargingData[i]->SystemStatus == SYS_MODE_IDLE ||
						_chargingData[i]->SystemStatus == SYS_MODE_RESERVATION ||
						_chargingData[i]->SystemStatus == SYS_MODE_MAINTAIN)
				{
					_isOvpChkTimeFlag[i] = NO;
				}

				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 ||
					(ShmSysConfigAndInfo->SysInfo.PageIndex >= _LCM_AUTHORIZING && ShmSysConfigAndInfo->SysInfo.PageIndex <= _LCM_WAIT_FOR_PLUG))
				{
					_chargingData[i]->IsReadyToCharging = YES;
					isCharging = true;

					if (_chargingData[i]->SystemStatus == SYS_MODE_CHARGING)
					{
						// OVP
						CheckOutputPowerOverCarReq(i);
					}
					else if (_chargingData[i]->SystemStatus == SYS_MODE_PREPARE_FOR_EVSE)
					{
						// abnormal voltage at the stage of GFD
						CheckOutputVolNoneMatchFire(i);
					}
					else
						_isOutputNoneMatch[i] = NO;
				}
				else
					_chargingData[i]->IsReadyToCharging = NO;
			}
			// Cable check (Get)
			GetGfdAdc();

			// ���� relay
			SetParalleRelayStatus();

			// �f�W AC Contactor
//			if (isCharging)
//				outputRelay.relay_event.bits.AC_Contactor = YES;
//			else
//				outputRelay.relay_event.bits.AC_Contactor = NO;

			if (isCharging || (ShmPsuData->Work_Step == _TEST_MODE))
			{
				isStopChargingCount = false;
				outputRelay.relay_event.bits.AC_Contactor = YES;
			}
			else
			{
				if (!isStopChargingCount)
				{
					GetTimespecFunc(&_close_ac_contactor);
					isStopChargingCount = true;
				}
				else
				{
					if ((outputRelay.relay_event.bits.AC_Contactor == YES && GetTimeoutValue(&_close_ac_contactor) >= TEN_MINUTES))
					{
						outputRelay.relay_event.bits.AC_Contactor = NO;
					}
				}
			}

			if ((ShmPrimaryMcuData->InputDet.bits.EmergencyButton == ABNORMAL ||
					ShmPrimaryMcuData->InputDet.bits.DoorOpen == ABNORMAL) &&
					ShmDcCommonData->_tiltSensorStep == _TILT_SENSOR_STEP_NONE)
				outputRelay.relay_event.bits.AC_Contactor = NO;

			if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuFailureAlarm == ABNORMAL ||
					ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuComminicationErrWithCSU == ABNORMAL)
			{
				RunForceStopProcess();
				outputRelay.relay_event.bits.AC_Contactor = NO;
			}

			ShmDcCommonData->acContactSwitch = outputRelay.relay_event.bits.AC_Contactor;

			if (ShmPsuData->Work_Step >= _TEST_MODE && ShmPsuData->Work_Step <= _TEST_MODE)
				outputRelay.relay_event.bits.Gun1_N = outputRelay.relay_event.bits.Gun1_P = YES;

			// �f�W/�P�} Relay
			if(IsNoneMatchRelayStatus())
			{
				relayMatchFlag = NO;

				if (Config_Relay_Output(Uart5Fd, Addr.Relay, &outputRelay))
				{
//					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;
//					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;
				}
			}
			else if (relayMatchFlag == NO)
			{
				relayMatchFlag = YES;
				PRINTF_FUNC("======== Relay Status Start========\n");
				if (regRelay.relay_event.bits.AC_Contactor == YES)
					PRINTF_FUNC("AC Power : ON \n");
				else
					PRINTF_FUNC("AC Power : OFF \n");

				if (regRelay.relay_event.bits.Gun1_P == YES)
					PRINTF_FUNC("Conn1(+) : ON \n");
				else
					PRINTF_FUNC("Conn1(+) : OFF \n");

				if (regRelay.relay_event.bits.Gun1_N == YES)
					PRINTF_FUNC("Conn1(-) : ON \n");
				else
					PRINTF_FUNC("Conn1(-) : OFF \n");

				if (regRelay.relay_event.bits.Gun2_P == YES)
					PRINTF_FUNC("Conn2(+) : ON \n");
				else
					PRINTF_FUNC("Conn2(+) : OFF \n");

				if (regRelay.relay_event.bits.Gun2_N == YES)
					PRINTF_FUNC("Conn2(-) : ON \n");
				else
					PRINTF_FUNC("Conn2(-) : OFF \n");

				if (regRelay.relay_event.bits.R3_BOTH_K1_K4 == YES)
					PRINTF_FUNC("R3_BOTH_K1_K4 : ON \n");
				else
					PRINTF_FUNC("R3_BOTH_K1_K4 : OFF \n");

				if (regRelay.relay_event.bits.R4_BOTH_K2_K5 == YES)
					PRINTF_FUNC("R4_BOTH_K2_K5 : ON \n");
				else
					PRINTF_FUNC("R4_BOTH_K2_K5 : OFF \n");

				if (regRelay.relay_event.bits.R5_BOTH_K3_K6 == YES)
					PRINTF_FUNC("R5_BOTH_K3_K6 : ON \n");
				else
					PRINTF_FUNC("R5_BOTH_K3_K6 : OFF \n");

				PRINTF_FUNC("======== Relay Status End========\n");
			}
		}

		if (ShmFanModuleData->SelfTest_Comp == YES ||
				strlen((char *)ShmSysConfigAndInfo->SysInfo.FanModuleFwRev) != 0 ||
				ShmSysConfigAndInfo->SysInfo.FanModuleFwRev[0] != '\0')
		{
			ShmFanModuleData->SelfTest_Comp = YES;

			int _timebuf = GetTimeoutValue(&_priority_time);

			if (_timebuf < 0)
				GetTimespecFunc(&_priority_time);
			else
			{
				if (_timebuf >= 1)
				{
					//GetPsuTempForFanSpeed();
					GetFanSpeedByFunction();
					GetFanSpeed();
					ShmSysConfigAndInfo->SysInfo.SystemFanRotaSpeed = _setFanSpeed;
					GetTimespecFunc(&_priority_time);

					ShmFanModuleData->SetFan1Speed = ShmFanModuleData->TestFanSpeed;
					ShmFanModuleData->SetFan2Speed = ShmFanModuleData->TestFanSpeed;
					ShmFanModuleData->SetFan3Speed = ShmFanModuleData->TestFanSpeed;
					ShmFanModuleData->SetFan4Speed = ShmFanModuleData->TestFanSpeed;

					//PRINTF_FUNC("set fan = %d \n", ShmFanModuleData->SetFan1Speed);
					SetFanModuleSpeed();
				}
			}
		}

		if (ShmLedModuleData->SelfTest_Comp == YES)
		{
			int _timebuf = GetTimeoutValue(&_led_priority_time);
			if (_timebuf < 0)
				GetTimespecFunc(&_led_priority_time);
			else
			{
				int _ledTimebuf = GetTimeoutValue(&_led_blink_time);

				if (_ledTimebuf > 6 ||_ledTimebuf < 0)
					GetTimespecFunc(&_led_blink_time);

				if (_timebuf >= 1)
				{
					if(gunCount == 1)
					{
						SetLedColor(_chargingData[0], _chargingData[0]);
					}
					else if (gunCount == 2)
					{
						SetLedColor(_chargingData[0], _chargingData[1]);
					}

					GetTimespecFunc(&_led_priority_time);
				}
			}
		}

		usleep(10000);
	}

	return FAIL;
}