#include    <sys/types.h>
#include    <sys/stat.h>
#include 	<sys/time.h>
#include 	<sys/timeb.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>      /*標準輸入輸出定義*/
#include    <stdlib.h>     /*標準函數庫定義*/
#include    <unistd.h>     /*Unix 標準函數定義*/
#include    <fcntl.h>      /*檔控制定義*/
#include    <termios.h>    /*PPSIX 終端控制定義*/
#include    <errno.h>      /*錯誤號定義*/
#include 	<errno.h>
#include 	<string.h>
#include	<time.h>
#include	<ctype.h>
#include 	<ifaddrs.h>
#include 	<math.h>
#include 	"Config.h"
#include 	<stdbool.h>
#include 	"../../define.h"
#include 	<dirent.h>
#include 	"VCCU.h"
#include	"timeout.h"
#include	"internalComm.h"
#include 	"IOComm.h"
#include 	<unistd.h>                 //write, close, usleep, read

#include 	<sys/time.h>
#include 	<sys/timeb.h>
#include    <sys/types.h>
#include    <sys/stat.h>
#include 	<sys/types.h>
#include 	<sys/ioctl.h>
#include 	<sys/socket.h>
#include 	<sys/ipc.h>
#include 	<sys/shm.h>
#include 	<sys/shm.h>
#include 	<sys/mman.h>
#include 	<linux/wireless.h>
#include 	<arpa/inet.h>
#include 	<netinet/in.h>

#include 	<unistd.h>
#include 	<stdarg.h>
#include    <stdio.h>      /*標準輸入輸出定義*/
#include    <stdlib.h>     /*標準函數庫定義*/
#include    <unistd.h>     /*Unix 標準函數定義*/
#include    <fcntl.h>      /*檔控制定義*/
#include    <termios.h>    /*PPSIX 終端控制定義*/
#include    <errno.h>      /*錯誤號定義*/
#include 	<errno.h>
#include 	<string.h>
#include	<time.h>
#include	<ctype.h>
#include 	<ifaddrs.h>
#include 	<math.h>
#include 	"Module_EvComm.h"

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>                 //write, close, usleep, read
#include <fcntl.h>                  //uart
#define 	Debug
#define 	ARRAY_SIZE(A)		(sizeof(A) / sizeof(A[0]))
#define 	PASS				1
#define 	FAIL				-1
#define 	START				1
#define 	STOP				0
#define 	BUFFER_SIZE			128
#define 	YES					1
#define 	NO					0
#define 	NORMAL				0
#define		ABNORMAL			1
#define 	EQUAL				0
#define 	BTN_RELEASE			0
#define 	BTN_PRESS			1
#define 	MAX_BUF 			64
#define 	SYSFS_GPIO_DIR 		"/sys/class/gpio"
#define 	SendDirection               0x08000000
#define 	FAIL				-1

struct SysConfigAndInfo				*ShmSysConfigAndInfo;
struct StatusCodeData 				*ShmStatusCodeData;
struct CHAdeMOData					*ShmCHAdeMOData;
struct CcsData						*ShmCcsData;
struct RelayModuleData				*ShmRelayModuleData;
//struct ATE 							*ate;
struct ChargingInfoData			*chargingInfo[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
struct timeb 					startChargingTime[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
struct timeb 					endChargingTime[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
struct timeb 					startPlugPresentStatusTime[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
struct timeb 					startDutyCyclTime[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
struct timeb 					endPlugPresentStatusTime[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
struct timeb 					endDutyCyclTime[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];


//VCCU_ChargeFromVehicle_DATA chargeFromVehicle;

pid_t CANReceiverPid;
int 						CanFd;
int 						CanFd2;

#define VIN_MAX_VOLTAGE		250	// 大於該值 : OVP
#define VIN_MIN_VOLTAGE		170	// 小於該值 : UVP
#define VIN_DROP_VOLTAGE	150	// 小於該值 : ac drop

#define SYSFS_GPIO_DIR      "/sys/class/gpio"

byte gunCount = CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY;
// for initial index to check EV board type is correct
Ver ver;
PresentInputVoltage inputVoltage;
PresentOutputVoltage outputVoltage;
Relay outputRelay;
Relay regRelay;
int Uart5Fd;
int Uart1Fd;
Gpio_in gpio_in;
char *relayRs485PortName = "/dev/ttyS5";
char* pPortName = "/dev/ttyS3";
char *priPortName = "/dev/ttyS1";

#define btoa(x) ((x)?"true":"false")
long hexToDec(char *source);
int getIndexOfSigns(char ch);
int whileLoopTime = 500000;//500ms//10000; // 10 ms
int targetCurrent_Value = 60;//2;
int targetVoltage_Value = 400;
int maximumCurrent_value = 200;//10;
int maximumVoltage_value = 500;
int linkVoltage = 500;
int contactorVoltage = 0;
int _port;
#define YES                 1
#define NO                  0
byte flash = NO;
//=================================
// Create all share memory
//=================================
struct Address Addr={0x01,0x02,0x03,0x04,0xFF};
struct Command Cmd={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x81,0x85,0x86,0xe0,0xe1,0xe2,0xe3};

byte normalStop = 0x01;
byte stopReason[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
byte evstaus[5] = { 0x01, 0x02, 0x03, 0x04, 0x05 };

struct Ev_Board_Cmd Ev_Cmd={
		0,
		0x00000200,
		0x00000400,
		0x00000500,
		0x00000600,
		0x00000700,
		0x00000800,
		0x00000900,
		0x00000A00,
		0x00000C00,
		0x00000D00,

		0x00000E00,
		0x00000F00,
		0x00001000,
		0x00001100,

		0x00001200,
		0x00001500,
};

unsigned long GetTimeoutValue(struct timeval _sour_time);


unsigned long GetTimeoutValue(struct timeval _sour_time)
{
	struct timeval _end_time;
	gettimeofday(&_end_time, NULL);

	return 1000000 * (_end_time.tv_sec - _sour_time.tv_sec) + _end_time.tv_usec - _sour_time.tv_usec;
}

int tranceive(int fd, unsigned char* cmd, unsigned char cmd_len, unsigned char* rx)
{
	int len;
	//sleep(2); //required to make flush work, for some reason
	tcflush(fd,TCIOFLUSH);
	if(write(fd, cmd, cmd_len) >= cmd_len)
	{
		usleep(5000);
		len = read(fd, rx, 512);
	}
	else
	{
		#ifdef SystemLogMessage
		//DEBUG_ERROR("Serial command %s response fail.\n", cmd);
		#endif
	}

	return len;
}

unsigned char Query_FW_Ver(unsigned char fd, unsigned char targetAddr, Ver *Ret_Buf)
{
	unsigned char result = FAIL;
	unsigned char tx[7] = {0xaa, 0x00, targetAddr, Cmd.query_FW_Ver, 0x00, 0x00, 0x00};
	unsigned char rx[512];
	unsigned char chksum = 0x00;
	unsigned char len = tranceive(fd, tx, sizeof(tx), rx);

	if(len > 6)
	{
		if (len < 6+(rx[4] | rx[5]<<8))
			return result;

		for(int idx = 0;idx<(rx[4] | rx[5]<<8);idx++)
		{
			chksum ^= rx[6+idx];
		}

		if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
		   (rx[2] == tx[1]) &&
		   (rx[1] == tx[2]) &&
		   (rx[3] == tx[3]))
		{
			memcpy(Ret_Buf->Version_FW, (char *)rx+6, (rx[4] | rx[5]<<8));
			*(Ret_Buf->Version_FW + 8) = 0x00;
			result = PASS;
		}
	}

	return result;
}

unsigned char Query_HW_Ver(unsigned char fd, unsigned char targetAddr, Ver *Ret_Buf)
{
	unsigned char result = FAIL;
	unsigned char tx[7] = {0xaa, 0x00, targetAddr, Cmd.query_HW_Ver, 0x00, 0x00, 0x00};
	unsigned char rx[512];
	unsigned char chksum = 0x00;
	unsigned char len = tranceive(fd, tx, sizeof(tx), rx);

	if(len > 6)
	{
		if (len < 6+(rx[4] | rx[5]<<8))
			return result;

		for(int idx = 0;idx<(rx[4] | rx[5]<<8);idx++)
		{
			chksum ^= rx[6+idx];
		}

		if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
		   (rx[2] == tx[1]) &&
		   (rx[1] == tx[2]) &&
		   (rx[3] == tx[3]))
		{
			memcpy(Ret_Buf->Version_HW, (char *)rx+6, (rx[4] | rx[5]<<8));
			*(Ret_Buf->Version_HW + 8) = 0x00;
			result = PASS;
		}
	}

	return result;
}

unsigned char Query_Present_InputVoltage(unsigned char fd, unsigned char targetAddr, PresentInputVoltage *Ret_Buf)
{
	unsigned char result = FAIL;
	unsigned char tx[7] = {0xaa, 0x00, targetAddr, Cmd.query_Present_InputVoltage, 0x00, 0x00, 0x00};
	unsigned char rx[512];
	unsigned char chksum = 0x00;
	unsigned char len = tranceive(fd, tx, sizeof(tx), rx);

	if(len > 6)
	{
		if (len < 6+(rx[4] | rx[5]<<8))
			return result;

		for(int idx = 0;idx<(rx[4] | rx[5]<<8);idx++)
		{
			chksum ^= rx[6+idx];
		}
		if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
		   (rx[2] == tx[1]) &&
		   (rx[1] == tx[2]) &&
		   (rx[3] == tx[3]))
		{
			Ret_Buf->inputType = rx[6];
			Ret_Buf->L1N_L12 =(rx[7] | (rx[8]<<8))/10.0;
			Ret_Buf->L2N_L23 =(rx[9] | (rx[10]<<8))/10.0;
			Ret_Buf->L3N_L31 =(rx[11] | (rx[12]<<8))/10.0;

			result = PASS;
		}
	}

	return result;
}

unsigned char Query_Present_OutputVoltage(unsigned char fd, unsigned char targetAddr, PresentOutputVoltage *Ret_Buf)
{
	unsigned char result = FAIL;
	unsigned char tx[7] = {0xaa, 0x00, targetAddr, Cmd.query_Present_OutputVoltage, 0x00, 0x00, 0x00};
	unsigned char rx[512];
	unsigned char chksum = 0x00;
	unsigned char len = tranceive(fd, tx, sizeof(tx), rx);

	if(len > 6)
	{
		if (len < 6+(rx[4] | rx[5]<<8))
			return result;

		for(int idx = 0;idx<(rx[4] | rx[5]<<8);idx++)
		{
			chksum ^= rx[6+idx];
		}

		if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
		   (rx[2] == tx[1]) &&
		   (rx[1] == tx[2]) &&
		   (rx[3] == tx[3]))
		{

			Ret_Buf->behindFuse_Voltage_C1 =(rx[6] | (rx[7]<<8));
			Ret_Buf->behindRelay_Voltage_C1 =(rx[8] | (rx[9]<<8));
			if((rx[4] | rx[5]<<8) > 4)
			{
				Ret_Buf->behindFuse_Voltage_C2 =(rx[10] | (rx[11]<<8));
				Ret_Buf->behindRelay_Voltage_C2 =(rx[12] | (rx[13]<<8));
			}
			result = PASS;
		}
	}

	return result;
}

unsigned char Query_Fan_Speed(unsigned char fd, unsigned char targetAddr, FanSpeed *Ret_Buf)
{
	unsigned char result = FAIL;
	unsigned char tx[7] = {0xaa, 0x00, targetAddr, Cmd.query_Fan_Speed, 0x00, 0x00, 0x00};
	unsigned char rx[512];
	unsigned char chksum = 0x00;
	unsigned char len = tranceive(fd, tx, sizeof(tx), rx);

	if(len > 6)
	{
		if (len < 6+(rx[4] | rx[5]<<8))
			return result;

		for(int idx = 0;idx<(rx[4] | rx[5]<<8);idx++)
		{
			chksum ^= rx[6+idx];
		}

		if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
		   (rx[2] == tx[1]) &&
		   (rx[1] == tx[2]) &&
		   (rx[3] == tx[3]))
		{
			for(int idx=0;idx < 4;idx++)
				Ret_Buf->speed[idx] = (rx[6+(2*idx)] | (rx[6+(2*idx)+1]<<8));

			result = PASS;
		}
	}

	return result;
}

unsigned char Query_Temperature(unsigned char fd, unsigned char targetAddr, Temperature *Ret_Buf)
{
	unsigned char result = FAIL;
	unsigned char tx[7] = {0xaa, 0x00, targetAddr, Cmd.query_Temperature, 0x00, 0x00, 0x00};
	unsigned char rx[512];
	unsigned char chksum = 0x00;
	unsigned char len = tranceive(fd, tx, sizeof(tx), rx);

	if(len > 6)
	{
		if (len < 6+(rx[4] | rx[5]<<8))
			return result;

		for(int idx = 0;idx<(rx[4] | rx[5]<<8);idx++)
		{
			chksum ^= rx[6+idx];
		}

		if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
		   (rx[2] == tx[1]) &&
		   (rx[1] == tx[2]) &&
		   (rx[3] == tx[3]))
		{
			for(int idx=0;idx < 4;idx++)
				Ret_Buf->temperature[idx] = rx[6+idx] - 60;

			result = PASS;
		}
	}


	return result;
}

unsigned char Query_Aux_PowerVoltage(unsigned char fd, unsigned char targetAddr, AuxPower *Ret_Buf)
{
	unsigned char result = FAIL;
	unsigned char tx[7] = {0xaa, 0x00, targetAddr, Cmd.query_Aux_PowerVoltage, 0x00, 0x00, 0x00};
	unsigned char rx[512];
	unsigned char chksum = 0x00;
	unsigned char len = tranceive(fd, tx, sizeof(tx), rx);

	if(len > 6)
	{
		if (len < 6+(rx[4] | rx[5]<<8))
			return result;

		for(int idx = 0;idx<(rx[4] | rx[5]<<8);idx++)
		{
			chksum ^= rx[6+idx];
		}

		if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
		   (rx[2] == tx[1]) &&
		   (rx[1] == tx[2]) &&
		   (rx[3] == tx[3]))
		{
			for(int idx=0;idx<(rx[4] | rx[5]<<8);idx++)
				Ret_Buf->voltage[idx] = rx[6+idx];

			result = PASS;
		}
	}

	return result;
}

unsigned char Query_Relay_Output(unsigned char fd, unsigned char targetAddr, Relay *Ret_Buf)
{
	unsigned char result = FAIL;
	unsigned char tx[7] = {0xaa, 0x00, targetAddr, Cmd.query_Relay_Output, 0x00, 0x00, 0x00};
	unsigned char rx[512];
	unsigned char chksum = 0x00;
	unsigned char len = tranceive(fd, tx, sizeof(tx), rx);

	if(len > 6)
	{
		if (len < 6+(rx[4] | rx[5]<<8))
			return result;

		for(int idx = 0;idx<(rx[4] | rx[5]<<8);idx++)
		{
			chksum ^= rx[6+idx];
		}

		if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
		   (rx[2] == tx[1]) &&
		   (rx[1] == tx[2]) &&
		   (rx[3] == tx[3]))
		{
			Ret_Buf->relay_event.bits.AC_Contactor = (rx[6] >> 0) & 0x01;
			Ret_Buf->relay_event.bits.CCS_Precharge = (rx[6] >> 1) & 0x01;

			Ret_Buf->relay_event.bits.Gun1_N = (rx[7] >> 0) & 0x01;
			Ret_Buf->relay_event.bits.Gun1_P = (rx[7] >> 1) & 0x01;
			Ret_Buf->relay_event.bits.Gun1_Parallel_N = (rx[7] >> 2) & 0x01;
			Ret_Buf->relay_event.bits.Gun1_Parallel_P = (rx[7] >> 3) & 0x01;

			Ret_Buf->relay_event.bits.Gun2_N = (rx[8] >> 0) & 0x01;
			Ret_Buf->relay_event.bits.Gun2_P = (rx[8] >> 1) & 0x01;
			result = PASS;
		}
	}

	return result;
}

unsigned char Query_Gfd_Adc(unsigned char fd, unsigned char targetAddr, Gfd *Ret_Buf)
{
	unsigned char result = FAIL;
	unsigned char tx[7] = {0xaa, 0x00, targetAddr, Cmd.query_Gfd_Adc, 0x00, 0x00, 0x00};
	unsigned char rx[512];
	unsigned char chksum = 0x00;
	unsigned char len = tranceive(fd, tx, sizeof(tx), rx);

	if(len > 6)
	{
		if (len < 6+(rx[4] | rx[5]<<8))
			return result;

		for(int idx = 0;idx<(rx[4] | rx[5]<<8);idx++)
		{
			chksum ^= rx[6+idx];
		}

		printf("chksum = %d \n", chksum);
		printf("rx[2] == %d tx[1] = %d \n", rx[2], tx[1]);
		printf("rx[1] == %d tx[2] = %d \n", rx[1], tx[2]);
		printf("rx[3] == %d tx[3] = %d \n", rx[3], tx[3]);
		printf("chksum = %d \n", chksum);
//		if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
//		   (rx[2] == tx[1]) &&
//		   (rx[1] == tx[2]) &&
//		   (rx[3] == tx[3]))
		if(
				   (rx[2] == tx[1]) &&
				   (rx[1] == tx[2]) &&
				   (rx[3] == tx[3]))
		{
			Ret_Buf->Resister = (rx[6] | (rx[7]<<8) | (rx[8]<<16) | (rx[9]<<24));
			Ret_Buf->voltage = rx[10] | (rx[11]<<8);
			Ret_Buf->result = rx[12];

			result = PASS;
		}
	}

	return result;
}

unsigned char Query_Gpio_Input(unsigned char fd, unsigned char targetAddr, Gpio_in *Ret_Buf)
{
	unsigned char result = FAIL;
	unsigned char tx[7] = {0xaa, 0x00, targetAddr, Cmd.query_Gpio_In, 0x00, 0x00, 0x00};
	unsigned char rx[512];
	unsigned char chksum = 0x00;
	unsigned char len = tranceive(fd, tx, sizeof(tx), rx);

	if(len > 6)
	{
		if (len < 6+(rx[4] | rx[5]<<8))
			return result;

		for(int idx = 0;idx<(rx[4] | rx[5]<<8);idx++)
		{
			chksum ^= rx[6+idx];
		}

		if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
		   (rx[2] == tx[1]) &&
		   (rx[1] == tx[2]) &&
		   (rx[3] == tx[3]))
		{
			Ret_Buf->AC_Connector 		= (rx[6] >> 0) & 0x01;
			Ret_Buf->AC_MainBreaker 	= (rx[6] >> 1) & 0x01;
			Ret_Buf->SPD 				= (rx[6] >> 2) & 0x01;
			Ret_Buf->Door_Open 			= (rx[6] >> 3) & 0x01;
			Ret_Buf->GFD[0] 			= (rx[6] >> 4) & 0x01;
			Ret_Buf->GFD[1] 			= (rx[6] >> 5) & 0x01;
			Ret_Buf->AC_Drop 			= (rx[6] >> 6) & 0x01;

			Ret_Buf->Emergency_IO		= (rx[7] >> 0) & 0x01;

			Ret_Buf->Button_Emergency_Press	= (rx[8] >> 0) & 0x01;
			Ret_Buf->Button_On_Press 	= (rx[8] >> 1) & 0x01;
			Ret_Buf->Button_Off_Press	= (rx[8] >> 2) & 0x01;
			Ret_Buf->Key_1_Press 		= (rx[8] >> 3) & 0x01;
			Ret_Buf->Key_2_Press 		= (rx[8] >> 4) & 0x01;
			Ret_Buf->Key_3_Press 		= (rx[8] >> 5) & 0x01;
			Ret_Buf->Key_4_Press 		= (rx[8] >> 6) & 0x01;

			result = PASS;
		}
	}

	return result;
}

unsigned char Config_Fan_Speed(unsigned char fd, unsigned char targetAddr, FanSpeed *Set_Buf)
{
	unsigned char result = FAIL;
	unsigned char tx[9] = {0xaa, 0x00, targetAddr, Cmd.config_Fan_Speed, 0x02, 0x00, Set_Buf->speed[0], Set_Buf->speed[1]};
	unsigned char rx[512];
	unsigned char chksum = 0x00;

	for(int idx = 0;idx<(tx[4] | tx[5]<<8);idx++)
		chksum ^= tx[6+idx];
	tx[9] = chksum;

	unsigned char len = tranceive(fd, tx, sizeof(tx), rx);

	if(len > 6)
	{
		if (len < 6+(rx[4] | rx[5]<<8))
			return result;

		chksum = 0x00;
		for(int idx = 0;idx<(rx[4] | rx[5]<<8);idx++)
		{
			chksum ^= rx[6+idx];
		}

		if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
		   (rx[2] == tx[1]) &&
		   (rx[1] == tx[2]) &&
		   (rx[3] == tx[3]))
		{
			result = PASS;
		}
	}

	return result;
}

unsigned char Config_Relay_Output(unsigned char fd, unsigned char targetAddr, Relay *Set_Buf)
{
	unsigned char result = FAIL;
	unsigned char tx[10] = {0xaa, 0x00, targetAddr, Cmd.config_Relay_Output, 0x03, 0x00, Set_Buf->relay_event.relay_status[0], Set_Buf->relay_event.relay_status[1], Set_Buf->relay_event.relay_status[2]};
	unsigned char rx[512];
	unsigned char chksum = 0x00;

	for(int idx = 0;idx<(tx[4] | tx[5]<<8);idx++)
		chksum ^= tx[6 + idx];

	tx[9] = chksum;

	unsigned char len = tranceive(fd, tx, sizeof(tx), rx);

	if(len > 6)
	{
		if (len < 6+(rx[4] | rx[5]<<8))
			return result;

//      for (int i = 0; i < len; i++)
//          printf("set relay cmd : rx = %x \n", rx[i]);

		chksum = 0x00;

		for(int idx = 0;idx<(rx[4] | rx[5]<<8);idx++)
		{
			chksum ^= rx[6+idx];
		}

		if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
		   (rx[2] == tx[1]) &&
		   (rx[1] == tx[2]) &&
		   (rx[3] == tx[3]) &&
		   rx[6] == PASS)
		{
			result = PASS;
		}
	}

	return result;
}

unsigned char Config_Gfd_Value(unsigned char fd, unsigned char targetAddr, Gfd_config *Set_Buf)
{
	unsigned char result = FAIL;
	unsigned char tx[11] = {0xaa, 0x00, targetAddr, Cmd.config_Gfd_Value, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00};
	unsigned char rx[512];
	unsigned char chksum = 0x00;

	tx[6] = (unsigned char)(Set_Buf->reqVol) & 0xff;
	tx[7] = ((unsigned char)(Set_Buf->reqVol) >> 8) & 0xff;
	tx[8] = (unsigned char)(Set_Buf->resister) & 0xff;
	tx[9] = ((unsigned char)(Set_Buf->resister) >> 8) & 0xff;

	for(int idx = 0;idx<(tx[4] | tx[5]<<8);idx++)
		chksum ^= tx[6+idx];
	tx[10] = chksum;

	unsigned char len = tranceive(fd, tx, sizeof(tx), rx);

	if(len > 6)
	{
		if (len < 6+(rx[4] | rx[5]<<8))
			return result;

		chksum = 0x00;
		for(int idx = 0;idx<(rx[4] | rx[5]<<8);idx++)
		{
			chksum ^= rx[6+idx];
		}

		if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
		   (rx[2] == tx[1]) &&
		   (rx[1] == tx[2]) &&
		   (rx[3] == tx[3]) &&
		   (rx[6] == tx[6]))
		{
			result = PASS;
		}
	}

	return result;
}

unsigned char Update_Start(unsigned char fd, unsigned char targetAddr, unsigned int crc32)
{
	unsigned char result = FAIL;
	unsigned char tx[11] = {0xaa, 0x00, targetAddr, Cmd.update_Start, 0x04, 0x00, (crc32>>0)&0xff, (crc32>>8)&0xff, (crc32>>16)&0xff, (crc32>>24)&0xff, 0x00};
	unsigned char rx[512];
	unsigned char chksum = 0x00;

	for(int idx = 0;idx<(tx[4] | tx[5]<<8);idx++)
		chksum ^= tx[6+idx];
	tx[10] = chksum;

	unsigned char len = tranceive(fd, tx, sizeof(tx), rx);
	if(len > 6)
	{
		if (len < 6+(rx[4] | rx[5]<<8))
			return result;

		chksum = 0x00;
		for(int idx = 0;idx<(rx[4] | rx[5]<<8);idx++)
		{
			chksum ^= rx[6+idx];
		}

		if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
		   (rx[2] == tx[1]) &&
		   (rx[1] == tx[2]) &&
		   (rx[3] == tx[3]) &&
		   (rx[6] == 0x00))
		{
			result = PASS;
		}
	}

	return result;
}

unsigned char Update_Abord(unsigned char fd, unsigned char targetAddr)
{
	unsigned char result = FAIL;
	unsigned char tx[7] = {0xaa, 0x00, targetAddr, Cmd.update_Start, 0x04, 0x00, 0x00};
	unsigned char rx[512];
	unsigned char chksum = 0x00;
	unsigned char len = tranceive(fd, tx, sizeof(tx), rx);

	if(len > 6)
	{
		if (len < 6+(rx[4] | rx[5]<<8))
			return result;

		for(int idx = 0;idx<(rx[4] | rx[5]<<8);idx++)
		{
			chksum ^= rx[6+idx];
		}

		if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
		   (rx[2] == tx[1]) &&
		   (rx[1] == tx[2]) &&
		   (rx[3] == tx[3]) &&
		   (rx[6] == 0x00))
		{
			result = PASS;
		}
	}

	return result;
}

unsigned char Update_Transfer(unsigned char fd, unsigned char targetAddr, unsigned int startAddr, unsigned char *data, unsigned short int length)
{
	unsigned char result = FAIL;
	unsigned char tx[11 + length];
	unsigned char rx[512];
	unsigned char chksum = 0x00;

	tx[0] = 0xaa;
	tx[1] = 0x00;
	tx[2] = targetAddr;
	tx[3] = Cmd.update_Transfer;
	tx[4] = (4 + length) & 0xff;
	tx[5] = ((4 + length)>>8) & 0xff;
	tx[6] = (startAddr>>0) & 0xff;
	tx[7] = (startAddr>>8) & 0xff;
	tx[8] = (startAddr>>16) & 0xff;
	tx[9] = (startAddr>>24) & 0xff;
	memcpy(tx+10, data, length);

	for(int idx = 0;idx<(tx[4] | tx[5]<<8);idx++)
		chksum ^= tx[6+idx];
	tx[sizeof(tx)-1] = chksum;

	unsigned char len = tranceive(fd, tx, sizeof(tx), rx);

	if(len > 6)
	{
		if (len < 6+(rx[4] | rx[5]<<8))
			return result;

		for(int idx = 0;idx<(rx[4] | rx[5]<<8);idx++)
		{
			chksum ^= rx[6+idx];
		}

		if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
		   (rx[2] == tx[1]) &&
		   (rx[1] == tx[2]) &&
		   (rx[3] == tx[3]) &&
		   (rx[6] == 0x00))
		{
			result = PASS;
		}
	}

	return result;
}

unsigned char Update_Finish(unsigned char fd, unsigned char targetAddr)
{
	unsigned char result = FAIL;
	unsigned char tx[7] = {0xaa, 0x00, targetAddr, Cmd.update_Finish, 0x04, 0x00, 0x00};
	unsigned char rx[512];
	unsigned char chksum = 0x00;
	unsigned char len = tranceive(fd, tx, sizeof(tx), rx);

	if(len > 6)
	{
		if (len < 6+(rx[4] | rx[5]<<8))
			return result;

		for(int idx = 0;idx<(rx[4] | rx[5]<<8);idx++)
		{
			chksum ^= rx[6+idx];
		}

		if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
		   (rx[2] == tx[1]) &&
		   (rx[1] == tx[2]) &&
		   (rx[3] == tx[3]) &&
		   (rx[6] == 0x00))
		{
			result = PASS;
		}
	}

	return result;
}

const int System_GPIO_Pin_Table[SYS_GPIO_NUM] =
{
    PIN_AM_OK_FLAG, PIN_IO_BD1_1, PIN_IO_BD1_2, PIN_IO_BD2_1, PIN_IO_BD2_2, PIN_ID_BD1_1, PIN_ID_BD1_2, PIN_ID_BD2_1,
    PIN_ID_BD2_2, PIN_AM_RFID_RST, PIN_AM_RFID_ICC, PIN_BOARD1_PROXIMITY, PIN_BOARD2_PROXIMITY, PIN_AM_DE_1, PIN_AM_RE_1, PIN_ETHERNET_RESET
};

void gpio_export(int pin)
{
    char buffer[64];

    snprintf(buffer, sizeof(buffer), "echo %d > /sys/class/gpio/export", pin);
    system(buffer);
}

void gpio_unexport(int pin)
{
    char buffer[64];

    snprintf(buffer, sizeof(buffer), "echo %d > /sys/class/gpio/unexport", pin);
    system(buffer);
}

void gpio_set_direction(int pin, unsigned char dir)
{
    /*
    char buffer[64];

    snprintf(buffer, sizeof(buffer), "echo %s > /sys/class/gpio/gpio%d/direction", dir == GPIO_DIR_INPUT ? "in" : "out", pin);
    system(buffer);
    */

    int fd;
    char buffer[64];

    snprintf(buffer, sizeof(buffer), "/sys/class/gpio/gpio%d/direction", pin);
    fd = open(buffer, O_WRONLY);
    if (fd < 0)
    {
        gpio_export(pin);

        fd = open(buffer, O_WRONLY);
        if(fd < 0)
        {
            printf("\r\nFailed to open gpio%d direction for writing!", pin);
            return;
        }
    }

    write(fd, dir == GPIO_DIR_INPUT ? "in" : "out", dir == GPIO_DIR_INPUT ? 2 : 3);

    close(fd);
}

void gpio_write(int pin, unsigned char value)
{
    char buffer[64];

    snprintf(buffer, sizeof(buffer), "echo %d > /sys/class/gpio/gpio%d/value", value > 0 ? 1 : 0, pin);
    system(buffer);
}

int gpio_read(int pin)
{
    int fd, value = 0;
    char ch;
    char buffer[64];

    snprintf(buffer, sizeof(buffer), "/sys/class/gpio/gpio%d/value", pin);

    fd = open(buffer, O_RDONLY);
    if (fd < 0)
    {
        return -1;
    }

    if (read(fd, &ch, 4) < 0)
    {
        return -1;
    }

    value = atoi(&ch);

    close(fd);
    return value;
}

int adc_read(int adc_port)
{
    int fd, value = 0;
    char ch[5];
    char buffer[64];

    snprintf(buffer,sizeof(buffer), "/sys/bus/iio/devices/iio:device0/in_voltage%d_raw", adc_port);
    fd = open(buffer, O_RDONLY);

    if(fd < 0)
    {
        return -1;
    }

    if(read(fd, ch, 4) < 0)
    {
        return -1;
    }
    value = atoi(ch);

    close(fd);
    return value;
}

void InitIO(void)
{
    /* GPMC_AD8         =>  GPIO0_22 *//*ID BD1_1*/
    gpio_set_direction(PIN_ID_BD1_1, GPIO_DIR_INPUT);

    /* GPMC_AD9         =>  GPIO0_23 *//*ID BD1_2*/
    gpio_set_direction(PIN_ID_BD1_2, GPIO_DIR_INPUT);

    /* GPMC_AD10        =>  GPIO0_26 *//*IO BD1_1*/
    gpio_set_direction(PIN_IO_BD1_1, GPIO_DIR_OUTPUT);
    gpio_write(PIN_IO_BD1_1, 0);

    /* GPMC_AD11        =>  GPIO0_27 *//*IO BD1_2*/
    gpio_set_direction(PIN_IO_BD1_2, GPIO_DIR_OUTPUT);
    gpio_write(PIN_IO_BD1_2, 0);

    /*XDMA_EVENT_INTR0  =>  GPIO0_19 *//*AM_RFID_RST*/
    gpio_set_direction(PIN_AM_RFID_RST, GPIO_DIR_OUTPUT);
    gpio_write(PIN_AM_RFID_RST, 0);

    /*XDMA_EVENT_INTR1  =>  GPIO0_20 *//*AM_RFID_ICC*/
    gpio_set_direction(PIN_AM_RFID_ICC, GPIO_DIR_OUTPUT);
    gpio_write(PIN_AM_RFID_ICC, 0);

    /* GPMC_AD12    =>  GPIO1_12 *//*ID BD2_1*/
    gpio_set_direction(PIN_ID_BD2_1, GPIO_DIR_INPUT);

    /* GPMC_AD13    =>  GPIO1_13 *//*ID BD2_2*/
    gpio_set_direction(PIN_ID_BD2_2, GPIO_DIR_INPUT);

    /* GPMC_AD14    =>  GPIO1_14 *//*IO BD2_1*/
    gpio_set_direction(PIN_IO_BD2_1, GPIO_DIR_OUTPUT);
    gpio_write(PIN_IO_BD2_1, 0);

    /* GPMC_AD15    =>  GPIO1_15 *//*IO BD2_2*/
    gpio_set_direction(PIN_IO_BD2_2, GPIO_DIR_OUTPUT);
    gpio_write(PIN_IO_BD2_2, 0);

    /* MCASP0_AXR0  =>  GPIO3_16 *//*CSU board function OK indicator.*/
    gpio_set_direction(PIN_AM_OK_FLAG, GPIO_DIR_OUTPUT);
    gpio_write(PIN_AM_OK_FLAG, 0);

    gpio_set_direction(PIN_BOARD1_PROXIMITY, GPIO_DIR_INPUT);

    gpio_set_direction(PIN_BOARD2_PROXIMITY, GPIO_DIR_INPUT);
}

void DeInitIO(void)
{
    gpio_unexport(PIN_ID_BD1_1);
    gpio_unexport(PIN_ID_BD1_2);
    gpio_unexport(PIN_IO_BD1_1);
    gpio_unexport(PIN_IO_BD1_2);
    gpio_unexport(PIN_AM_RFID_RST);
    gpio_unexport(PIN_AM_RFID_ICC);
    gpio_unexport(PIN_ID_BD2_1);
    gpio_unexport(PIN_ID_BD2_2);
    gpio_unexport(PIN_IO_BD2_1);
    gpio_unexport(PIN_IO_BD2_2);
    gpio_unexport(PIN_AM_OK_FLAG);
}

void DoIOTest(void)
{
    InitIO();

    gpio_write(PIN_IO_BD1_1, 1);
    if(gpio_read(PIN_ID_BD1_1) == 1)
    {
        gpio_write(PIN_IO_BD1_1, 0);
        if(gpio_read(PIN_ID_BD1_1) == 0)
        {
            printf("\r\nID_BD1_1 Test OK");
        }
        else
        {
            printf("\r\nID_BD1_1 Low Test Fail");
            return;
        }
    }
    else
    {
        printf("\r\nID_BD1_1 High Test Fail");
        return;
    }

    gpio_write(PIN_IO_BD1_2, 1);
    if(gpio_read(PIN_ID_BD1_2) == 1)
    {
        gpio_write(PIN_IO_BD1_2, 0);
        if(gpio_read(PIN_ID_BD1_2) == 0)
        {
            printf("\r\nID_BD1_2 Test OK");
        }
        else
        {
            printf("\r\nID_BD1_2 Low Test Fail");
            return;
        }
    }
    else
    {
        printf("\r\nID_BD1_2 High Test Fail");
        return;
    }

    gpio_write(PIN_IO_BD2_1, 1);
    if(gpio_read(PIN_ID_BD2_1) == 1)
    {
        gpio_write(PIN_IO_BD2_1, 0);
        if(gpio_read(PIN_ID_BD2_1) == 0)
        {
            printf("\r\nID_BD2_1 Test OK");
        }
        else
        {
            printf("\r\nID_BD2_1 Low Test Fail");
            return;
        }
    }
    else
    {
        printf("\r\nID_BD2_1 High Test Fail");
        return;
    }

    gpio_write(PIN_IO_BD2_2, 1);
    if(gpio_read(PIN_ID_BD2_2) == 1)
    {
        gpio_write(PIN_IO_BD2_2, 0);
        if(gpio_read(PIN_ID_BD2_2) == 0)
        {
            printf("\r\nID_BD2_2 Test OK");
        }
        else
        {
            printf("\r\nID_BD2_2 Low Test Fail");
            return;
        }
    }
    else
    {
        printf("\r\nID_BD2_2 High Test Fail");
        return;
    }

    gpio_write(PIN_AM_RFID_RST, 1);
    if(gpio_read(PIN_BOARD1_PROXIMITY) == 1 && gpio_read(PIN_BOARD2_PROXIMITY) == 1)
    {
        gpio_write(PIN_AM_RFID_RST, 0);
        if(gpio_read(PIN_BOARD1_PROXIMITY) == 0 && gpio_read(PIN_BOARD2_PROXIMITY) == 0)
        {
            printf("\r\nBoard1 & Board2 Proximity Test OK");
        }
        else
        {
            printf("\r\nBoard1 & Board2 Proximity Low Test Fail");
            return;
        }
    }
    else
    {
        printf("\r\nBoard1 & Board2 Proximity High Test Fail");
        return;
    }

    gpio_write(PIN_AM_RFID_ICC, 1);
    usleep(100000);
    if(adc_read(ADC_AIN0) < 100 && adc_read(ADC_AIN1) < 100 && adc_read(ADC_AIN2) < 100 && adc_read(ADC_AIN3) < 100)
    {
        gpio_write(PIN_AM_RFID_ICC, 0);
        usleep(100000);
        if(adc_read(ADC_AIN0) > 4000 && adc_read(ADC_AIN1) > 4000 && adc_read(ADC_AIN2) > 4000 && adc_read(ADC_AIN3) > 4000)
        {
            printf("\r\nAIN0, AIN1, AIN2, AIN3 Test OK");
        }
        else
        {
            printf("\r\nAIN0, AIN1, AIN2, AIN3 High Test Fail");
            return;
        }
    }
    else
    {
        printf("\r\nAIN0, AIN1, AIN2, AIN3 Low Test Fail");
        return;
    }

    gpio_write(PIN_AM_OK_FLAG, 1);

    printf("\r\nIO Test Done!");
    printf("\r\nSuccess!\r\n");
}


int CreatShareMemory()
{
	int MeterSMId;

	//creat ShmSysConfigAndInfo
	if ((MeterSMId = shmget(ShmSysConfigAndInfoKey,	sizeof(struct SysConfigAndInfo), IPC_CREAT | 0777)) < 0)
	{
		#ifdef SystemLogMessage
		//StoreLogMsg("[main]CreatShareMemory:shmget ShmSysConfigAndInfo NG \n");
		#endif
		return 0;
	}
	else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0))	== (void *) -1)
	{
		#ifdef SystemLogMessage
		//StoreLogMsg("[main]CreatShareMemory:shmat ShmSysConfigAndInfo NG \n");
		#endif
		return 0;
	}
	memset(ShmSysConfigAndInfo, 0, sizeof(struct SysConfigAndInfo));
	/*
	if ((MeterSMId = shmget(ShmATEKey, sizeof(struct ATE), IPC_CREAT | 0777)) < 0)
	{
		#ifdef SystemLogMessage
		//StoreLogMsg("[main]CreatShareMemory:shmget ShmPrimaryMcuData NG \n");
		#endif
		return 0;
	}
	else if ((ate = shmat(MeterSMId, NULL, 0)) == (void *) -1)
	{
		#ifdef SystemLogMessage
		//StoreLogMsg("[main]CreatShareMemory:shmat ShmPrimaryMcuData NG \n");
		#endif
		return 0;
	}
	memset(ate, 0, sizeof(struct ATE));
	*/
	//creat ShmCcsData
	if ((MeterSMId = shmget(ShmCcsCommKey, sizeof(struct CcsData),	IPC_CREAT | 0777)) < 0){
		#ifdef SystemLogMessage
			//StoreLogMsg("[main]CreatShareMemory:shmget ShmCcsData NG \n");
		#endif
		return 0;
	}
	else if ((ShmCcsData = shmat(MeterSMId, NULL, 0)) == (void *) -1){
		#ifdef SystemLogMessage
			//StoreLogMsg("[main]CreatShareMemory:shmat ShmCcsData NG \n");
		#endif
		return 0;
	}
	memset(ShmCcsData, 0, sizeof(struct CcsData));
	//creat ShmRelayModuleData
	if ((MeterSMId = shmget(ShmRelayBdKey, sizeof(struct RelayModuleData), IPC_CREAT | 0777)) < 0)
	{
		#ifdef SystemLogMessage
		//StoreLogMsg("shmget ShmRelayModuleData NG\n");
		#endif
		return 0;
	}
	else if ((ShmRelayModuleData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
	{
		#ifdef SystemLogMessage
		//StoreLogMsg("shmat ShmRelayModuleData NG\n");
		#endif
		return 0;
	}
	memset(ShmRelayModuleData, 0, sizeof(struct RelayModuleData));
	return 1;
}

int InitCanBus()
{
    int s0, nbytes;
    struct timeval tv;
    struct ifreq ifr0;
    struct sockaddr_can addr0;
    /*
    //can0
    system("/sbin/ip link set can0 down");//先將interface disable
    system("/sbin/ip link set can0 type can bitrate 500000 restart-ms 100");
    system("/sbin/ip link set can0 up");
    */

    //can1
    system("/sbin/ip link set can0 down");//先將interface disable
    system("/sbin/ip link set can0 type can bitrate 250000 restart-ms 100");
    system("/sbin/ip link set can0 up");

    s0 = socket(PF_CAN, SOCK_RAW, CAN_RAW);
    tv.tv_sec = 0;
    tv.tv_usec = 10000;

    if(setsockopt(s0, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval)) < 0)
    {
        #ifdef SystemLogMessage
            //StoreLogMsg("[CsuComm]InitCanBus:Set SO_RCVTIMEO NG");
        #endif
    }

    nbytes = 40960;

    if(setsockopt(s0, SOL_SOCKET,  SO_RCVBUF, &nbytes, sizeof(int)) < 0)
    {
        #ifdef SystemLogMessage
            //StoreLogMsg("[CsuComm]InitCanBus:Set SO_RCVBUF NG");
        #endif
    }

    nbytes = 40960;

    if(setsockopt(s0, SOL_SOCKET, SO_SNDBUF, &nbytes, sizeof(int)) < 0)
    {
        #ifdef SystemLogMessage
            //StoreLogMsg("[CsuComm]InitCanBus:Set SO_SNDBUF NG");
        #endif
    }

    //strcpy(ifr0.ifr_name, "can0" );
    strcpy(ifr0.ifr_name, "can0" );
    ioctl(s0, SIOCGIFINDEX, &ifr0); /* ifr.ifr_ifindex gets filled with that device's index */
    addr0.can_family = AF_CAN;
    addr0.can_ifindex = ifr0.ifr_ifindex;
    bind(s0, (struct sockaddr *)&addr0, sizeof(addr0));
    return s0;
}

int CHROMAInitCanBus()
{
	int 					s0,nbytes;
		struct timeval			tv;
		struct ifreq 			ifr0;
		struct sockaddr_can		addr0;

		system("/sbin/ip link set can1 down");
		system("/sbin/ip link set can1 type can bitrate 500000 restart-ms 100");
		system("/sbin/ip link set can1 up");

		s0 = socket(PF_CAN, SOCK_RAW, CAN_RAW);

		tv.tv_sec = 0;
		tv.tv_usec = 10000;
	   	if (setsockopt(s0, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct	timeval)) < 0)
		{
			#ifdef SystemLogMessage
			//DEBUG_ERROR("Set SO_RCVTIMEO NG");
			#endif
		}
		nbytes=40960;
		if (setsockopt(s0, SOL_SOCKET,  SO_RCVBUF, &nbytes, sizeof(int)) < 0)
		{
			#ifdef SystemLogMessage
			//DEBUG_ERROR("Set SO_RCVBUF NG");
			#endif
		}
		nbytes=40960;
		if (setsockopt(s0, SOL_SOCKET, SO_SNDBUF, &nbytes, sizeof(int)) < 0)
		{
			#ifdef SystemLogMessage
			//DEBUG_ERROR("Set SO_SNDBUF NG");
			#endif
		}

	   	strcpy(ifr0.ifr_name, "can1" );
		ioctl(s0, SIOCGIFINDEX, &ifr0); /* ifr.ifr_ifindex gets filled with that device's index */
		addr0.can_family = AF_CAN;
		addr0.can_ifindex = ifr0.ifr_ifindex;
		bind(s0, (struct sockaddr *)&addr0, sizeof(addr0));
		return s0;
}
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;
}
unsigned char isATEChange(unsigned char gun_index)
{
	unsigned char result = NO;
	if(chargingInfo[gun_index]->SystemStatus != chargingInfo[gun_index]->PreviousSystemStatus)
	{
		result = YES;
		chargingInfo[gun_index]->PreviousSystemStatus = chargingInfo[gun_index]->SystemStatus;

	}
	return result;
}

unsigned char isATEChange(unsigned char gun_index)
{
	unsigned char result = NO;
	if(chargingInfo[gun_index]->ATEState != chargingInfo[gun_index]->PreviousATEState)
	{
		result = YES;
		chargingInfo[gun_index]->PreviousATEState = chargingInfo[gun_index]->ATEState;

	}
	return result;
}
unsigned char isModeChange(unsigned char gun_index)
{
	unsigned char result = NO;
	if(chargingInfo[gun_index]->SystemStatus != chargingInfo[gun_index]->PreviousSystemStatus)
	{
		result = YES;
		chargingInfo[gun_index]->PreviousSystemStatus = chargingInfo[gun_index]->SystemStatus;

	}
	return result;
}

unsigned char checkMode(byte gun_index, byte mode)
{
	unsigned char result = NO;

	if(chargingInfo[gun_index]->SystemStatus != mode)
	{
		result = YES;

	}
	return result;
}

void setChargerMode(byte gun_index, byte mode)
{
	chargingInfo[gun_index]->SystemStatus = mode;
}

void setATEMode(byte gun_index, byte mode)
{
	chargingInfo[gun_index]->ATEState = mode;
}

void setStatusMode(byte gun_index, byte mode)
{
	chargingInfo[gun_index]->ATEStatus = mode;
}

unsigned char isStatusChange(unsigned char gun_index)
{
	unsigned char result = NO;
	if(chargingInfo[gun_index]->ATEStatus != chargingInfo[gun_index]->PreviousATEStatus)
	{
		result = YES;
		chargingInfo[gun_index]->PreviousATEStatus = chargingInfo[gun_index]->ATEStatus;

	}
	return result;
}

// AC 三相輸入電壓
void GetPresentInputVol()
{
	if (Query_Present_InputVoltage(Uart5Fd, Addr.Relay, &inputVoltage) == PASS)
	{
		// resolution : 0.1
//		printf("InputVoltageR = %f \n", inputVoltage.L1N_L12);
//		printf("InputVoltageS = %f \n", inputVoltage.L2N_L23);
//		printf("InputVoltageT = %f \n", inputVoltage.L3N_L31);

		ShmRelayModuleData->InputL1Volt = inputVoltage.L1N_L12;
		ShmRelayModuleData->InputL2Volt = inputVoltage.L2N_L23;
		ShmRelayModuleData->InputL3Volt = inputVoltage.L3N_L31;

		//********************************************************************************************************//
		// VIN < 170
		if (inputVoltage.L1N_L12 < VIN_MIN_VOLTAGE)
		{
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP = 0x01;
		}
		if (inputVoltage.L2N_L23 < VIN_MIN_VOLTAGE)
		{
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP = 0x01;
		}
		if (inputVoltage.L3N_L31 < VIN_MIN_VOLTAGE)
		{
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP = 0x01;
		}

		//********************************************************************************************************//
		// VIN > 250
		if (inputVoltage.L1N_L12 > VIN_MAX_VOLTAGE)
		{
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP = 0x01;
		}
		if (inputVoltage.L2N_L23 > VIN_MAX_VOLTAGE)
		{
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP = 0x01;
		}
		if (inputVoltage.L3N_L31 > VIN_MAX_VOLTAGE)
		{
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP = 0x01;
		}
		//********************************************************************************************************//
		// VIN < 150
		if (inputVoltage.L1N_L12 < VIN_DROP_VOLTAGE)
		{
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputDrop = 0x01;
		}
		if (inputVoltage.L2N_L23 < VIN_DROP_VOLTAGE)
		{
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputDrop = 0x01;
		}
		if (inputVoltage.L3N_L31 < VIN_DROP_VOLTAGE)
		{
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputDrop = 0x01;
		}
	}
}
// 左右槍的 Relay 前後的輸出電壓
void GetPersentOutputVol()
{
	if (Query_Present_OutputVoltage(Uart5Fd, Addr.Relay, &outputVoltage) == PASS)
	{
		printf("Conn1 fuse 1 = %f \n", outputVoltage.behindFuse_Voltage_C1);
		printf("Conn1 relay 1 = %f \n", outputVoltage.behindRelay_Voltage_C1);
		printf("Conn2 fuse 2 = %f \n", outputVoltage.behindFuse_Voltage_C2);
		printf("Conn2 relay 2 = %f \n", outputVoltage.behindRelay_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;

		printf("FuseChargingVoltage 1 = %d \n", ShmRelayModuleData->Gun1FuseOutputVolt);
		printf("FuseChargingVoltage 2 = %d \n", ShmRelayModuleData->Gun1RelayOutputVolt);
		printf("FuseChargingVoltage 1 = %d \n", ShmRelayModuleData->Gun2FuseOutputVolt);
		printf("FuseChargingVoltage 2 = %d \n", ShmRelayModuleData->Gun2RelayOutputVolt);
		/*
		for (int index = 0; index < gunCount; index++)
		{
			if (index == 0)
			{
				if (chargingInfo[index]->Evboard_id == 0x01)
				{
					chargingInfo[index]->FuseChargingVoltage = ShmRelayModuleData->Gun1FuseOutputVolt;
					chargingInfo[index]->FireChargingVoltage = ShmRelayModuleData->Gun1RelayOutputVolt;
				}
				else if (chargingInfo[index]->Evboard_id == 0x02)
				{
					chargingInfo[index]->FuseChargingVoltage = ShmRelayModuleData->Gun2FuseOutputVolt;
					chargingInfo[index]->FireChargingVoltage = ShmRelayModuleData->Gun2RelayOutputVolt;
				}
			}
			else if (index == 1)
			{
				chargingInfo[index]->FuseChargingVoltage = ShmRelayModuleData->Gun2FuseOutputVolt;
				chargingInfo[index]->FireChargingVoltage = ShmRelayModuleData->Gun2RelayOutputVolt;
			}*/
			/*
			unsigned short Ovp = 0;
			unsigned short Ocp = 0;
			//Ovp = MIN [VOUT_MAX_VOLTAGE, EV_BATTERY_VOLTAGE] 	// 最大輸出電壓與電池電壓最大值
			//Ocp = MIN [IOUT_MAX_CURRENT, EV_CURRENT_REQ]		// 最大輸出電流與需求電流最小值

			if (chargingInfo[index]->Type == _Type_Chademo)
			{
				Ovp = MaxValue(chargingInfo[index]->MaximumChargingVoltage, chargingInfo[index]->EvBatteryMaxVoltage);
				Ocp = MaxValue(chargingInfo[index]->PresentChargingCurrent, ShmCHAdeMOData->ev[chargingInfo[index]->type_index].ChargingCurrentRequest);
				if (chargingInfo[index]->FireChargingVoltage >= Ovp)
				{
					//ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemChademoOutputOVP = 0x01;
				}
				if (chargingInfo[index]->PresentChargingCurrent >= Ocp)
				{
					//ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemChademoOutputOCP = 0x01;
				}
			}
			else if (chargingInfo[index]->Type == _Type_CCS)
			{

			}
			*/
		//}
	}
}

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


// relay 的狀態
void CheckRelayOutput(byte index)
{
	if (index == 0)
	{
		//printf("=====%d\n",chargingInfo[index]->Evboard_id);
		if (chargingInfo[index]->Evboard_id == 0x01)
		{
			if (regRelay.relay_event.bits.Gun1_N == YES && regRelay.relay_event.bits.Gun1_P == YES)
				chargingInfo[0]->RelayK1K2Status = YES;
			else
				chargingInfo[0]->RelayK1K2Status = NO;

			if (regRelay.relay_event.bits.Gun1_N == YES	&& regRelay.relay_event.bits.CCS_Precharge == YES)
				chargingInfo[0]->RelayKPK2Status = YES;
			else
				chargingInfo[0]->RelayKPK2Status = NO;
		}
		else if (chargingInfo[index]->Evboard_id == 0x02)
		{
			if (regRelay.relay_event.bits.Gun2_N == YES && regRelay.relay_event.bits.Gun2_P == YES)
				chargingInfo[0]->RelayK1K2Status = YES;
			else
				chargingInfo[0]->RelayK1K2Status = NO;

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

		if (regRelay.relay_event.bits.Gun2_N == YES && regRelay.relay_event.bits.CCS_Precharge == YES)
			chargingInfo[1]->RelayKPK2Status = YES;
		else
			chargingInfo[1]->RelayKPK2Status = NO;
	}
}


void SetOutputGpio(byte flash)
{
    Gpio_out gpio;
    gpio.Button_LED[0] = 0x00;
    gpio.Button_LED[1] = 0x00;

    gpio.System_LED[0] = flash;
    gpio.System_LED[1] = 0x00;
    gpio.System_LED[2] = 0x00;
    gpio.System_LED[3] = flash;

    gpio.AC_Connector = 0x00;
    gpio.AC_Breaker = 0x00;

    if (Config_Gpio_Output(Uart1Fd, Addr.IoExtend, &gpio) == PASS)
    {
        //PRINTF_FUNC("SetOutputGpio sucessfully. %d \n", flash);
    }
    else
    {
        //PRINTF_FUNC("SetOutputGpio fail. \n");
    }
}

//==========================================
// Common Function
//==========================================
void SetEvContactorRelayStatus(byte index)
{
	// 為安全起見~ 切換該槍 relay 的條件一是 relay 前後電壓須都要小於 10V
	// 除了做完 CCS 端的 Precharge,因為在做完 Precharge後,車端會直接直接準備拉載,輸出並不會降低
	// 另一個是 Complete 狀態,因為火線上的電壓有可能是來自車端電池電壓,導致火線上的電壓並不會降下來
	// 於此同時,只要判斷火線上的電流低於 1A 來判斷 Relay 可鬆開
	/*
	if (chargingInfo[index]->SystemStatus != V_ISOLATION &&
			chargingInfo[index]->SystemStatus != S_COMPLETE )
	{
		if (index == 0 && (ShmRelayModuleData->Gun1FuseOutputVolt > 600 || ShmRelayModuleData->Gun1RelayOutputVolt > 600))
		{
				return;
		}

	}
	*/


	if(ShmSysConfigAndInfo->ate.ATEState == 1){
		if(chargingInfo[index]->SystemStatus >= V_ISOLATION){
			if(chargingInfo[index]->Evboard_id == 0x01)
			{
				// 先搭 D-
				if (outputRelay.relay_event.bits.Gun1_N == 0x00)
					outputRelay.relay_event.bits.Gun1_N = 0x01;
				else
					outputRelay.relay_event.bits.Gun1_P = 0x01;


				if (outputRelay.relay_event.bits.Gun2_N == 0x00)
					outputRelay.relay_event.bits.Gun2_N = 0x01;
				else
					outputRelay.relay_event.bits.Gun2_P = 0x01;

				flash = YES;
				SetOutputGpio(flash);
			}

		}else{
			if (chargingInfo[index]->Evboard_id == 0x01)
			{
				// 先釋放 D+
				if (outputRelay.relay_event.bits.Gun1_P == 0x01)
					outputRelay.relay_event.bits.Gun1_P = 0x00;
				else
					outputRelay.relay_event.bits.Gun1_N = 0x00;

				if (outputRelay.relay_event.bits.Gun2_P == 0x01)
					outputRelay.relay_event.bits.Gun2_P = 0x00;
				else
					outputRelay.relay_event.bits.Gun2_N = 0x00;

				flash = NO;
				SetOutputGpio(flash);
			}
		}
	}else if(ShmSysConfigAndInfo->ate.ATEState == 2){
		if(ShmSysConfigAndInfo->ate.chademo.id0D_req.K1K2Status == 1){
			if(chargingInfo[index]->Evboard_id == 0x01){
				if (outputRelay.relay_event.bits.Gun1_Parallel_N == 0x00)
					outputRelay.relay_event.bits.Gun1_Parallel_N = 0x01;
				else
					outputRelay.relay_event.bits.Gun1_Parallel_P = 0x01;

				flash = YES;
				SetOutputGpio(flash);
			}
		}else{
			if (chargingInfo[index]->Evboard_id == 0x01){
				if (outputRelay.relay_event.bits.Gun1_Parallel_P == 0x01)
					outputRelay.relay_event.bits.Gun1_Parallel_P = 0x00;
				else
					outputRelay.relay_event.bits.Gun1_Parallel_N = 0x00;
				flash = NO;
				SetOutputGpio(flash);
			}
		}
	}
}

int PackageIdCmd(int cmd)
{
	return cmd | 0x80000000;
}

void SendCmdToEvboard(int canfd, int cmd, byte *data, byte dataLen)
{
    struct can_frame frame;
    frame.can_id = PackageIdCmd(cmd);//(0x00001000 + cmd) | 0x80000000;//(cmd | 0x80000000);
    frame.can_dlc = dataLen;
    memcpy(frame.data, data, sizeof(frame.data));
    write(canfd, &frame, sizeof(struct can_frame));
    usleep(2000);
}

void setBootNotification1(){
	byte data[8];
	data[0] = 0x02;
	data[1] = 0x02;
	data[2] = 0x02;
	data[3] = 0x02;
	data[4] = 0x03;
	data[5] = 0x03;
	data[6] = 0x03;
	data[7] = 0x03;
	SendCmdToEvboard(CanFd2, bn1, data, sizeof(data));
}

void setBootNotification2(){
	byte data[8];
	data[0] = 0x04;
	data[1] = 0x04;
	data[2] = 0x04;
	data[3] = 0x04;
	data[4] = 0x05;
	data[5] = 0x05;
	data[6] = 0x05;
	data[7] = 0x05;
	SendCmdToEvboard(CanFd2, bn2, data, sizeof(data));
}

void setEVStatus1(byte evstatus){
	byte data[1];
	data[0] =  evstatus;
	SendCmdToEvboard(CanFd2, EVStatus1, data, sizeof(data));
}

void setEVStatus2(){
	byte data[1];
	data[0] = 0x02;
	SendCmdToEvboard(CanFd2, EVStatus2, data, sizeof(data));
}

void GetFirmwareVersion(byte gun_index, byte toId)
{
	int id = PackageIdCmd(Ev_Cmd.get_firmware_ver + toId);
	byte data[8];

	SendCmdToEvboard(CanFd, id, data, 0);
}

void GetHardwareVersion(byte gun_index, byte toId)
{
	int id = PackageIdCmd(Ev_Cmd.get_hardware_ver + toId);
	byte data[8];

	SendCmdToEvboard(CanFd, id, data, 0);
}

void SetChargingPermission(byte gun_index, byte permissionStatus, short aOutputPw, short aOutputCur, short aOutputVol, byte toId)
{
	int id = PackageIdCmd(Ev_Cmd.charging_permission + toId);
	byte data[8];

	data[0] = permissionStatus;
	data[1] = aOutputPw & 0xff;
	data[2] = (aOutputPw >> 8) & 0xff;
	data[3] = aOutputCur & 0xff;
	data[4] = (aOutputCur >> 8) & 0xff;
	data[5] = aOutputVol & 0xff;
	data[6] = (aOutputVol >> 8) & 0xff;
	data[7] = 0xff;
	//printf(" ChargingPermission Get-Msg : %08X - %02x %02x %02x %02x %02x %02x %02x %02x\n ",(Ev_Cmd.charging_permission + toId), data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7] );

	SendCmdToEvboard(CanFd, id, data, sizeof(data));
}

void GetMiscellaneousInfo(byte gun_index, byte toId, short K1K2Status, short soc)
{
	int id = PackageIdCmd(Ev_Cmd.get_miscellaneous_info + toId);
	byte data[8];
	data[0] = 0x01;
	data[1] = 0x02;
	data[2] = 0x03;
	data[3] = 0x04;
	data[4] = 0x05;
	data[5] = K1K2Status & 0xff;
	data[6] = soc & 0xff;
	data[7] = 0x08;
	//printf(" Miscellaneous Info Get-Msg : %08X - %02x %02x %02x %02x %02x %02x %02x %02x\n ",Ev_Cmd.get_miscellaneous_info, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7] );

	/*
	data[1] = 0x0001;
	data[2] = 0x0001;
	data[3] = 0x10;
	data[4] = 0x10;
	*/
	SendCmdToEvboard(CanFd, id, data, sizeof(data));
}
void setMisc(byte toId){

	float K1K2Status = 0;
	float soc = 0;
	K1K2Status = ShmSysConfigAndInfo->ate.chademo.id0D_req.K1K2Status;
	soc = ShmSysConfigAndInfo->ate.chademo.id0D_req.Soc;
	GetMiscellaneousInfo(0, toId, K1K2Status, soc);
}

void SetPresentInputPower(short outputVol_b1, short outputCur_b1, byte toId)
{
	int id = PackageIdCmd(Ev_Cmd.present_input_power + toId);
	byte data[8];

	data[0] = outputVol_b1 & 0xff;
	data[1] = (outputVol_b1 >> 8) & 0xff;
	data[2] = outputCur_b1 & 0xff;
	data[3] = (outputCur_b1 >> 8) & 0xff;
	/*
	data[4] = outputVol_b2 & 0xff;
	data[5] = (outputVol_b2 >> 8) & 0xff;
	data[6] = outputCur_b2 & 0xff;
	data[7] = (outputCur_b2 >> 8) & 0xff;
	*/
	//printf(" PresentInputPower Get-Msg : %08X - %02x %02x %02x %02x %02x %02x %02x %02x\n ",Ev_Cmd.present_input_power, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7] );
	SendCmdToEvboard(CanFd, id, data, sizeof(data));
}


void SetPresentInputRequirement(short aOutputPw_b1, short aOutputCur_b1, short aOutputPw_b2, short aOutputCur_b2, byte toId)
{
	int id = PackageIdCmd(Ev_Cmd.present_input_requirement + toId );
	byte data[8];

	data[0] = aOutputPw_b1 & 0xff;
	data[1] = (aOutputPw_b1 >> 8) & 0xff;
	data[2] = aOutputCur_b1 & 0xff;
	data[3] = (aOutputCur_b1 >> 8) & 0xff;
	data[4] = aOutputPw_b2 & 0xff;
	data[5] = (aOutputPw_b2 >> 8) & 0xff;
	data[6] = aOutputCur_b2 & 0xff;
	data[7] = 0x01;
	/*
	data[6] = aOutputCur_b2 & 0xff;
	data[7] = (aOutputCur_b2 >> 8) & 0xff;
	*/

	//printf(" Present Input Requirement Get-Msg : %08X - %02x %02x %02x %02x %02x %02x %02x %02x\n ",Ev_Cmd.present_input_requirement, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7] );

	SendCmdToEvboard(CanFd, id, data, sizeof(data));
}

void GetEvseOutputStatus(byte gun_index, byte toId)
{
	int id = PackageIdCmd(Ev_Cmd.get_evse_output_status + toId);
	byte data[8];

	SendCmdToEvboard(CanFd, id, data, 0);
}

void GetEvseCapacityInfo(byte gun_index, byte toId)
{
	int id = PackageIdCmd(Ev_Cmd.get_evse_capacity_info + toId);
	byte data[8];

	SendCmdToEvboard(CanFd, id, data, 0);
}

void EvseStopChargingEvent(byte stopResult, byte *stopReason, byte toId)
{
	int id = PackageIdCmd(Ev_Cmd.evse_stop_charging + toId);
	byte data[8];

	data[0] = stopResult;
	data[1] = *stopReason;
	data[2] = *(stopReason + 1);
	data[3] = *(stopReason + 2);
	data[4] = *(stopReason + 3);
	data[5] = *(stopReason + 4);
	data[6] = *(stopReason + 5);

	SendCmdToEvboard(CanFd, id, data, sizeof(data));
}


void SetIsolationStatus(byte gun_index, byte result, byte toId)
{
	int id = PackageIdCmd(Ev_Cmd.isolation_status + toId);
	byte data[8];
	data[0] = result;
	SendCmdToEvboard(CanFd, id, data, 1);
}

void SetEvsePrechargeInfo(byte gun_index, byte result, byte toId)
{
	int id = PackageIdCmd(Ev_Cmd.evse_precharge_info + toId);
	byte data[8];

	data[0] = result;
	SendCmdToEvboard(CanFd, id, data, 1);
}

void handleEmulatorFaultStatus(){
	setEVStatus2(evstaus[4]);
	ShmSysConfigAndInfo->ate.Permission = STOP;
	setStatusMode(CCS_QUANTITY, ShmSysConfigAndInfo->ate.Permission);
	ShmSysConfigAndInfo->ate.ATEStatus = 0x00;
	EvseStopChargingEvent(normalStop, stopReason, 1);
	SetChargingPermission(CCS_QUANTITY, ShmSysConfigAndInfo->ate.Permission, ShmSysConfigAndInfo->ate.TotalBatteryCap,
			ShmSysConfigAndInfo->ate.MaxBatteryCurrent, ShmSysConfigAndInfo->ate.MaxBatteryVoltage, 1);
}
int SpawnTask()
{
	system("/root/Module_VCCU &");
	return PASS;
}

void KillTask()
{
	system("killall Module_VCCU");
}
int bitExtracted(byte number, int k, int p)
{
    return (((1 << k) - 1) & (number >> (p - 1)));
}

unsigned short bitextract(unsigned short value, int begin, int end)
{
	unsigned short mask = (1 << (end - begin)) - 1;
    return (value >> begin) & mask;
}

//接收can
void CANReceiver()
{
	pid_t canRecPid;
	canRecPid = fork();
	if(canRecPid > 0){
		int nbytes;
		struct can_frame frame;
		int intCmd;
		while (1){
			//清空 canbus recever buf
			memset(&frame, 0, sizeof(struct can_frame));
			//讀取 canbus 是否有接收到封包
			nbytes = read(CanFd, &frame, sizeof(struct can_frame));
			//如果有收到 canbus 封包
			if (nbytes > 0){
				intCmd = (int) (frame.can_id & CAN_EFF_MASK);//extended frame format
							#ifdef Debug
								//printf("hsout0StatusChange Get-INFYPWR-Msg : %08x - %02x %02x %02x %02x %02x %02x %02x %02x\n ", intCmd, frame.data[0], frame.data[1], frame.data[2], frame.data[3],frame.data[4], frame.data[5], frame.data[6], frame.data[7] );
								//printf(" Get-Msg : %08X - %02x %02x %02x %02x %02x %02x %02x %02x\n ", frame.can_id, frame.data[0], frame.data[1], frame.data[2], frame.data[3],frame.data[4], frame.data[5], frame.data[6], frame.data[7] );
							#endif
				//printf("hsout0StatusChange Get-INFYPWR-Msg : %08x - %02x %02x %02x %02x %02x %02x %02x %02x\n ", frame.can_id, frame.data[0], frame.data[1], frame.data[2], frame.data[3],frame.data[4], frame.data[5], frame.data[6], frame.data[7] );
				//printf("Ack none defined. intCmd = %08x  \n", intCmd);
				switch (intCmd){
					case VCCU_ChargeFromVehicleId:{
						//memcpy(&ShmSysConfigAndInfo->ate.vccu.chargeFromVehicle, &frame.data, frame.can_dlc);

						ShmSysConfigAndInfo->ate.vccu.chargeFromVehicle.VCCU_Vehicle_ContactorVoltage = ((short) frame.data[1] << 8) + (short) frame.data[0];
						ShmSysConfigAndInfo->ate.vccu.chargeFromVehicle.VCCU_Vehicle_LinkVoltage = ((short) frame.data[3] << 8) + (short) frame.data[2];
						ShmSysConfigAndInfo->ate.vccu.chargeFromVehicle.DATA.bits.VCCU_Vehicle_IsolationMeasurem = bitextract(frame.data[4],0, 2);//((short) frame.data[4] >> 0)+((short) frame.data[4] >> 1);//((short) frame.data[4] << 2);
						ShmSysConfigAndInfo->ate.vccu.chargeFromVehicle.DATA.bits.VCCU_Vehicle_PlugLockPermissio = bitextract(frame.data[4],2, 4);//((short) frame.data[4] >> 2)+((short) frame.data[4] >> 3);
						ShmSysConfigAndInfo->ate.vccu.chargeFromVehicle.DATA.bits.VCCU_Vehicle_PlugUnlockPermiss = bitextract(frame.data[4],4, 6);//((short) frame.data[4] >> 4)+((short) frame.data[4] >> 5);
						ShmSysConfigAndInfo->ate.vccu.chargeFromVehicle.DATA.bits.VCCU_Vehicle_ChargePermission  = bitextract(frame.data[4],6, 8);//((short) frame.data[4] >> 6)+((short) frame.data[4] >> 7);
						ShmSysConfigAndInfo->ate.vccu.chargeFromVehicle.bits.VCCU_Vehicle_ContactorStatus  = bitextract(frame.data[5],0, 2);

						//memset(&ShmSysConfigAndInfo->ate.vccu.chargeFromVehicle,*frame.data, frame.can_dlc);
					    //printf("hsout0StatusChange Get-INFYPWR-Msg : %08x - %02x %02x %02x %02x %02x %02x %02x %02x\n ", frame.can_id, frame.data[0], frame.data[1], frame.data[2], frame.data[3],frame.data[4], frame.data[5], frame.data[6], frame.data[7] );
						break;
					}
					case VCCU_ControlPilotStatusId:{
						//memcpy(&ShmSysConfigAndInfo->ate.vccu.controlPilotStatus, &frame.data, frame.can_dlc);
						ShmSysConfigAndInfo->ate.vccu.controlPilotStatus.ControlPilot_Frequency.bits.VCCU_ControlPilot_Frequency = ((short) frame.data[1] << 8) + (short) frame.data[0];
						ShmSysConfigAndInfo->ate.vccu.controlPilotStatus.ControlPilot_DutyCycle.bits.value = ((short) frame.data[2] ) ;
						ShmSysConfigAndInfo->ate.vccu.controlPilotStatus.ControlPilot_Voltage.bits.value = ((short) frame.data[3] << 8) + (short) frame.data[4];
						ShmSysConfigAndInfo->ate.vccu.controlPilotStatus.DATA.bits.VCCU_ControlPilot_Wakeup = bitextract(((short) (frame.data[5])), 0, 2);
						ShmSysConfigAndInfo->ate.vccu.controlPilotStatus.DATA.bits.VCCU_ChargeUnit_Mode = bitextract(frame.data[5],2, 5);
						ShmSysConfigAndInfo->ate.vccu.controlPilotStatus.DATA.bits.VCCU_ChargeUnit_State = bitextract(((short) (frame.data[5])), 5, 8);
						ShmSysConfigAndInfo->ate.vccu.controlPilotStatus.ChargeUnit_MaxCurrent = ((short) frame.data[6] );
						//memset(&ShmSysConfigAndInfo->ate.vccu.controlPilotStatus.ControlPilot_Voltage,frame.data[5], frame.can_dlc);
						//printf("VCCU_ControlPilotStatus Get-INFYPWR-Msg : %08x - %02x %02x %02x %02x %02x %02x %02x \n ", intCmd, frame.data[0], frame.data[1], frame.data[2], frame.data[3],frame.data[4], frame.data[5], frame.data[6] );
						break;
					}
					case VCCU_V2G_StateMId:{
						//memcpy(&ShmSysConfigAndInfo->ate.vccu.v2g_StateM, &frame.data, frame.can_dlc);
						ShmSysConfigAndInfo->ate.vccu.v2g_StateM.VCCU_V2G_StateM_EnergyTransfer = (short) frame.data[0];
						ShmSysConfigAndInfo->ate.vccu.v2g_StateM.VCCU_V2G_StateM_StateMachineEr = (short) frame.data[1];
						ShmSysConfigAndInfo->ate.vccu.v2g_StateM.VCCU_V2G_StateM_StateMachineMe = (short) frame.data[2];
						ShmSysConfigAndInfo->ate.vccu.v2g_StateM.VCCU_V2G_StateM_StateMachineSt = (short) frame.data[3];
						ShmSysConfigAndInfo->ate.vccu.v2g_StateM.DATA.bits.VCCU_V2G_StateM_InternetAvaila = bitextract(frame.data[4],0, 1);
						ShmSysConfigAndInfo->ate.vccu.v2g_StateM.DATA.bits.VCCU_V2G_Appl_SccChargeModeReq = bitextract(frame.data[4],1, 4);
						ShmSysConfigAndInfo->ate.vccu.v2g_StateM.DATA.bits.VCCU_V2G_Appl_SccFuncModeReq = bitextract(frame.data[4],4, 6);
						//memset(&ShmSysConfigAndInfo->ate.vccu.v2g_StateM.VCCU_V2G_StateM_StateMachineSt,*frame.data, frame.can_dlc);
						//printf("VCCU_ControlPilotStatus Get-INFYPWR-Msg : %08x - %02x %02x %02x %02x %02x %02x %02x %02x\n ", intCmd, frame.data[0], frame.data[1], frame.data[2], frame.data[3],frame.data[4], frame.data[5], frame.data[6], frame.data[7] );
						break;
					}
					case VCCU_InletStatusId:{
						//memcpy(&ShmSysConfigAndInfo->ate.vccu.inletStatus, &frame.data, frame.can_dlc);
						ShmSysConfigAndInfo->ate.vccu.inletStatus.VCCU_POSFeedback_Voltage = ((short) frame.data[1] << 8) + (short) frame.data[0];
						ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA2.VCCU_PlugPresent_SelfDiagnosti = bitextract(frame.data[2],0, 3);
						ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA2.VCCU_PlugPresent_Resistance = bitextract(frame.data[2],3, 6);
						ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA2.VCCU_PlugPresent_Status = bitextract(frame.data[2],6, 8);
						ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA3.VCCU_PlugPresent_Wakeup = bitextract(frame.data[3],0, 2);
						ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA3.VCCU_POSFeedback_SelfDiagnosti = bitextract(frame.data[3],2, 5);
						ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA3.VCCU_PlugLock_MotorStatus = bitextract(frame.data[3],5, 8);
						ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA4.VCCU_PlugLock_Output0_SelfDiag = bitextract(frame.data[4],0, 3);
						ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA4.VCCU_PlugLock_Output1_SelfDiag = bitextract(frame.data[4],3, 6);
						ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA4.VCCU_Inlet_HWVariant = bitextract(frame.data[4],6, 8);
						ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA5.bits.VCCU_DigitalInput_Status = bitextract(frame.data[5],0, 2);
						ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA5.bits.VCCU_DigitalInput_Wakeup = bitextract(frame.data[5],2, 4);
						ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA5.bits.VCCU_Inlet_MotorStatus = bitextract(frame.data[5],4, 7);
						ShmSysConfigAndInfo->ate.vccu.inletStatus.VCCU_Inlet_MaxCurrent = (short) frame.data[6];
						ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA7.bits.VCCU_DigitalInput_DebouncedSta = bitextract(frame.data[7],0, 2);
						ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA7.bits.VCCU_Inlet_ConnectionStatus = bitextract(frame.data[7],2, 4);
						ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA7.bits.VCCU_S3Switch_Status = bitextract(frame.data[7],4, 6);
						ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA7.bits.VCCU_S3Switch_DebouncedStatus = bitextract(frame.data[7],6, 8);
						//memset(&ShmSysConfigAndInfo->ate.vccu.inletStatus,*frame.data, frame.can_dlc);
						//printf("VCCU_ControlPilotStatus Get-INFYPWR-Msg : %08x - %02x %02x %02x %02x %02x %02x %02x %02x\n ", intCmd, frame.data[0], frame.data[1], frame.data[2], frame.data[3],frame.data[4], frame.data[5], frame.data[6], frame.data[7] );
						break;
					}
					case VCCU_ChargeToVehicleId:{
						//memcpy(&ShmSysConfigAndInfo->ate.vccu.chargeToVehicle, &frame.data, frame.can_dlc);
						//ShmSysConfigAndInfo->ate.vccu.chargeToVehicle.Data.bits.VCCU_Vehicle_IsolationMea_0000 = bitextract(frame.data[0],0, 2);
						ShmSysConfigAndInfo->ate.vccu.chargeToVehicle.bits.VCCU_Vehicle_IsolationMea_0000 = bitextract(frame.data[0],0, 2);
						ShmSysConfigAndInfo->ate.vccu.chargeToVehicle.bits.VCCU_Vehicle_ContactorRequest = bitextract(frame.data[0],2, 4);
						//memset(&ShmSysConfigAndInfo->ate.vccu.chargeToVehicle,*frame.data, frame.can_dlc);
						//printf("VCCU_ControlPilotStatus Get-INFYPWR-Msg : %08x - %02x %02x %02x %02x %02x %02x %02x %02x\n ", intCmd, frame.data[0], frame.data[1], frame.data[2], frame.data[3],frame.data[4], frame.data[5], frame.data[6], frame.data[7] );
						break;
					}
					case VCCU_V2G_EVMaximumVoltageLimitId:{
						//memcpy(&ShmSysConfigAndInfo->ate.vccu.v2g_EVMaximumVoltageLimit, &frame.data, frame.can_dlc);
						//memset(&ShmSysConfigAndInfo->ate.vccu.v2g_EVMaximumVoltageLimit,*frame.data, frame.can_dlc);
						break;
					}
					case VCCU_V2G_EVMaximumCurrentLimitId:{
						//memcpy(&ShmSysConfigAndInfo->ate.vccu.v2g_EVMaximumCurrentLimit, &frame.data, frame.can_dlc);
						//memset(&ShmSysConfigAndInfo->ate.vccu.v2g_EVMaximumCurrentLimit,*frame.data, frame.can_dlc);
						break;
					}
					case VCCU_V2G_EVTargetCurrentId:{
						//memcpy(&ShmSysConfigAndInfo->ate.vccu.v2g_EVTargetCurrent, &frame.data, frame.can_dlc);
						//memset(&ShmSysConfigAndInfo->ate.vccu.v2g_EVTargetCurrent,*frame.data, frame.can_dlc);
						break;
					}
					case VCCU_V2G_EVTargetVoltageId:{
						//memcpy(&ShmSysConfigAndInfo->ate.vccu.v2g_EVTargetVoltage, &frame.data, frame.can_dlc);
						//memset(&ShmSysConfigAndInfo->ate.vccu.v2g_EVTargetVoltage,*frame.data, frame.can_dlc);
						break;
					}case EV_BOARD_STATUS_NOTIFICATION:
					{
						ShmSysConfigAndInfo->ate.chademo.id03.ProximitySignal = frame.data[2];
						ShmSysConfigAndInfo->ate.chademo.id03.state = frame.data[3];
						break;
					}
					case ACK_EV_FW_VERSION:
					{
						break;
					}
					case ACK_EV_HW_VERSION:
					{
						printf("Get EV HW = %s \n", frame.data);
						break;
					}
					case ACK__GET_EVSE_OUTPUT_STATUS:
					{
						//printf(" Get EVSE output status Get-Msg : %08X - %02x %02x %02x %02x %02x %02x %02x %02x\n ", frame.can_id, frame.data[0], frame.data[1], frame.data[2], frame.data[3],frame.data[4], frame.data[5], frame.data[6], frame.data[7] );
						ShmSysConfigAndInfo->ate.chademo.id09_ack.DcEvState = frame.data[0];//EV模擬器
						ShmSysConfigAndInfo->ate.chademo.id09_ack.ChargingMode = frame.data[1];
						ShmSysConfigAndInfo->ate.chademo.id09_ack.EvsePresentOutputVoltage = ((short) frame.data[3] << 8) + (short) frame.data[2];//充電樁輸出電壓
						ShmSysConfigAndInfo->ate.chademo.id09_ack.EvsePresentOutputCurrent = ((short) frame.data[5] << 8) + (short) frame.data[4];//充電樁輸出電流
						ShmSysConfigAndInfo->ate.chademo.id09_ack.RemainingTimeSec = ((short) frame.data[7] << 8) + (short) frame.data[6];//剩餘時間

						break;
					}

					case ACK_GET_EVSE_Capacity_INFO:
					{
						//printf(" Get EVSE Capacity Information Get-Msg : %08X - %02x %02x %02x %02x %02x %02x %02x %02x\n ", frame.can_id, frame.data[0], frame.data[1], frame.data[2], frame.data[3],frame.data[4], frame.data[5], frame.data[6], frame.data[7] );
						ShmSysConfigAndInfo->ate.chademo.id0A_ack.EvseMaxChargeVoltage = ((short) frame.data[1] << 8) + (short) frame.data[0];//樁的最大電壓
						ShmSysConfigAndInfo->ate.chademo.id0A_ack.EvseMaxChargeCurrent = ((short) frame.data[3] << 8) + (short) frame.data[2];//樁的最大電流
						ShmSysConfigAndInfo->ate.chademo.id0A_ack.EvseMinChargeVoltage = ((short) frame.data[5] << 8) + (short) frame.data[4];
						ShmSysConfigAndInfo->ate.chademo.id0A_ack.EvseMinChargeCurrent = ((short) frame.data[7] << 8) + (short) frame.data[6];

						break;
					}
					case ACK_GET_MISCELLANEOUS_INFO:
					{
						ShmSysConfigAndInfo->ate.chademo.id0D_ack.K1K2OnOff = frame.data[5];
						if(ShmSysConfigAndInfo->ate.chademo.relaystatus == 0){
							ShmSysConfigAndInfo->ate.chademo.id0D_req.K1K2Status = ShmSysConfigAndInfo->ate.chademo.id0D_ack.K1K2OnOff;
						}

						break;
					}
					case ACK_EVSE_ISOLATION_STATUS: { break;}
					case ACK_EVSE_PRECHAGE_INFO:
					{
						//_chargingData[targetGun]->PrechargeStatus = frame.data[0];
						break;
					}

					case NOTIFICATION_EV_STOP:
					{
						ShmSysConfigAndInfo->ate.chademo.id0B.EvStopReason = frame.data[0];
						ShmSysConfigAndInfo->ate.chademo.id0B.AlarmCode1 = frame.data[1];
						ShmSysConfigAndInfo->ate.chademo.id0B.AlarmCode2 = frame.data[2];
						ShmSysConfigAndInfo->ate.chademo.id0B.AlarmCode3 = frame.data[3];
						ShmSysConfigAndInfo->ate.chademo.id0B.AlarmCode4 = frame.data[4];
						ShmSysConfigAndInfo->ate.chademo.id0B.AlarmCode5 = frame.data[5];
						ShmSysConfigAndInfo->ate.chademo.id0B.AlarmCode6 = frame.data[6];
						setEVStatus2(evstaus[4]);
						ShmSysConfigAndInfo->ate.Permission = STOP;
						setStatusMode(CCS_QUANTITY, ShmSysConfigAndInfo->ate.Permission);
						ShmSysConfigAndInfo->ate.ATEStatus = 0x00;
						SetChargingPermission(CCS_QUANTITY, ShmSysConfigAndInfo->ate.Permission, ShmSysConfigAndInfo->ate.TotalBatteryCap, ShmSysConfigAndInfo->ate.MaxBatteryCurrent, ShmSysConfigAndInfo->ate.MaxBatteryVoltage, 1);
						EvseStopChargingEvent(normalStop, stopReason, 1);

						break;
					}

					default:
						break;
				}
			}
			usleep(2000);
			//usleep(100000);
		}
	}
}

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

    fd = open(priPortName, O_RDWR);
    if(fd<=0)
    {
        #ifdef SystemLogMessage
        //DEBUG_ERROR("open 407 Communication port NG \n");
        #endif
        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]=(unsigned char)1;
    tios.c_lflag=0;
    tcflush(fd, TCIFLUSH);
    ioctl (fd, TCSETS, &tios);

    return fd;
}

//接收can
void CHROMACANReceiver()
{
	pid_t canRecPid;
	canRecPid = fork();
	if(canRecPid > 0){
		int nbytes;
		struct can_frame frame;
		int intCmd;
		while (1){
			//清空 canbus recever buf
			memset(&frame, 0, sizeof(struct can_frame));
			//讀取 canbus 是否有接收到封包
			nbytes = read(CanFd2, &frame, sizeof(struct can_frame));
			//如果有收到 canbus 封包
			if (nbytes > 0){
				intCmd = (int) (frame.can_id & CAN_EFF_MASK);//extended frame format
						#ifdef Debug
							//printf("hsout0StatusChange Get-INFYPWR-Msg : %08x - %02x %02x %02x %02x %02x %02x %02x %02x\n ", intCmd, frame.data[0], frame.data[1], frame.data[2], frame.data[3],frame.data[4], frame.data[5], frame.data[6], frame.data[7] );
							//printf(" Get-Msg : %08X - %02x %02x %02x %02x %02x %02x %02x %02x\n ", frame.can_id, frame.data[0], frame.data[1], frame.data[2], frame.data[3],frame.data[4], frame.data[5], frame.data[6], frame.data[7] );
						#endif
				//printf("hsout0StatusChange Get-INFYPWR-Msg : %08x - %02x %02x %02x %02x %02x %02x %02x %02x\n ", frame.can_id, frame.data[0], frame.data[1], frame.data[2], frame.data[3],frame.data[4], frame.data[5], frame.data[6], frame.data[7] );
				//printf("Ack none defined. intCmd = %08x  \n", intCmd);
				switch (intCmd){
					case bn_res1:{
						ShmSysConfigAndInfo->ate.ATEState = (short) frame.data[0];
						setATEMode(CCS_QUANTITY, ShmSysConfigAndInfo->ate.ATEState);
						//printf(" Get-Msg : %08X - %02x %02x %02x %02x %02x %02x %02x %02x\n ", frame.can_id, frame.data[0], frame.data[1], frame.data[2], frame.data[3],frame.data[4], frame.data[5], frame.data[6], frame.data[7] );
						break;
					}
					case bn_res2:{
						//printf(" Get-Msg : %08X - %02x %02x %02x %02x %02x %02x %02x %02x\n ", frame.can_id, frame.data[0], frame.data[1], frame.data[2], frame.data[3],frame.data[4], frame.data[5], frame.data[6], frame.data[7] );
						break;
					}
					case ATE_Connector2:{
						/*
						ShmSysConfigAndInfo->ate.chroma.ate_Connector_2.TargetVoltage =  ((short) frame.data[1] << 8) + (short) frame.data[0];//
						ShmSysConfigAndInfo->ate.chroma.ate_Connector_2.TargetCurrent =  ((short) frame.data[3] << 8) + (short) frame.data[2];//
						ShmSysConfigAndInfo->ate.chroma.ate_Connector_2.PresentVoltage  = ((short) frame.data[5] << 8) + (short) frame.data[4];
						ShmSysConfigAndInfo->ate.chroma.ate_Connector_2.PresentCurrent = ((short) frame.data[7] << 8) + (short) frame.data[6];
						//ShmSysConfigAndInfo->ate.linkVoltage = ShmSysConfigAndInfo->ate.chroma.ate_Connector_2.PresentVoltage;
						ShmSysConfigAndInfo->ate.targetVoltage_Value = ((short) frame.data[1] << 8) + (short) frame.data[0];
						ShmSysConfigAndInfo->ate.targetCurrent_Value = ((short) frame.data[3] << 8) + (short) frame.data[2];
						//ShmSysConfigAndInfo->ate.maximumVoltage_value = ShmSysConfigAndInfo->ate.targetVoltage_Value+(ShmSysConfigAndInfo->ate.targetVoltage_Value*0.1);
						ShmSysConfigAndInfo->ate.maximumVoltage_value = ShmSysConfigAndInfo->ate.targetVoltage_Value+10;
						ShmSysConfigAndInfo->ate.linkVoltage = ShmSysConfigAndInfo->ate.targetVoltage_Value;
						*/
						//printf("targetVoltage_Value= %d targetCurrent_Value =%d maximumVoltage_value = %d linkVoltage = %d \n",ShmSysConfigAndInfo->ate.targetVoltage_Value, ShmSysConfigAndInfo->ate.targetCurrent_Value, ShmSysConfigAndInfo->ate.maximumVoltage_value, ShmSysConfigAndInfo->ate.linkVoltage);
						//printf("ATE_Connector2 Get-Msg : %08X - %02x %02x %02x %02x %02x %02x %02x %02x %d %d %d %d %d %d  \n ", frame.can_id, frame.data[0], frame.data[1], frame.data[2], frame.data[3],frame.data[4], frame.data[5], frame.data[6], frame.data[7], ShmSysConfigAndInfo->ate.chroma.ate_Connector_2.TargetVoltage, ShmSysConfigAndInfo->ate.chroma.ate_Connector_2.TargetCurrent, ShmSysConfigAndInfo->ate.chroma.ate_Connector_2.PresentVoltage, ShmSysConfigAndInfo->ate.chroma.ate_Connector_2.PresentCurrent, ShmSysConfigAndInfo->ate.targetVoltage_Value, ShmSysConfigAndInfo->ate.targetCurrent_Value);
						break;
					}
					case ATE_Connector1:{

						if(ShmSysConfigAndInfo->ate.ATEState == 1){
							ShmSysConfigAndInfo->ate.chroma.ate_Connector_1.TargetVoltage =  ((short) frame.data[1] << 8) + (short) frame.data[0];//
							ShmSysConfigAndInfo->ate.chroma.ate_Connector_1.TargetCurrent =  ((short) frame.data[3] << 8) + (short) frame.data[2];//
							ShmSysConfigAndInfo->ate.chroma.ate_Connector_1.PresentVoltage  = ((short) frame.data[5] << 8) + (short) frame.data[4];
							ShmSysConfigAndInfo->ate.chroma.ate_Connector_1.PresentCurrent = ((short) frame.data[7] << 8) + (short) frame.data[6];
							//ShmSysConfigAndInfo->ate.linkVoltage = ShmSysConfigAndInfo->ate.chroma.ate_Connector_1.PresentVoltage;
							ShmSysConfigAndInfo->ate.targetVoltage_Value = ((short) frame.data[1] << 8) + (short) frame.data[0];
							ShmSysConfigAndInfo->ate.targetCurrent_Value = ((short) frame.data[3] << 8) + (short) frame.data[2];
							//ShmSysConfigAndInfo->ate.maximumVoltage_value = ShmSysConfigAndInfo->ate.targetVoltage_Value+(ShmSysConfigAndInfo->ate.targetVoltage_Value*0.1);
							ShmSysConfigAndInfo->ate.maximumVoltage_value = ShmSysConfigAndInfo->ate.targetVoltage_Value+10;
							ShmSysConfigAndInfo->ate.linkVoltage = ShmSysConfigAndInfo->ate.targetVoltage_Value;
						}else if (ShmSysConfigAndInfo->ate.ATEState == 2){

						}
						//printf("targetVoltage_Value= %d targetCurrent_Value =%d maximumVoltage_value = %d linkVoltage = %d \n",ShmSysConfigAndInfo->ate.targetVoltage_Value, ShmSysConfigAndInfo->ate.targetCurrent_Value, ShmSysConfigAndInfo->ate.maximumVoltage_value, ShmSysConfigAndInfo->ate.linkVoltage);
						//printf("ATE_Connector1 Get-Msg : %08X - %02x %02x %02x %02x %02x %02x %02x %02x %d %d %d %d %d %d  \n ", frame.can_id, frame.data[0], frame.data[1], frame.data[2], frame.data[3],frame.data[4], frame.data[5], frame.data[6], frame.data[7], ShmSysConfigAndInfo->ate.chroma.ate_Connector_1.TargetVoltage, ShmSysConfigAndInfo->ate.chroma.ate_Connector_1.TargetCurrent, ShmSysConfigAndInfo->ate.chroma.ate_Connector_1.PresentVoltage, ShmSysConfigAndInfo->ate.chroma.ate_Connector_1.PresentCurrent, ShmSysConfigAndInfo->ate.targetVoltage_Value, ShmSysConfigAndInfo->ate.targetCurrent_Value );
						break;
					}

					default:

					break;
				}
			}
			usleep(2000);
			//usleep(100000);
		}
	}
}

void VCCU_TD(){
	byte data[8];
	data[0] = 0x00;
	data[1] = 0x00;
	data[2] = 0x01;
	data[3] = 0x01;
	data[4] = 0x00;
	data[5] = 0x00;
	data[6] = 0x42;
	data[7] = 0x66;
	SendCmdToEvboard(CanFd, TDId, data, sizeof(data));
}

void VCCU_ChargeFromVehicle(int canfd, int linkVoltage, int contactorVoltage,
		int chargePermission, int isolationMeasurem,
		int plugLockPermissio, int plugUnlockPermiss, int contactorStatus){
	struct VCCU_ChargeFromVehicle obj;
	obj.VCCU_Vehicle_LinkVoltage= linkVoltage;//500
	obj.VCCU_Vehicle_ContactorVoltage = contactorVoltage;//0
	obj.DATA.bits.VCCU_Vehicle_ChargePermission = chargePermission;//Not_allowed
	obj.DATA.bits.VCCU_Vehicle_IsolationMeasurem = isolationMeasurem;//Active
	obj.DATA.bits.VCCU_Vehicle_PlugLockPermissio = plugLockPermissio;//Allowed//Not_allowed;
	obj.DATA.bits.VCCU_Vehicle_PlugUnlockPermiss = plugUnlockPermiss;//Not_allowed
	obj.bits.VCCU_Vehicle_ContactorStatus = contactorStatus;//Open
	obj.bits.VCCU_Vehicle_StopCharge = 0;//Open
	obj.bits.VCCU_Vehicle_ChargeSelection = 0;//Open
	byte* data1;
	data1 = (byte*) &(*((UWORD *) &obj.VCCU_Vehicle_ContactorVoltage));
	byte* data2;
	data2 = (byte*) &(*((UWORD *) &obj.VCCU_Vehicle_LinkVoltage));
	byte data[6];
	data[0] = data1[0];
	data[1] = data1[1];
	data[2] = data2[0];
	data[3] = data2[1];
	data[4] = *((UBYTE *) &obj.DATA);
	data[5] = *((UBYTE *) &obj.bits);
	//printf("%02x %02x %02x %02x %02x %02x  \n", data[0], data[1], data[2], data[3], data[4], data[5] );
	SendCmdToEvboard(canfd, VCCU_ChargeFromVehicleIds, data, sizeof(data));
}

//0x18FF3082
void VCCU_V2G_VehicleStatus(int canfd, int EnergyTra, int EVErrorCode,
		int EVPowerDeliveryParame, int EVRESSSOC,
		int EVRESSConditioningFla, int EVRESSConditionin, int EVReady,
		int BulkChargingCompleteF, int EVCabinConditioningFl, int EVCabinConditioning,
		int ChargingComplete, int FullSOCFlag, int FullSOC,
		int BulkSOCFlag, int BulkSOC, int BulkChargingComplete,
		int BulkChargingCompleteFValue){
	struct VCCU_V2G_VehicleStatus obj;
	obj.DATA4.VCCU_V2G_StateM_EnergyTra_0000 = EnergyTra;//VCCU_V2G_StateM_EnergyTra_0000_DC_DC_extended;
	obj.DATA1.VCCU_V2G_EVErrorCode = EVErrorCode;//0;
	obj.DATA4.VCCU_V2G_EVPowerDeliveryParame = EVPowerDeliveryParame;//3;
	obj.VCCU_V2G_EVRESSSOC.value = EVRESSSOC;//0;
	obj.DATA3.VCCU_V2G_EVRESSConditioningFla = EVRESSConditioningFla;//3;
	obj.DATA3.VCCU_V2G_EVRESSConditioning = EVRESSConditionin;//3;
	obj.DATA3.VCCU_V2G_EVReady = EVReady;//3;
	obj.DATA1.VCCU_V2G_BulkChargingCompleteF = BulkChargingCompleteF;//3;
	obj.DATA3.VCCU_V2G_EVCabinConditioningFl = EVCabinConditioningFl;//3;
	obj.DATA2.VCCU_V2G_EVCabinConditioning = EVCabinConditioning;//3;
	obj.DATA2.VCCU_V2G_ChargingComplete = ChargingComplete;//3;
	obj.DATA2.VCCU_V2G_FullSOCFlag = FullSOCFlag;//0;
	obj.VCCU_V2G_FullSOC.value = FullSOC;//3;
	obj.DATA2.VCCU_V2G_BulkSOCFlag = BulkSOCFlag;//3;
	obj.VCCU_V2G_BulkSOC.value = BulkSOC;//0;
	obj.DATA1.VCCU_V2G_BulkChargingComplete = BulkChargingComplete;//3;
	obj.DATA1.VCCU_V2G_BulkChargingCompleteF = BulkChargingCompleteFValue;//3;
	byte data[7];
	data[0] = *((UBYTE *) &obj.DATA1);
	data[1] = *((UBYTE *) &obj.DATA2);
	data[2] = *((UBYTE *) &obj.DATA3);
	data[3] = *((UBYTE *) &obj.DATA4);
	data[4] = *((UBYTE *) &obj.VCCU_V2G_BulkSOC);
	data[5] = *((UBYTE *) &obj.VCCU_V2G_FullSOC);
	data[6] = *((UBYTE *) &obj.VCCU_V2G_EVRESSSOC);
	//printf("%02x %02x %02x %02x %02x %02x %02x  \n", data[0], data[1], data[2], data[3], data[4], data[5] , data[6]);
	SendCmdToEvboard(canfd, VCCU_V2G_VehicleStatusIds, data, sizeof(data));
}

void VCCU_V2G_EVMaximumVoltageLimit(int VMaximumVoltageLimit,
		int EVMaximumVoltage_0002,
		int EVMaximumVoltage_0000,
		int EVMaximumVoltage_0001,
		int EVMaximumVoltage_0003){
	struct VCCU_V2G_EVMaximumVoltageLimit obj;
	obj.DATA1.VCCU_V2G_EVMaximumVoltageLimit = VMaximumVoltageLimit;//1
	obj.DATA1.VCCU_V2G_EVMaximumVoltage_0002 = EVMaximumVoltage_0002;//5
	obj.VCCU_V2G_EVMaximumVoltage_0000.value = EVMaximumVoltage_0000;//520
	obj.VCCU_V2G_EVMaximumVoltage_0001.value = EVMaximumVoltage_0001;//1
	obj.VCCU_V2G_EVMaximumVoltage_0003.value = EVMaximumVoltage_0003;//0
	byte* data1;
	data1 = (byte*) &(*((UWORD *) &obj.VCCU_V2G_EVMaximumVoltage_0000));
	byte data[5];
	data[0] = *((UBYTE *) &obj.DATA1);
	data[1] = *((UBYTE *) &obj.VCCU_V2G_EVMaximumVoltage_0003);
	data[2] = data1[0];
	data[3] = data1[1];
	data[4] = *((UBYTE *) &obj.VCCU_V2G_EVMaximumVoltage_0001);
	//printf("%02x %02x %02x %02x %02x \n", data[0], data[1], data[2], data[3], data[4]);
	SendCmdToEvboard(CanFd, VCCU_V2G_EVMaximumVoltageLimitIds, data, sizeof(data));
}

void VCCU_V2G_EVMaximumCurrentLimit(int EVMaximumCurrentLimit,
		int EVMaximumCurrent_0000,
		int EVMaximumCurrent_0001,
		int EVMaximumCurrent_0002,
		int EVMaximumCurrent_0003){
	struct VCCU_V2G_EVMaximumCurrentLimit obj;
	obj.DATA1.VCCU_V2G_EVMaximumCurrentLimit = EVMaximumCurrentLimit;//1
	obj.DATA1.VCCU_V2G_EVMaximumCurrent_0000 = EVMaximumCurrent_0000;//3
	obj.VCCU_V2G_EVMaximumCurrent_0001.value = EVMaximumCurrent_0001;//1
	obj.VCCU_V2G_EVMaximumCurrent_0002.value = EVMaximumCurrent_0002;//0
	obj.VCCU_V2G_EVMaximumCurrent_0003.value = EVMaximumCurrent_0003;//10
	byte* data1;
	data1 = (byte*) &(*((UWORD *) &obj.VCCU_V2G_EVMaximumCurrent_0003));
	byte data[5];
	data[0] = *((UBYTE *) &obj.DATA1);
	data[1] = *((UBYTE *) &obj.VCCU_V2G_EVMaximumCurrent_0002);
	data[2] = data1[0];
	data[3] = data1[1];
	data[4] = *((UBYTE *) &obj.VCCU_V2G_EVMaximumCurrent_0001);
	//printf("%02x %02x %02x %02x %02x \n", data[0], data[1], data[2], data[3], data[4]);
	SendCmdToEvboard(CanFd, VCCU_V2G_EVMaximumCurrentLimitIds, data, sizeof(data));
}

void VCCU_V2G_EVTargetCurrent(int EVTargetCurrent_Unit,
		int EVTargetCurrent_Value,
		int EVTargetCurrent_UnitF,
		int EVTargetCurrent_Multi){//05 00 00 01 03
	struct VCCU_V2G_EVTargetCurrent obj;
	obj.VCCU_V2G_EVTargetCurrent_Unit.value = EVTargetCurrent_Unit;//3
	obj.VCCU_V2G_EVTargetCurrent_Value.value = EVTargetCurrent_Value;//5
	obj.VCCU_V2G_EVTargetCurrent_UnitF.value = EVTargetCurrent_UnitF;//1
	obj.VCCU_V2G_EVTargetCurrent_Multi.value = EVTargetCurrent_Multi;//0
	byte* data1;
	data1 = (byte*) &(*((UWORD *) &obj.VCCU_V2G_EVTargetCurrent_Value));
	byte data[5];
	data[0] = data1[0];
	data[1] = data1[1];
	data[2] = *((UBYTE *) &obj.VCCU_V2G_EVTargetCurrent_Multi);
	data[3] = *((UBYTE *) &obj.VCCU_V2G_EVTargetCurrent_UnitF);
	data[4] = *((UBYTE *) &obj.VCCU_V2G_EVTargetCurrent_Unit);
	//printf("%02x %02x %02x %02x %02x \n", data[0], data[1], data[2], data[3], data[4]);
	SendCmdToEvboard(CanFd, VCCU_V2G_EVTargetCurrentIds, data, sizeof(data));
}

void VCCU_V2G_EVTargetVoltage(int EVTargetVoltage_Value,
		int EVTargetVoltage_Unit,
		int EVTargetVoltage_UnitF,
		int EVTargetVoltage_Multi){//C2 01 00 01 05
	struct VCCU_V2G_EVTargetVoltage obj;
	obj.VCCU_V2G_EVTargetVoltage_Value.value = EVTargetVoltage_Value;//450
	obj.VCCU_V2G_EVTargetVoltage_Unit.value = EVTargetVoltage_Unit;//5
	obj.VCCU_V2G_EVTargetVoltage_UnitF.value = EVTargetVoltage_UnitF;//1
	obj.VCCU_V2G_EVTargetVoltage_Multi.value = EVTargetVoltage_Multi;//0
	byte* data1;
	data1 = (byte*) &(*((UWORD *) &obj.VCCU_V2G_EVTargetVoltage_Value));
	byte data[5];
	data[0] = data1[0];
	data[1] = data1[1];
	data[2] = *((UBYTE *) &obj.VCCU_V2G_EVTargetVoltage_Multi);
	data[3] = *((UBYTE *) &obj.VCCU_V2G_EVTargetVoltage_UnitF);
	data[4] = *((UBYTE *) &obj.VCCU_V2G_EVTargetVoltage_Unit);
	//printf("%d %02x %02x \n",obj.VCCU_V2G_EVTargetVoltage_Value.value, data[0], data[1]);
	//printf("%02x %02x %02x %02x %02x \n", data[0], data[1], data[2], data[3], data[4]);
	SendCmdToEvboard(CanFd, VCCU_V2G_EVTargetVoltageIds, data, sizeof(data));
}

void VCCU_Requests(int LED0, int LED1, int LED2,
		int HighSideOut0, int HighSideOut1, int HighSideOut2, int HighSideOut3,
		int HighSideOut4, int RTC, int PlugLock,
		int ControlPilot, int ChargeUnit, int Inlet){
	struct VCCU_Requests obj;
	obj.VCCU_LED0_Request.value = LED0;
	obj.VCCU_LED1_Request.value = LED1;
	obj.VCCU_LED2_Request.value = LED2;
	obj.DATA4.VCCU_HighSideOut0_Request = HighSideOut0;
	obj.DATA4.VCCU_HighSideOut1_Request = HighSideOut1;
	obj.DATA4.VCCU_HighSideOut2_Request = HighSideOut2;
	obj.DATA4.VCCU_HighSideOut3_Request = HighSideOut3;
	obj.DATA5.VCCU_HighSideOut4_Request = HighSideOut4;
	obj.DATA5.VCCU_RTC_TimerRequest = RTC;
	obj.DATA5.VCCU_PlugLock_MotorRequest = PlugLock;
	obj.DATA7.VCCU_ControlPilot_ChargeModeRe = ControlPilot;
	obj.DATA7.VCCU_ChargeUnit_Request = ChargeUnit;
	obj.DATA7.VCCU_Inlet_MotorRequest = Inlet;
	byte data[7];
	data[0] = *((UBYTE *) &obj.VCCU_LED0_Request);
	data[1] = *((UBYTE *) &obj.VCCU_LED1_Request);
	data[2] = *((UBYTE *) &obj.VCCU_LED2_Request);
	data[3] = *((UBYTE *) &obj.DATA4);
	data[4] = *((UBYTE *) &obj.DATA5);
	data[5] = *((UBYTE *) &obj.VCCU_RTC_TimerValue);
	data[6] = *((UBYTE *) &obj.DATA7);
	printf("%02x %02x %02x %02x %02x %02x %02x  \n", data[0], data[1], data[2], data[3], data[4], data[5] , data[6]);
	//SendCmdToEvboard(CanFd, VCCU_RequestsIds, data, sizeof(data));
}

bool MatedPlugInletUnlocked_Status(){
	return (ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA2.VCCU_PlugPresent_Status == VCCU_InletStatus_Connected &&
			ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA7.bits.VCCU_Inlet_ConnectionStatus == VCCU_InletStatus_Connected &&
			//ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA5.bits.VCCU_Inlet_MotorStatus == Unlocked &&
			ShmSysConfigAndInfo->ate.vccu.controlPilotStatus.DATA.bits.VCCU_ChargeUnit_State == EVSEStateB2 &&
			ShmSysConfigAndInfo->ate.vccu.controlPilotStatus.DATA.bits.VCCU_ChargeUnit_Mode == ChargeV2G
			//&& ShmSysConfigAndInfo->ate.vccu.controlPilotStatus.VCCU_ControlPilot_Voltage - 32000 == 9
			);
}

bool PreCharge_Statue(){
	return ((ShmSysConfigAndInfo->ate.vccu.v2g_StateM.VCCU_V2G_StateM_StateMachineSt == PreCharge ) &&
			ShmSysConfigAndInfo->ate.vccu.controlPilotStatus.DATA.bits.VCCU_ChargeUnit_State == EVSEStateC &&
			//(ShmSysConfigAndInfo->ate.vccu.controlPilotStatus.ControlPilot_Voltage.bits.value / 2) == 6 &&
			ShmSysConfigAndInfo->ate.vccu.chargeToVehicle.bits.VCCU_Vehicle_IsolationMea_0000 == Not_requested);
}

bool status1(){

	bool result = false;
	result = (ShmSysConfigAndInfo->ate.vccu.chargeFromVehicle.DATA.bits.VCCU_Vehicle_PlugLockPermissio == Allowed
			&& ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA5.bits.VCCU_Inlet_MotorStatus == VCCU_Unlocked &&
			((chargingInfo[CCS_QUANTITY]->PlugPresentStatusDuration >= 2) && chargingInfo[CCS_QUANTITY]->DutyCycleDuration >= 2));
	return result;
}

bool status2(){
	bool result = false;
	result = ((ShmSysConfigAndInfo->ate.vccu.controlPilotStatus.ControlPilot_DutyCycle.bits.value >= 5
			&& ShmSysConfigAndInfo->ate.vccu.controlPilotStatus.ControlPilot_DutyCycle.bits.value <= 7)
			&& ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA5.bits.VCCU_Inlet_MotorStatus == Locked
			&& ShmSysConfigAndInfo->ate.vccu.controlPilotStatus.DATA.bits.VCCU_ChargeUnit_Mode == EVSEStateB2
			&& ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA5.bits.VCCU_DigitalInput_Status == Not_pressed
			&& ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA7.bits.VCCU_S3Switch_Status == Not_pressed);
	return result;
}

bool  UnmatedPlug(){
	bool result = false;
	/*
	printf("VCCU_V2G_StateM_StateMachineSt = %d VCCU_ChargeUnit_State = %d VCCU_ChargeUnit_Mode = %d VCCU_Vehicle_ContactorRequest = %d VCCU_Vehicle_IsolationMea_0000 = %d \n", ShmSysConfigAndInfo->ate.vccu.v2g_StateM.VCCU_V2G_StateM_StateMachineSt,
			ShmSysConfigAndInfo->ate.vccu.controlPilotStatus.DATA.bits.VCCU_ChargeUnit_State,
			ShmSysConfigAndInfo->ate.vccu.controlPilotStatus.DATA.bits.VCCU_ChargeUnit_Mode,
			ShmSysConfigAndInfo->ate.vccu.chargeToVehicle.Data.bits.VCCU_Vehicle_ContactorRequest,
			ShmSysConfigAndInfo->ate.vccu.chargeToVehicle.Data.bits.VCCU_Vehicle_IsolationMea_0000);
			*/
	if(ShmSysConfigAndInfo->ate.vccu.v2g_StateM.VCCU_V2G_StateM_StateMachineSt == StateM_Initialized &&
					//ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA2.VCCU_PlugPresent_Status == VCCU_InletStatus_Not_connected &&
					//ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA7.bits.VCCU_Inlet_ConnectionStatus == VCCU_InletStatus_Not_connected &&
					//ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA5.bits.VCCU_Inlet_MotorStatus == Unlocked &&
					(ShmSysConfigAndInfo->ate.vccu.controlPilotStatus.DATA.bits.VCCU_ChargeUnit_State == EVSEStateA ||
							ShmSysConfigAndInfo->ate.vccu.controlPilotStatus.DATA.bits.VCCU_ChargeUnit_State == EVSEStateE ||
							ShmSysConfigAndInfo->ate.vccu.controlPilotStatus.DATA.bits.VCCU_ChargeUnit_State == EVSEStateB1) &&
					ShmSysConfigAndInfo->ate.vccu.controlPilotStatus.DATA.bits.VCCU_ChargeUnit_Mode == VCCU_ChargeUnit_Mode_SNA &&
					//ShmSysConfigAndInfo->ate.vccu.controlPilotStatus.VCCU_ControlPilot_Voltage == 0 &&
					ShmSysConfigAndInfo->ate.vccu.chargeToVehicle.bits.VCCU_Vehicle_ContactorRequest == ForceOpen &&
					ShmSysConfigAndInfo->ate.vccu.chargeToVehicle.bits.VCCU_Vehicle_IsolationMea_0000 == Requested ){
		//TODO
		result = true;
		//printf("CCS DC01....................\n");
		//VCCU_ChargeFromVehicle(CanFd, 500, 0, Not_allowed, Active, Not_allowed, Not_allowed, Opened);
		setChargerMode(CCS_QUANTITY, V_UNMATEDPLUG);
	}

	return result;
}

bool MatedPlugInletUnlocked(){
	bool result = false;
	if(MatedPlugInletUnlocked_Status() && chargingInfo[CCS_QUANTITY]->SystemStatus == V_IDLE){//(DC02) Mated Plug - Inlet Unlocked
		//TODO
		result = true;
		//VCCU_ChargeFromVehicle(CanFd, 500, 0, Not_allowed, Active, Allowed, Not_allowed, Opened);
		setChargerMode(CCS_QUANTITY, V_MATED_PLUG_INLET_UNLOCKED);
	}
	return result;
}

bool InletLocking(){
	bool result = false;

	if(//ShmSysConfigAndInfo->ate.vccu.controlPilotStatus.DATA.bits.VCCU_ChargeUnit_State == EVSEStateB2
			status1() &&
			ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA5.bits.VCCU_Inlet_MotorStatus == VCCU_Inlet_MotorStatus_Moving
			){//(DC03) Inlet Locking
		result = true;
		//printf("CCS DC03....................\n");
		/*
		if(ShmSysConfigAndInfo->ate.vccu.chargeFromVehicle.DATA.bits.VCCU_Vehicle_PlugLockPermissio == Allowed &&
				ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA2.VCCU_PlugPresent_Status == VCCU_InletStatus_Connected &&//PlugPresent_Status == Connected for >=2s
				//ShmSysConfigAndInfo->ate.vccu.controlPilotStatus.VCCU_ControlPilot_DutyCycle && //ControlPilot_DutyCycle == valid for >= 2s
				ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA5.bits.VCCU_Inlet_MotorStatus == Unlocked){

		}*/
		setChargerMode(CCS_QUANTITY, V_INLETLOCKING);
	}
	return result;
}

bool InletLocked(){
	bool result = false;
	if(MatedPlugInletUnlocked_Status() && ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA5.bits.VCCU_Inlet_MotorStatus == Locked){//DC04) Inlet Locked
		result = true;
		/*
		if(ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA5.bits.VCCU_Inlet_MotorStatus == VCCU_Inlet_MotorStatus_Moving){
				}*/
		setChargerMode(CCS_QUANTITY, V_INLETLOCKED);
	}
	return result;
}
bool DC05_Status(){
	return (status1() && status2() && (ShmSysConfigAndInfo->ate.vccu.v2g_StateM.VCCU_V2G_StateM_StateMachineSt == SLAC || ShmSysConfigAndInfo->ate.vccu.v2g_StateM.VCCU_V2G_StateM_StateMachineSt == WaitForIP ||
			ShmSysConfigAndInfo->ate.vccu.v2g_StateM.VCCU_V2G_StateM_StateMachineSt == SECCDiscoveryProtocol || ShmSysConfigAndInfo->ate.vccu.v2g_StateM.VCCU_V2G_StateM_StateMachineSt == TLConnection ||
			ShmSysConfigAndInfo->ate.vccu.v2g_StateM.VCCU_V2G_StateM_StateMachineSt == SupportedAppProtocol || ShmSysConfigAndInfo->ate.vccu.v2g_StateM.VCCU_V2G_StateM_StateMachineSt == SessionSetup ||
			ShmSysConfigAndInfo->ate.vccu.v2g_StateM.VCCU_V2G_StateM_StateMachineSt == ServiceDiscovery || ShmSysConfigAndInfo->ate.vccu.v2g_StateM.VCCU_V2G_StateM_StateMachineSt == ServiceDetails ||
			ShmSysConfigAndInfo->ate.vccu.v2g_StateM.VCCU_V2G_StateM_StateMachineSt == PaymentServiceSelection || ShmSysConfigAndInfo->ate.vccu.v2g_StateM.VCCU_V2G_StateM_StateMachineSt == CertificateInstallation ||
			ShmSysConfigAndInfo->ate.vccu.v2g_StateM.VCCU_V2G_StateM_StateMachineSt == CertificateUpdate || ShmSysConfigAndInfo->ate.vccu.v2g_StateM.VCCU_V2G_StateM_StateMachineSt == PaymentDetails ||
			ShmSysConfigAndInfo->ate.vccu.v2g_StateM.VCCU_V2G_StateM_StateMachineSt == PaymentDetails || ShmSysConfigAndInfo->ate.vccu.v2g_StateM.VCCU_V2G_StateM_StateMachineSt == Authorization )
					&& ShmSysConfigAndInfo->ate.vccu.chargeToVehicle.bits.VCCU_Vehicle_ContactorRequest == Open);
}
bool S_SLAC(){
	bool result = false;
	if(MatedPlugInletUnlocked_Status() && DC05_Status()){
		result = true;


		/*
		if(ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA5.bits.VCCU_Inlet_MotorStatus == Locked &&
			(ShmSysConfigAndInfo->ate.vccu.controlPilotStatus.VCCU_ControlPilot_DutyCycle >= 5 || ShmSysConfigAndInfo->ate.vccu.controlPilotStatus.VCCU_ControlPilot_DutyCycle <= 7) &&
			ShmSysConfigAndInfo->ate.vccu.controlPilotStatus.DATA.bits.VCCU_ChargeUnit_State == EVSEStateB2 &&
			ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA5.bits.VCCU_DigitalInput_Status == Not_pressed &&
			ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA7.bits.VCCU_S3Switch_Status == Not_pressed&&
			ShmSysConfigAndInfo->ate.vccu.ptc1.VCCU_PTC1_Temperature < 90){

		}*/
		setChargerMode(CCS_QUANTITY, V_SLAC);
	}
	return result;
}

bool Definition(){
	bool result = false;
	if(MatedPlugInletUnlocked_Status() && (ShmSysConfigAndInfo->ate.vccu.v2g_StateM.VCCU_V2G_StateM_StateMachineSt == ChargeParameterDiscovery ) &&
			ShmSysConfigAndInfo->ate.vccu.chargeToVehicle.bits.VCCU_Vehicle_ContactorRequest == Open){
		result = true;
/*
		VCCU_V2G_VehicleStatus(CanFd, VCCU_V2G_StateM_EnergyTra_0000_DC_DC_extended, 0,
								3, 0,
								3, 3, TRUE,
								3, 3, 3,
								3, 3, 0,
								3, 0, 3,
								3);
		VCCU_V2G_EVMaximumVoltageLimit(TRUE, U_V, 520, TRUE, 0);
		VCCU_V2G_EVMaximumCurrentLimit(TRUE, U_A, TRUE, 0, 10);
*/
		setChargerMode(CCS_QUANTITY, V_DEFINITION);
	}
	return result;
}

bool S_CableCheck(){
	bool result = false;
	if(MatedPlugInletUnlocked_Status() && (ShmSysConfigAndInfo->ate.vccu.v2g_StateM.VCCU_V2G_StateM_StateMachineSt == CableCheck )){
		result = true;
		//VCCU_ChargeFromVehicle(CanFd, 500, 0, Allowed, Active, Allowed, Not_allowed, Opened);
		setChargerMode(CCS_QUANTITY, V_CABLECHECK);
	}
	return result;
}

bool Isolation(){
	bool result = false;
	if(MatedPlugInletUnlocked_Status() && PreCharge_Statue()){
		result = true;
		//VCCU_ChargeFromVehicle(CanFd, 500, 0, Allowed, Not_Active, Allowed, Not_allowed, Opened);
		setChargerMode(CCS_QUANTITY, V_ISOLATION);
	}
	return result;
}

bool S_PreCharge(){
	bool result = false;
	if(PreCharge_Statue()){
		//VCCU_ChargeFromVehicle(CanFd, 500, 500, Allowed, Not_Active, Allowed, Not_allowed, Opened);
		//VCCU_V2G_EVTargetCurrent(U_A, 5, TRUE, 0);
		setChargerMode(CCS_QUANTITY, V_VOLTAGEDIFFERENCE);
	}
	return result;
}

bool Contactors(){
	bool result = false;
	if( PreCharge_Statue() && ShmSysConfigAndInfo->ate.vccu.chargeToVehicle.bits.VCCU_Vehicle_ContactorRequest == Close){
		result = true;
		//VCCU_ChargeFromVehicle(CanFd, 500, 500, Allowed, Not_Active, Allowed, Not_allowed, Closed);
		setChargerMode(CCS_QUANTITY, V_CONTACTORSCLOSED);
	}
	return result;
}

bool S_PowerDelivery(){
	bool result = false;
	if(PreCharge_Statue() && ShmSysConfigAndInfo->ate.vccu.v2g_StateM.VCCU_V2G_StateM_StateMachineSt == PowerDelivery
			&& ShmSysConfigAndInfo->ate.vccu.chargeToVehicle.bits.VCCU_Vehicle_ContactorRequest == Close
			){
		result = true;
		//VCCU_V2G_EVTargetVoltage(450, U_V, TRUE, 0);
		setChargerMode(CCS_QUANTITY, V_POWERDELIVERY);
	}
	return result;
}

bool S_CurrentDemand(){
	bool result = false;
	if(ShmSysConfigAndInfo->ate.vccu.v2g_StateM.VCCU_V2G_StateM_StateMachineSt == CurrentDemand){//(DC12) Current Demand
		result = true;
		//TODO stop
		setChargerMode(CCS_QUANTITY, V_CURRENTDEMAND);
	}
	return result;
}

bool PowerDeliveryFalse(){
	bool result = false;
	if(ShmSysConfigAndInfo->ate.vccu.v2g_StateM.VCCU_V2G_StateM_StateMachineSt == PowerDelivery
			&& ShmSysConfigAndInfo->ate.vccu.chargeToVehicle.bits.VCCU_Vehicle_ContactorRequest == Open
			){//(DC13) PowerDelivery
		result = true;
		setChargerMode(CCS_QUANTITY, V_POWERDELIVERYFALSE);
	}
	return result;
}

bool S_WeldingDetection(){
	bool result = false;
	if(ShmSysConfigAndInfo->ate.vccu.v2g_StateM.VCCU_V2G_StateM_StateMachineSt == WeldingDetection){//(DC14) Welding Detection
		result = true;
		setChargerMode(CCS_QUANTITY, V_DETECTION);
	}
	return result;
}

bool SessionStop(){
	bool result = false;
	if(ShmSysConfigAndInfo->ate.vccu.v2g_StateM.VCCU_V2G_StateM_StateMachineSt == StateM_SessionStop &&
			ShmSysConfigAndInfo->ate.vccu.chargeToVehicle.bits.VCCU_Vehicle_IsolationMea_0000 == Requested){//Session Stop
		result = true;
		setChargerMode(CCS_QUANTITY, V_SESSION_STOP);
	}
	return result;
}

bool StopCommunicationSession(){
	bool result = false;
	if(ShmSysConfigAndInfo->ate.vccu.v2g_StateM.VCCU_V2G_StateM_StateMachineSt == StateM_StopCommunicationSession ){//Stop Communication Session
		result = true;
		setChargerMode(CCS_QUANTITY, V_STOP_COMMUNICATION_SESSION);
	}
	return result;
}

bool DCFinished(){
	bool result = false;
	if(ShmSysConfigAndInfo->ate.vccu.v2g_StateM.VCCU_V2G_StateM_StateMachineSt == StateM_Finished ){//Finished
		result = true;
		setChargerMode(CCS_QUANTITY, V_FINISHED);
	}
	return result;
}

bool statusCheck(){
	bool result = false;
	VCCU_TD();
	UnmatedPlug();
	MatedPlugInletUnlocked();
	InletLocking();
	InletLocked();
	S_SLAC();
	Definition();
	S_CableCheck();
	Isolation();
	S_PreCharge();
	Contactors();
	S_PowerDelivery();
	S_CurrentDemand();
	PowerDeliveryFalse();
	S_WeldingDetection();
	SessionStop();
	StopCommunicationSession();
	DCFinished();
	return result;
}

//===============================================
// 確認 GPIO 狀態
//===============================================
int gpio_get_value(unsigned int gpio, unsigned int *value)
{
    int fd;
    char buf[MAX_BUF];
    char ch;

    snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);

    fd = open(buf, O_RDONLY);
    if (fd < 0) {
        perror("gpio/get-value");
        return fd;
    }

    read(fd, &ch, 1);

    if (ch != '0') {
        *value = 1;
    } else {
        *value = 0;
    }

    close(fd);
    return 0;
}

void SelfTestRun()
{

}

long hexToDec(char *source)
{
    long sum = 0;
    long t = 1;
    int i, len;

    len = strlen(source);
    for(i=len-1; i>=0; i--)
    {
        sum += t * getIndexOfSigns(*(source + i));
        t *= 16;
    }

    return sum;
}

int getIndexOfSigns(char ch)
{
    if(ch >= '0' && ch <= '9')
    {
        return ch - '0';
    }
    if(ch >= 'A' && ch <='F')
    {
        return ch - 'A' + 10;
    }
    if(ch >= 'a' && ch <= 'f')
    {
        return ch - 'a' + 10;
    }
    return -1;
}


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_cc[VTIME] = (unsigned char) 5;
	tios.c_lflag=0;
    tcflush(fd, TCIFLUSH);
    ioctl(fd, TCSETS, &tios);

	return fd;
}

unsigned char Config_Gpio_Output(unsigned char fd, unsigned char targetAddr, Gpio_out *Set_Buf)
{
    unsigned char result = FAIL;
    unsigned char tx[9] = {0xaa, 0x00, targetAddr, Cmd.config_Gpio_Output, 0x01, 0x00, 0x00, 0x00};
    unsigned char rx[512];
    unsigned char chksum = 0x00;

    for (int idx = 0; idx < 2; idx++)
        tx[6] |= (Set_Buf->Button_LED[idx] ? 0x01:0x00) << (0+idx);

    for (int idx = 0; idx < 4; idx++)
            tx[6] |= (Set_Buf->System_LED[idx] ? 0x01:0x00) << (2+idx);

    tx[6] |= (Set_Buf->AC_Connector ? 0x01:0x00) << 6;
    tx[6] |= (Set_Buf->AC_Breaker ? 0x01:0x00) << 7;

    for (int idx = 0; idx < (tx[4] | tx[5] << 8); idx++)
        chksum ^= tx[6+idx];
    tx[7] = chksum;

    if (tranceive(fd, tx, sizeof(tx), rx) > 0)
    {
        chksum = 0x00;
        for(int idx=0;idx<(rx[4] | rx[5]<<8);idx++)
        {
            chksum ^= rx[6+idx];
        }

        if((chksum == rx[6+(rx[4] | rx[5]<<8)]) &&
           (rx[2] == tx[1]) &&
           (rx[1] == tx[2]) &&
           (rx[3] == tx[3]) &&
           (rx[6] == tx[6]))
        {
            result = PASS;
        }
    }

    return result;
}


int Initialization(){
	char *moduleName = "DMYZ30100J01P0";
	memcpy(&ShmSysConfigAndInfo->SysConfig.ModelName, moduleName, strlen(moduleName));
	//printf("%s \n", ShmSysConfigAndInfo->SysConfig.ModelName);
	ShmSysConfigAndInfo->SysInfo.CcsChargingData[CCS_QUANTITY].Index = CCS_QUANTITY;
	ShmSysConfigAndInfo->SysInfo.CcsChargingData[CCS_QUANTITY].slotsIndex = 1;
	chargingInfo[CCS_QUANTITY] = &ShmSysConfigAndInfo->SysInfo.CcsChargingData[CCS_QUANTITY];
	chargingInfo[CCS_QUANTITY]->SystemStatus = V_IDLE;
	chargingInfo[CCS_QUANTITY]->Type = _Type_CCS;
	chargingInfo[CCS_QUANTITY]->type_index = CCS_QUANTITY;
	chargingInfo[CCS_QUANTITY]->Evboard_id = 0x01;
	ShmSysConfigAndInfo->ate.ATEStatus = 0;
	// 現階段預設為走 DIN70121
	ShmCcsData->CommProtocol = 0x01;
	return PASS;
}

bool IsNoneMatchRelayStatus()
{
	bool result = false;

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

	return result;
}

void MatchRelayStatus()
{
	// 因為 AC Contactor 沒有 Feedback,所以暫時先這樣處理
	//regRelay.relay_event.bits.AC_Contactor = outputRelay.relay_event.bits.AC_Contactor;
	ShmSysConfigAndInfo->SysInfo.AcContactorStatus  = regRelay.relay_event.bits.AC_Contactor = outputRelay.relay_event.bits.AC_Contactor;
	regRelay.relay_event.bits.CCS_Precharge = outputRelay.relay_event.bits.CCS_Precharge;
	regRelay.relay_event.bits.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;
}

bool CheckConnectorTypeStatus()
{
	bool result = true;

	return result;
}

void CloseInternalCommPort()
{
    close(Uart5Fd);
}

void InitRS485DirectionIO(void)
{
    //LCD_AC_BIAS_EN    =>  GPIO2_25*//*RS-485 for module DE control
    gpio_set_direction(PIN_AM_DE_1, GPIO_DIR_OUTPUT);
    gpio_write(PIN_AM_DE_1, 1);
    //system("echo 89 > /sys/class/gpio/export");
    //system("echo \"out\" > /sys/class/gpio/gpio89/direction");
    //system("echo 1 > /sys/class/gpio/gpio89/value");
    //LCD_HSYNC     =>  GPIO2_23*//*RS-485 for module RE control
    gpio_set_direction(PIN_AM_RE_1, GPIO_DIR_OUTPUT);
    gpio_write(PIN_AM_RE_1, 0);
    //system("echo 87 > /sys/class/gpio/export");
    //system("echo \"out\" > /sys/class/gpio/gpio87/direction");
    //system("echo 0 > /sys/class/gpio/gpio87/value");
}

void InitGPIO()
{


}


int main(void){
	//Create all share memory
	//printf("=====Initializing. \n");
	//ate = malloc( sizeof(ate) );


	if(CreatShareMemory()==0){
		#ifdef SystemLogMessage
		//DEBUG_ERROR("CreatShareMemory NG \n");
		#endif
		if(ShmStatusCodeData!=NULL)
		{
			//ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FailToCreateShareMemory=1;
		}
		return 0;
		sleep(5);
		system("reboot -f");
	}
	/*
	int a=2;
	int *b;
	b = &a;
	printf("%p\n", &a);
	printf("%d\n", *b);
	printf("%p\n", b);
	printf("%p\n", &b);
	*//*
	int a = 2;
	int b = 3;
	a = a^b;
	b = a^b;
	a = a^b;
	printf("%d %d", a, b);

	const char *SystemId="0101";

	printf("%c %p =====\n", *SystemId, &SystemId);

	strcpy((char *)&ShmSysConfigAndInfo->SysConfig.SystemId,SystemId);

	char *SystemIdStr = (char *)&ShmSysConfigAndInfo->SysConfig.SystemId;

	printf("%s =====\n", SystemIdStr);*/

	//SpawnTask();
	//KillTask();

	CanFd = InitCanBus();
	CanFd2 = CHROMAInitCanBus();
	CANReceiver();
	CHROMACANReceiver();
	printf ("vccu 1===== CanFd2:%d. \n", CanFd2);
	//setChargerMode(CCS_QUANTITY, V_IDLE);

	/*
	struct   timeb   tp;

	unsigned int StartTime,StopTime;
	//ftime(&tp);
	ftime(&startChargingTime[CCS_QUANTITY]);
	//
	StartTime = (int)startChargingTime[CCS_QUANTITY].time;
	printf("%u\n", StartTime);
	sleep(2);
	ftime(&tp);

	ftime(&endChargingTime[CCS_QUANTITY]);
	StopTime = (int)endChargingTime[CCS_QUANTITY].time;
	printf("%u\n", StopTime);

*/
/*
	gpio_set_direction(1, GPIO_DIR_INPUT);
	gpio_set_direction(2, GPIO_DIR_INPUT);
    gpio_set_direction(3, GPIO_DIR_INPUT);
    gpio_write(1, 0);
    gpio_write(3, 0);
    gpio_write(3, 1);
    gpio_write(3, 1);
    */
	/*
	int pinIn[2] = { 1, 3 };

	system("echo 1 > /sys/class/gpio/export");
	system("echo \"out\" > /sys/class/gpio/gpio1/direction");
	system("echo 1 > /sys/class/gpio/gpio1/value");
	system("echo 3 > /sys/class/gpio/export");
	system("echo \"out\" > /sys/class/gpio/gpio3/direction");
	system("echo 1 > /sys/class/gpio/gpio3/value");

	gpio_set_direction(1, GPIO_DIR_OUTPUT);
    gpio_set_direction(4, GPIO_DIR_OUTPUT);
	gpio_write(1, 0);
	gpio_write(4, 0);

	for (int i = 0; i < ARRAY_SIZE(pinIn); i++)
	{

	}*/
	Uart1Fd = Init407ComPort();

    //printf("407 Port id = %d \n", Uart1Fd);
    //int led = gpio_read(3);
    //printf("led === %d \n", led);

	//printf("%d %d %d %d %d %d \n", ShmSysConfigAndInfo->ate.targetCurrent_Value, ShmSysConfigAndInfo->ate.targetVoltage_Value, ShmSysConfigAndInfo->ate.maximumCurrent_value, ShmSysConfigAndInfo->ate.maximumVoltage_value, ShmSysConfigAndInfo->ate.linkVoltage, ShmSysConfigAndInfo->ate.contactorVoltage);
	Initialization();
	InitRS485DirectionIO();
	// Open Uart5 for RB
	Uart5Fd = InitComPort();
	for (byte index = 0; index < ARRAY_SIZE(outputRelay.relay_event.relay_status); index++)
	{
		outputRelay.relay_event.relay_status[index] = 0x00;
	}

	memset(&regRelay, 0xFF,sizeof(Relay));
	outputRelay.relay_event.bits.AC_Contactor = 0x00;
	outputRelay.relay_event.bits.CCS_Precharge = 0x00;
	outputRelay.relay_event.bits.Gun1_P = 0x00;
	outputRelay.relay_event.bits.Gun1_N = 0x00;
	outputRelay.relay_event.bits.Gun2_P = 0x00;
	outputRelay.relay_event.bits.Gun2_N = 0x00;
	//outputRelay.relay_event.bits.Gun1_Parallel_N = 0x00;
	//outputRelay.relay_event.bits.Gun1_Parallel_P = 0x01;
	Config_Relay_Output(Uart5Fd, Addr.Relay, &outputRelay);
	/*
	VCCU_Requests(90, 90, 90,
			3, 3, 3, 3,
			3, 0, 7,
		7, 3, 3);*/
	sleep(1);
	if(Uart5Fd < 0){
		printf ("open port error. \n");
		return 0;
	}
	//usleep(300000);
	//outputRelay.relay_event.bits.Gun1_N = 0x00;
	//outputRelay.relay_event.bits.Gun1_P = 0x00;
//	outputRelay.relay_event.bits.Gun2_N = 0x00;
//	outputRelay.relay_event.bits.Gun2_P = 0x00;
//	Config_Relay_Output(Uart5Fd, Addr.Relay, &outputRelay);
//	flash = NO;
//	SetOutputGpio(flash);
//	return 0;
	ShmSysConfigAndInfo->ate.chademo.id0D_req.K1K2Status=0x00;
	ShmSysConfigAndInfo->ate.chademo.id0D_req.Soc = 50;
	ShmSysConfigAndInfo->ate.ateMode = 0;
	ShmSysConfigAndInfo->ate.ATEState = 1;
	//byte priorityLow = 1;
/**/
	//byte normalStop = 0x01;
	//byte stopReason[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

	byte evstaus[5] = { 0x01, 0x02, 0x03, 0x04, 0x05 };
	//PresentInputRequirement

	/*
	typedef enum
	{
		ESIdle = 0x01;
		ESPreparing = 0x02;
		ESCharging = 0x03;
		ESChargingTerminating = 0x04;
		ESFault = 0x05;
	}EmulatorStatus;
*/

	//setStatusMode(CCS_QUANTITY, STOP);
	//CCS
	ShmSysConfigAndInfo->ate.targetCurrent_Value = targetCurrent_Value;
	ShmSysConfigAndInfo->ate.targetVoltage_Value = targetVoltage_Value;
	ShmSysConfigAndInfo->ate.maximumCurrent_value = maximumCurrent_value;
	ShmSysConfigAndInfo->ate.maximumVoltage_value = maximumVoltage_value;
	ShmSysConfigAndInfo->ate.linkVoltage = linkVoltage;
	ShmSysConfigAndInfo->ate.contactorVoltage = contactorVoltage;//contactorVoltage;

	//GB
	ShmSysConfigAndInfo->ate.PresentBattVoltage = 4700;
	ShmSysConfigAndInfo->ate.MinimumChargeCurrent = 20;
	ShmSysConfigAndInfo->ate.RequireVoltage = 3800;
	//ShmSysConfigAndInfo->ate.RequireVoltage = 4700;
	ShmSysConfigAndInfo->ate.RequireCurrent = 600;
	ShmSysConfigAndInfo->ate.chademoTargetVoltage_Value = 4800;
	ShmSysConfigAndInfo->ate.chademoTargetCurrent_Value = 30;
	//ShmSysConfigAndInfo->ate.targetCurrent_Value = 1200;
	ShmSysConfigAndInfo->ate.Permission = STOP;
	ShmSysConfigAndInfo->ate.TotalBatteryCap = 1000;          //0.1
	ShmSysConfigAndInfo->ate.MaxBatteryCurrent = 1200;        //0.1
	ShmSysConfigAndInfo->ate.MaxBatteryVoltage = 5000;        //0.1
	ShmSysConfigAndInfo->ate.status = 0;
	ShmSysConfigAndInfo->ate.chademo.id03.state = 0;
	ShmSysConfigAndInfo->ate.ATEStatus = 0x00;
	ShmSysConfigAndInfo->ate.cstatus = 0;
	ShmSysConfigAndInfo->ate.chademo.PresentChargedDuration = 0;
	ShmSysConfigAndInfo->ate.chademo.RemainChargingDuration = 0;
	setStatusMode(CCS_QUANTITY, STOP);
	if(ShmSysConfigAndInfo->ate.ATEState  == 1){

	}else if(ShmSysConfigAndInfo->ate.ATEState  == 2){

	}

	setATEMode(CCS_QUANTITY, ShmSysConfigAndInfo->ate.ATEState);
	while(CanFd){
		//ShmSysConfigAndInfo->ate.ATEState
		if(ShmSysConfigAndInfo->ate.ATEState  == 1){//VCCU
			//TODO
			//ShmSysConfigAndInfo->ate.ateMode = 0;
		}else if(ShmSysConfigAndInfo->ate.ATEState  == 2){//GB
			//TODO
			//ShmSysConfigAndInfo->ate.ateMode = 0;
		}else{//none
			// init
		}
		int state = isATEChange(CCS_QUANTITY);
		if(state){
//TODO
		}
		if(ShmSysConfigAndInfo->ate.ATEState  == 1){//VCCU
/*
			VCCU_Requests(0, 0, 0,
						3, 3, 3, 3,
						3, 3, 3,
					7, 3, 3);
					*/
			setBootNotification1();
			// 輸出電壓
			//測試value
			//GetPersentOutputVol();
			// 三相輸入電壓
			//GetPresentInputVol();
			statusCheck();
			// Relay
			CheckRelayOutput(CCS_QUANTITY);
			//依據當前各槍的狀態選擇 搭上/放開 Relay
			SetEvContactorRelayStatus(CCS_QUANTITY);
			int status = isModeChange(CCS_QUANTITY);/**/
			// 搭上/鬆開 Relay
			// 放開 Relay 之前要先確認輸出的電壓電流是否已經降到某個值
			if(IsNoneMatchRelayStatus())
			{
				if (Config_Relay_Output(Uart5Fd, Addr.Relay, &outputRelay))
				{
					printf("Match Relay............................ \n");
					MatchRelayStatus();
					printf("reg relay, AC = %x, g1_p = %x, g1_n = %x, g2_p = %x, g2_n = %x, pre = %x \n",
							regRelay.relay_event.bits.AC_Contactor,
							regRelay.relay_event.bits.Gun1_P,
							regRelay.relay_event.bits.Gun1_N,
							regRelay.relay_event.bits.Gun2_P,
							regRelay.relay_event.bits.Gun2_N,
							regRelay.relay_event.bits.CCS_Precharge);
				}
			}

			switch(chargingInfo[CCS_QUANTITY]->SystemStatus){
				case V_IDLE:{
					if (status){
						printf("CCS IDLE Processing 1....................\n");
					}
					setEVStatus1(evstaus[0]);
					break;
				}
				case V_UNMATEDPLUG:{
					if (status){
						printf("CCS UNMATEDPLUG Processing 2....................\n");
					}
					setEVStatus1(evstaus[0]);
					VCCU_ChargeFromVehicle(CanFd, ShmSysConfigAndInfo->ate.linkVoltage, 0, Not_allowed, Active, Not_allowed, Not_allowed, Opened);
					break;
				}
				case V_MATED_PLUG_INLET_UNLOCKED:{
					if (status){
						if(ShmSysConfigAndInfo->ate.vccu.inletStatus.DATA2.VCCU_PlugPresent_Status == VCCU_InletStatus_Connected){

						}
						printf("CCS MATED_PLUG_INLET_UNLOCKED Processing 3....................\n");
					}
					setEVStatus1(evstaus[0]);
					VCCU_ChargeFromVehicle(CanFd, ShmSysConfigAndInfo->ate.linkVoltage, 0, Not_allowed, Active, Allowed, Not_allowed, Opened);
					break;
				}
				case V_INLETLOCKING:{
					if (status){
						printf("CCS INLETLOCKING Processing 4....................\n");
					}
					setEVStatus1(evstaus[0]);
					break;
				}
				case V_INLETLOCKED:{
					if (status){
						printf("CCS INLETLOCKED Processing 5....................\n");
					}
					setEVStatus1(evstaus[1]);
					VCCU_ChargeFromVehicle(CanFd, ShmSysConfigAndInfo->ate.linkVoltage, 0, Not_allowed, Active, Allowed, Not_allowed, Opened);
					break;
				}
				case V_SLAC:{
					if (status){
						printf("CCS SLAC Processing 6....................\n");
					}
					setEVStatus1(evstaus[1]);
					VCCU_ChargeFromVehicle(CanFd, ShmSysConfigAndInfo->ate.linkVoltage, 0, Not_allowed, Active, Allowed, Not_allowed, Opened);
					break;
				}
				case V_DEFINITION:{
					if (status){
						printf("CCS DEFINITION Processing 7....................\n");
					}
					setEVStatus1(evstaus[1]);
					VCCU_V2G_VehicleStatus(CanFd, VCCU_V2G_StateM_EnergyTra_0000_DC_DC_extended, 0, 3, 0,
											3, 3, TRUE, 3, 3, 3, 3, 3, 0, 3, 0, 3, 3);
					/*
					VCCU_V2G_EVMaximumVoltageLimit(TRUE, U_V, 500, TRUE, 0);
					VCCU_V2G_EVMaximumCurrentLimit(TRUE, U_A, TRUE, 0, 10);
					*/
					VCCU_V2G_EVMaximumVoltageLimit(TRUE, U_V, ShmSysConfigAndInfo->ate.maximumVoltage_value, TRUE, 0);
					VCCU_V2G_EVMaximumCurrentLimit(TRUE, U_A, TRUE, 0, ShmSysConfigAndInfo->ate.maximumCurrent_value);
					break;
				}
				case V_CABLECHECK:{
					if (status){
						printf("CCS CABLECHECK Processing 8....................\n");
					}
					setEVStatus1(evstaus[1]);
					VCCU_ChargeFromVehicle(CanFd, ShmSysConfigAndInfo->ate.linkVoltage, 0, Allowed, Active, Allowed, Not_allowed, Opened);
					break;
				}
				case V_ISOLATION:{
					if (status){
						printf("CCS ISOLATION Processing 9....................\n");
					}
					setEVStatus1(evstaus[1]);
					VCCU_ChargeFromVehicle(CanFd, ShmSysConfigAndInfo->ate.linkVoltage, 0, Allowed, Not_Active, Allowed, Not_allowed, Opened);
					break;
				}
				case V_VOLTAGEDIFFERENCE:{
					if (status){
						printf("CCS VOLTAGEDIFFERENCE Processing 10....................\n");
					}

					setEVStatus1(evstaus[1]);
					VCCU_ChargeFromVehicle(CanFd, ShmSysConfigAndInfo->ate.linkVoltage, ShmSysConfigAndInfo->ate.linkVoltage, Allowed, Not_Active, Allowed, Not_allowed, Opened);
					VCCU_V2G_EVTargetCurrent(U_A, ShmSysConfigAndInfo->ate.targetCurrent_Value, TRUE, 0);
					break;
				}
				case V_CONTACTORSCLOSED:{
					if (status){
						printf("CCS CONTACTORSCLOSED Processing 11....................\n");
					}
					setEVStatus1(evstaus[1]);
					VCCU_ChargeFromVehicle(CanFd, ShmSysConfigAndInfo->ate.linkVoltage, ShmSysConfigAndInfo->ate.linkVoltage, Allowed, Not_Active, Allowed, Not_allowed, Closed);
					break;
				}
				case V_POWERDELIVERY:{
					if (status){
						printf("CCS POWERDELIVERY Processing 12....................\n");
					}
					VCCU_ChargeFromVehicle(CanFd, ShmSysConfigAndInfo->ate.linkVoltage, ShmSysConfigAndInfo->ate.linkVoltage, Allowed, Not_Active, Allowed, Not_allowed, Closed);
					if(ShmSysConfigAndInfo->ate.ATEStatus == 0){
						VCCU_ChargeFromVehicle(CanFd, ShmSysConfigAndInfo->ate.linkVoltage, ShmSysConfigAndInfo->ate.linkVoltage, Allowed, Not_Active, Allowed, Not_allowed, Closed);
					}else{
						VCCU_ChargeFromVehicle(CanFd, ShmSysConfigAndInfo->ate.linkVoltage, ShmSysConfigAndInfo->ate.linkVoltage, Not_allowed, Not_Active, Allowed, Not_allowed, Opened);
					}
					//VCCU_V2G_EVTargetVoltage(400, U_V, TRUE, 0);

					setEVStatus1(evstaus[1]);
					break;
				}
				case V_CURRENTDEMAND:{
					if (status){
						printf("CCS CURRENTDEMAND Processing 13....................\n");
					}
					setEVStatus1(evstaus[2]);
					VCCU_V2G_VehicleStatus(CanFd, VCCU_V2G_StateM_EnergyTra_0000_DC_DC_extended, 0,
											3, 0,
											3, 3, TRUE,
											3, 3, 3,
											3, 3, 0,
											3, 0, 3,
											3);
					//printf("targetVoltage_Value= %d targetCurrent_Value =%d maximumVoltage_value = %d maximumCurrent_value = %d linkVoltage = %d \n",ShmSysConfigAndInfo->ate.targetVoltage_Value, ShmSysConfigAndInfo->ate.targetCurrent_Value, ShmSysConfigAndInfo->ate.maximumVoltage_value, ShmSysConfigAndInfo->ate.maximumCurrent_value, ShmSysConfigAndInfo->ate.linkVoltage);

					/*
					VCCU_V2G_EVMaximumVoltageLimit(TRUE, U_V, 500, TRUE, 0);
					VCCU_V2G_EVMaximumCurrentLimit(TRUE, U_A, TRUE, 0, 10);
					VCCU_V2G_EVTargetVoltage(400, U_V, TRUE, 0);
					VCCU_V2G_EVTargetCurrent(U_A, 2, TRUE, 0);
					VCCU_ChargeFromVehicle(CanFd, 500, 500, Allowed, Not_Active, Allowed, Not_allowed, Closed);
					*/
					VCCU_V2G_EVMaximumVoltageLimit(TRUE, U_V, ShmSysConfigAndInfo->ate.maximumVoltage_value, TRUE, 0);
					VCCU_V2G_EVMaximumCurrentLimit(TRUE, U_A, TRUE, 0, ShmSysConfigAndInfo->ate.maximumCurrent_value);
					VCCU_V2G_EVTargetVoltage(ShmSysConfigAndInfo->ate.targetVoltage_Value, U_V, TRUE, 0);
					VCCU_V2G_EVTargetCurrent(U_A, ShmSysConfigAndInfo->ate.targetCurrent_Value, TRUE, 0);
					//VCCU_ChargeFromVehicle(CanFd, ShmSysConfigAndInfo->ate.linkVoltage, ShmSysConfigAndInfo->ate.linkVoltage, Allowed, Not_Active, Allowed, Not_allowed, Closed);
					if(ShmSysConfigAndInfo->ate.ATEStatus == 0){
						//VCCU_ChargeFromVehicle(CanFd, 500, 500, Allowed, Not_Active, Allowed, Not_allowed, Closed);
						VCCU_ChargeFromVehicle(CanFd, ShmSysConfigAndInfo->ate.linkVoltage, ShmSysConfigAndInfo->ate.linkVoltage, Allowed, Not_Active, Allowed, Not_allowed, Closed);
					}else{
						//VCCU_ChargeFromVehicle(CanFd, 500, 500, Not_allowed, Not_Active, Allowed, Not_allowed, Closed);
						VCCU_ChargeFromVehicle(CanFd, ShmSysConfigAndInfo->ate.linkVoltage, ShmSysConfigAndInfo->ate.linkVoltage, Not_allowed, Not_Active, Allowed, Not_allowed, Closed);
					}
					break;
				}
				case V_POWERDELIVERYFALSE:{
					if (status){
						printf("CCS POWERDELIVERYFALSE Processing 14....................\n");
					}
					setEVStatus1(evstaus[3]);
					VCCU_ChargeFromVehicle(CanFd, ShmSysConfigAndInfo->ate.linkVoltage, ShmSysConfigAndInfo->ate.linkVoltage, Not_allowed, Not_Active, Allowed, Not_allowed, Opened);
					break;
				}
				case V_DETECTION:{
					if (status){
						printf("CCS DETECTION Processing 15....................\n");
					}
					setEVStatus1(evstaus[3]);
					VCCU_ChargeFromVehicle(CanFd, ShmSysConfigAndInfo->ate.linkVoltage, 0, Not_allowed, Active, Allowed, Not_allowed, Opened);
					break;
				}
				case V_SESSION_STOP:{
					if (status){
						printf("CCS SESSION_STOP Processing 16....................\n");
					}
					setEVStatus1(evstaus[3]);
					VCCU_ChargeFromVehicle(CanFd, ShmSysConfigAndInfo->ate.linkVoltage, 0, Not_allowed, Active, Allowed, Not_allowed, Opened);
					break;
				}
				case V_STOP_COMMUNICATION_SESSION:{
					if (status){
						printf("CCS STOP_COMMUNICATION_SESSION Processing 17....................\n");
					}
					setEVStatus1(evstaus[3]);
					VCCU_ChargeFromVehicle(CanFd, ShmSysConfigAndInfo->ate.linkVoltage, 0, Not_allowed, Active, Allowed, Not_allowed, Opened);
					break;
				}
				case V_FINISHED:{
					if (status){
						printf("CCS FINISHED Processing 18....................\n");
					}
					setEVStatus1(evstaus[3]);
					VCCU_ChargeFromVehicle(CanFd, ShmSysConfigAndInfo->ate.linkVoltage, 0, Not_allowed, Active, Allowed, Not_allowed, Opened);
					break;
				}
				default:{
					break;
				}
			}
			//usleep(100000);
			usleep(whileLoopTime);
		}else if(ShmSysConfigAndInfo->ate.ATEState  == 2){//GB
			if(ShmSysConfigAndInfo->ate.status == 0){
				int status = isStatusChange(CCS_QUANTITY);
				// 輸出電壓
				//GetPersentOutputVol();
				// Relay
				CheckRelayOutput(CCS_QUANTITY);
				//依據當前各槍的狀態選擇 搭上/放開 Relay
				SetEvContactorRelayStatus(CCS_QUANTITY);

				// 搭上/鬆開 Relay
				// 放開 Relay 之前要先確認輸出的電壓電流是否已經降到某個值
				if(IsNoneMatchRelayStatus())
				{
					if (Config_Relay_Output(Uart5Fd, Addr.Relay, &outputRelay))
					{
						//printf("Match Relay............................ \n");
						MatchRelayStatus();
						printf("reg relay, AC = %x, g1_p = %x, g1_n = %x, g2_p = %x, g2_n = %x, pn = %x, pp = %x \n",
								regRelay.relay_event.bits.AC_Contactor,
								regRelay.relay_event.bits.Gun1_P,
								regRelay.relay_event.bits.Gun1_N,
								regRelay.relay_event.bits.Gun2_P,
								regRelay.relay_event.bits.Gun2_N,
								regRelay.relay_event.bits.Gun1_Parallel_N,
								regRelay.relay_event.bits.Gun1_Parallel_P);
						//
						//ftime(&startChargingTime[CCS_QUANTITY]);
					}
				}

				usleep(1000);
				setMisc(1);

				if(ShmSysConfigAndInfo->ate.ATEStatus == 1){
					ShmSysConfigAndInfo->ate.Permission = START;
					setStatusMode(CCS_QUANTITY, ShmSysConfigAndInfo->ate.Permission);
					//printf("ATEStatus == 1 %d \n",ShmSysConfigAndInfo->ate.ATEStatus);
				}else if(ShmSysConfigAndInfo->ate.ATEStatus == 2){
					ShmSysConfigAndInfo->ate.Permission = STOP;
					setStatusMode(CCS_QUANTITY, ShmSysConfigAndInfo->ate.Permission);
					//printf("ATEStatus == 2 %d \n",ShmSysConfigAndInfo->ate.ATEStatus);
					ShmSysConfigAndInfo->ate.ATEStatus = 0;
				}else if(ShmSysConfigAndInfo->ate.ATEStatus == 3){
					setEVStatus2(evstaus[4]);
					ShmSysConfigAndInfo->ate.Permission = STOP;
					setStatusMode(CCS_QUANTITY, ShmSysConfigAndInfo->ate.Permission);
					ShmSysConfigAndInfo->ate.ATEStatus = 0x00;
					SetChargingPermission(CCS_QUANTITY, ShmSysConfigAndInfo->ate.Permission, ShmSysConfigAndInfo->ate.TotalBatteryCap, ShmSysConfigAndInfo->ate.MaxBatteryCurrent, ShmSysConfigAndInfo->ate.MaxBatteryVoltage, 1);
					EvseStopChargingEvent(normalStop, stopReason, 1);
				}else{

				}
				if(ShmSysConfigAndInfo->ate.chademo.id03.state == 0 || ShmSysConfigAndInfo->ate.Permission == 0){
					//SetChargingPermission(CCS_QUANTITY, START, 1000, 1200, 6000, 1);
					//setChargerMode(CCS_QUANTITY, ShmSysConfigAndInfo->ate.Permission);

					ShmSysConfigAndInfo->ate.Permission = START;
					setStatusMode(CCS_QUANTITY, ShmSysConfigAndInfo->ate.Permission);
					SetChargingPermission(CCS_QUANTITY, ShmSysConfigAndInfo->ate.Permission, ShmSysConfigAndInfo->ate.TotalBatteryCap, ShmSysConfigAndInfo->ate.MaxBatteryCurrent, ShmSysConfigAndInfo->ate.MaxBatteryVoltage, 1);
				}else  if(ShmSysConfigAndInfo->ate.chademo.id03.state ==1){
					ShmSysConfigAndInfo->ate.Permission = STOP;
				}else  if(ShmSysConfigAndInfo->ate.chademo.id03.state ==2){
					ShmSysConfigAndInfo->ate.Permission = STOP;
				}else  if(ShmSysConfigAndInfo->ate.chademo.id03.state ==3){
					ShmSysConfigAndInfo->ate.Permission = STOP;
				}else  if(ShmSysConfigAndInfo->ate.chademo.id03.state ==4){
					ShmSysConfigAndInfo->ate.Permission = STOP;
				}else  if(ShmSysConfigAndInfo->ate.chademo.id03.state == 5){
					ShmSysConfigAndInfo->ate.Permission = STOP;
					setEVStatus2(evstaus[1]);
				}else  if(ShmSysConfigAndInfo->ate.chademo.id03.state == 6){
					ShmSysConfigAndInfo->ate.Permission = STOP;
					setEVStatus2(evstaus[1]);
				}else  if(ShmSysConfigAndInfo->ate.chademo.id03.state == 7){
					ShmSysConfigAndInfo->ate.Permission = STOP;
					setEVStatus2(evstaus[2]);
					//setEVStatus2(evstaus[2]);
				}else  if(ShmSysConfigAndInfo->ate.chademo.id03.state == 8){
					ShmSysConfigAndInfo->ate.Permission = STOP;
					setEVStatus2(evstaus[2]);
					//setEVStatus2(evstaus[2]);
				}//else if(ShmSysConfigAndInfo->ate.chademo.id03.state == 16 ){
				else if(ShmSysConfigAndInfo->ate.chademo.id03.state >= 13 ){
					handleEmulatorFaultStatus();
				}else if(ShmSysConfigAndInfo->ate.chademo.id03.state == 14 ){
					handleEmulatorFaultStatus();
				}else if(ShmSysConfigAndInfo->ate.chademo.id03.state == 9 || ShmSysConfigAndInfo->ate.chademo.id03.state == 10
						|| ShmSysConfigAndInfo->ate.chademo.id03.state == 11 || ShmSysConfigAndInfo->ate.chademo.id03.state == 12
						//|| ShmSysConfigAndInfo->ate.chademo.id03.state == 13
						//|| ShmSysConfigAndInfo->ate.chademo.id03.state == 15
						){
					ShmSysConfigAndInfo->ate.Permission = STOP;
					//setEVStatus2(evstaus[3]);
					setEVStatus2(evstaus[3]);
				}else{
					setEVStatus2(evstaus[0]);
					//printf("4 %d %d\n",ShmSysConfigAndInfo->ate.chademo.id03.state,ShmSysConfigAndInfo->ate.chademo.id0D_req.K1K2Status);
				}

				if(ShmSysConfigAndInfo->ate.chademo.id03.ProximitySignal == 0){
					//printf("1 %d ===== \n", ShmSysConfigAndInfo->ate.chademo.id03.ProximitySignal);
					setEVStatus2(evstaus[3]);
				}else if(ShmSysConfigAndInfo->ate.chademo.id03.ProximitySignal == 1 && ShmSysConfigAndInfo->ate.chademo.id03.state != 7 &&
						ShmSysConfigAndInfo->ate.chademo.id03.state != 9 && ShmSysConfigAndInfo->ate.chademo.id03.state != 10
						&& ShmSysConfigAndInfo->ate.chademo.id03.state != 11 && ShmSysConfigAndInfo->ate.chademo.id03.state != 12
						&& ShmSysConfigAndInfo->ate.chademo.id03.state != 13
						&& ShmSysConfigAndInfo->ate.chademo.id03.state != 15){
					//printf("2 %d ===== \n", ShmSysConfigAndInfo->ate.chademo.id03.ProximitySignal);
					setEVStatus2(evstaus[1]);
				}
				if(status){
					//printf("status change1 %d ===== \n", status);
					SetChargingPermission(CCS_QUANTITY, ShmSysConfigAndInfo->ate.Permission, ShmSysConfigAndInfo->ate.TotalBatteryCap, ShmSysConfigAndInfo->ate.MaxBatteryCurrent, ShmSysConfigAndInfo->ate.MaxBatteryVoltage, 1);
				}else{
					if(ShmSysConfigAndInfo->ate.Permission == STOP ){
						if(ShmSysConfigAndInfo->ate.chademo.id03.state == 0){
							//printf("status change0 %d ===== \n", status);
							//SetChargingPermission(CCS_QUANTITY, ShmSysConfigAndInfo->ate.Permission, ShmSysConfigAndInfo->ate.TotalBatteryCap, ShmSysConfigAndInfo->ate.MaxBatteryCurrent, ShmSysConfigAndInfo->ate.MaxBatteryVoltage, 1);
							SetChargingPermission(CCS_QUANTITY, ShmSysConfigAndInfo->ate.Permission, ShmSysConfigAndInfo->ate.TotalBatteryCap, ShmSysConfigAndInfo->ate.MaxBatteryCurrent, ShmSysConfigAndInfo->ate.MaxBatteryVoltage, 1);
						}

					}
				}
				//SetChargingPermission(CCS_QUANTITY, ShmSysConfigAndInfo->ate.Permission, ShmSysConfigAndInfo->ate.TotalBatteryCap, ShmSysConfigAndInfo->ate.MaxBatteryCurrent, ShmSysConfigAndInfo->ate.MaxBatteryVoltage, 1);
				//SetChargingPermission(CCS_QUANTITY, START, 1000, 1200, 6000, 1);
				usleep(1000);
				//給火線電壓
				SetPresentInputPower(ShmSysConfigAndInfo->ate.chademoTargetVoltage_Value, ShmSysConfigAndInfo->ate.chademoTargetCurrent_Value, 1);
				usleep(1000);
				//SetPresentInputRequirement(4800, 6000, 1920, 20);
				SetPresentInputRequirement(ShmSysConfigAndInfo->ate.RequireVoltage, ShmSysConfigAndInfo->ate.RequireCurrent, ShmSysConfigAndInfo->ate.PresentBattVoltage, ShmSysConfigAndInfo->ate.MinimumChargeCurrent, 1);

			}
		}

	}
	printf("End. \n");
	return FAIL;
}