#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/can.h>
#include 	<linux/can/raw.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	"../../define.h"
#include 	"Config.h"
#include 	"Module_EvComm.h"
#include 	"VCCU.h"
#include	"internalComm.h"
#include 	"IOComm.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 YES					1
#define NO					0
#define DEMO 				0
byte flash = NO;

int whileLoopTime = 500000;//10000; // 10 ms
struct SysConfigAndInfo			*ShmSysConfigAndInfo;
struct StatusCodeData 			*ShmStatusCodeData;
struct FanModuleData			*ShmFanModuleData;
struct CHAdeMOData				*ShmCHAdeMOData;
struct CcsData					*ShmCcsData;
struct RelayModuleData				*ShmRelayModuleData;
Ver ver;
PresentInputVoltage inputVoltage;
PresentOutputVoltage outputVoltage;
Relay outputRelay;
Relay regRelay;
int Uart5Fd;
int Uart1Fd;
char *relayRs485PortName = "/dev/ttyS5";
char* pPortName = "/dev/ttyS3";
char *priPortName = "/dev/ttyS1";
#define SYSFS_GPIO_DIR      "/sys/class/gpio"
//struct ATE 							*ate;

byte gun_count = CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY;
int chargingTime[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];

float maxChargingVol = 5000;			// 限制最大充電電壓,如依照模塊則填上 0
float maxChargingCur = 100;				// 限制最大充電電流,如依照模塊則填上 0
#define 	MAX_BUF 			64
byte normalStop = 0x01;
byte stopReason[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
byte evstaus[5] = { 0x01, 0x02, 0x03, 0x04, 0x05 };

byte bd0_1_status = 0;
byte bd0_2_status = 0;
byte bd1_1_status = 0;
byte bd1_2_status = 0;
// 槍資訊
struct ChargingInfoData *_chargingData[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];

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

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

		0x00001200,
		0x00001500,
};

void GetMaxVolAndCurMethod(byte index, float *vol, float *cur);
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 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;
}

//=================================
// Common routine
//=================================
void getTimeString(char *buff)
{
	time_t timep;
	struct tm *p;
	time(&timep);
	p=gmtime(&timep);

	sprintf(buff, "[%04d-%02d-%02d %02d:%02d:%02d]", (1900+p->tm_year), (1+p->tm_mon), p->tm_mday, p->tm_hour, p->tm_hour, p->tm_sec);
}


struct Address Addr={0x01,0x02,0x03,0xFF};
struct Command Cmd={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x81,0x85,0x86,0xe0,0xe1,0xe2,0xe3};

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

//================================================
//================================================
// CANBUS send cmd
//================================================
//================================================

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

void SendCmdToEvboard(int cmd, byte *data, byte dataLen)
{
    struct can_frame frame;

    frame.can_id = cmd;
    frame.can_dlc = dataLen;
    memcpy(frame.data, data, sizeof(frame.data));

    write(CanFd, &frame, sizeof(struct can_frame));
}

void SetTargetAddr(byte *target_number, byte index)
{
	int id = PackageIdCmd(Ev_Cmd.address_assignment + index);
	//printf("intCmd = %x \n", cmd & CAN_EFF_MASK);
	//cmd = cmd & CAN_EFF_MASK;

	byte data[8];

	data[0] = *target_number;
	data[1] = *(target_number + 1);
	data[2] = *(target_number + 2);
	data[3] = *(target_number + 3);
	data[4] = index;

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

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

	SendCmdToEvboard(id, data, 0);
}

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

	SendCmdToEvboard(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(id, data, sizeof(data));
}

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(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(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(id, data, 0);
}

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

	SendCmdToEvboard(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(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(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(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(id, data, 1);
}
bool CheckUniqNumber(byte value)
{
	for (byte index = 0; index < gun_count; index++)
	{
		if (_chargingData[index]->Evboard_id == value)
		{
			struct timeval _end_time;
			gettimeofday(&_end_time, NULL);
			unsigned long diff = 1000000 *	(_end_time.tv_sec - _id_assign_time.tv_sec) + _end_time.tv_usec - _id_assign_time.tv_usec;
			if (diff >= 3000000)
			{
				gettimeofday(&_id_assign_time, NULL);
				return true;
			}
			else
			{
				return false;
			}
		}
	}

	gettimeofday(&_id_assign_time, NULL);
	return true;
}


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

//==========================================
// Init all share memory
//==========================================
int InitShareMemory()
{
	int result = PASS;
	int MeterSMId;

	//initial ShmSysConfigAndInfo
	if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo),  IPC_CREAT | 0777)) < 0)
    {
		#ifdef SystemLogMessage
		printf("shmget ShmSysConfigAndInfo NG\n");
		#endif
		return FAIL;
	}
    else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1)
    {
    	#ifdef SystemLogMessage
    	printf("shmat ShmSysConfigAndInfo NG\n");
		#endif
    	return FAIL;
   	 }
    else
    {}

	//initial ShmSysConfigAndInfo
	/*
	if ((MeterSMId = shmget(ShmATEKey, sizeof(struct ATE),  IPC_CREAT | 0777)) < 0)
    {
		#ifdef SystemLogMessage
		printf("shmget ShmATEKey NG\n");
		#endif
		return FAIL;
	}
    else if ((ate = shmat(MeterSMId, NULL, 0)) == (void *) -1)
    {
    	#ifdef SystemLogMessage
    	printf("shmat ShmATEKey NG\n");
		#endif
    	return FAIL;
   	 }
    else
    {}
*/
	//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));
	//initial ShmStatusCodeData
	if ((MeterSMId = shmget(ShmStatusCodeKey, sizeof(struct StatusCodeData),  IPC_CREAT | 0777)) < 0)
	{
		#ifdef SystemLogMessage
		printf("shmget ShmStatusCodeData NG\n");
		#endif
		return FAIL;
	}
	else if ((ShmStatusCodeData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
	{
		#ifdef SystemLogMessage
		printf("shmat ShmStatusCodeData NG\n");
		#endif
		return FAIL;
	}
	else
	{}


   	if(CHAdeMO_QUANTITY > 0)
   	{
   		if ((MeterSMId = shmget(ShmCHAdeMOCommKey, sizeof(struct CHAdeMOData),	IPC_CREAT | 0777)) < 0)
   		{
   			#ifdef SystemLogMessage
   			printf("[shmget ShmCHAdeMOData NG \n");
   			#endif
   			return FAIL;
   		}
   		else if ((ShmCHAdeMOData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
   		{
   			#ifdef SystemLogMessage
   			printf("shmat ShmCHAdeMOData NG \n");
   			#endif
   			return FAIL;
   		}
   		else
   		{}
   	}

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

    return result;
}

//================================================
// initial can-bus
//================================================
int InitCanBus()
{
	int 					s0,nbytes;
	struct timeval			tv;
	struct ifreq 			ifr0;
	struct sockaddr_can		addr0;

	system("/sbin/ip link set can0 down");
	system("/sbin/ip link set can0 type can bitrate 500000 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
		//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, "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;
}
void setChargerMode(byte gun_index, byte mode)
{
	_chargingData[gun_index]->SystemStatus = mode;
}

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

	}
	return result;
}

// 左右槍的 Relay 前後的輸出電壓
void GetPersentOutputVol()
{
	if (Query_Present_OutputVoltage(Uart5Fd, Addr.Relay, &outputVoltage) == PASS)
	{

        ShmSysConfigAndInfo->ate.targetVoltage_Value = (outputVoltage.behindRelay_Voltage_C2);
        /*
		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;
        */
        /*
        if (_chargingData[CCS_QUANTITY]->Evboard_id == 0x01)
		{
			_chargingData[CCS_QUANTITY]->FuseChargingVoltage = ShmRelayModuleData->Gun1FuseOutputVolt;
			_chargingData[CCS_QUANTITY]->FireChargingVoltage = ShmRelayModuleData->Gun1RelayOutputVolt;
			ShmSysConfigAndInfo->ate.targetVoltage_Value = ShmRelayModuleData->Gun1RelayOutputVolt;
		}*/
        /*
        for (int index = 0; index < gun_count; index++)
		{
			if (index == 0)
			{
				if (_chargingData[index]->Evboard_id == 0x01)
				{
					_chargingData[index]->FuseChargingVoltage = ShmRelayModuleData->Gun1FuseOutputVolt;
					_chargingData[index]->FireChargingVoltage = ShmRelayModuleData->Gun1RelayOutputVolt;
					ShmSysConfigAndInfo->ate.targetVoltage_Value = ShmRelayModuleData->Gun1RelayOutputVolt;
				}
				else if (_chargingData[index]->Evboard_id == 0x02)
				{
					_chargingData[index]->FuseChargingVoltage = ShmRelayModuleData->Gun2FuseOutputVolt;
					_chargingData[index]->FireChargingVoltage = ShmRelayModuleData->Gun2RelayOutputVolt;
				}
			}
			else if (index == 1)
			{
				if (_chargingData[index]->Evboard_id == 0x01)
				{
					_chargingData[index]->FuseChargingVoltage = ShmRelayModuleData->Gun1FuseOutputVolt;
					_chargingData[index]->FireChargingVoltage = ShmRelayModuleData->Gun1RelayOutputVolt;
					ShmSysConfigAndInfo->ate.targetVoltage_Value = ShmRelayModuleData->Gun1RelayOutputVolt;
				}
				else if (_chargingData[index]->Evboard_id == 0x02)
				{
					_chargingData[index]->FuseChargingVoltage = ShmRelayModuleData->Gun2FuseOutputVolt;
					_chargingData[index]->FireChargingVoltage = ShmRelayModuleData->Gun2RelayOutputVolt;
				}
			}

			//unsigned short Ovp = 0;
			//unsigned short Ocp = 0;
			//Ovp = MIN [VOUT_MAX_VOLTAGE, EV_BATTERY_VOLTAGE]  // 最大輸出電壓與電池電壓最大值
			//Ocp = MIN [IOUT_MAX_CURRENT, EV_CURRENT_REQ]      // 最大輸出電流與需求電流最小值
			if (_chargingData[index]->Type == _Type_Chademo)
			{
				//Ovp = MaxValue(_chargingData[index]->MaximumChargingVoltage, _chargingData[index]->EvBatteryMaxVoltage);
				//Ocp = MaxValue(_chargingData[index]->PresentChargingCurrent, ShmCHAdeMOData->ev[_chargingData[index]->type_index].ChargingCurrentRequest);
			}

		}*/
	}
	//sleep(1);
}
//================================================
//================================================
// CANBUS receive task
//================================================
//================================================
bool FindChargingInfoData(byte target, struct ChargingInfoData **chargingData)
{

	for (byte index = 0; index < CHAdeMO_QUANTITY; index++)
	{
		if (ShmSysConfigAndInfo->SysInfo.ChademoChargingData[index].Index == target)
		{
			chargingData[target] = &ShmSysConfigAndInfo->SysInfo.ChademoChargingData[index];
			return true;
		}
	}

	for (byte index = 0; index < CCS_QUANTITY; index++)
	{
		if (ShmSysConfigAndInfo->SysInfo.CcsChargingData[index].Index == target)
		{
			chargingData[target] = &ShmSysConfigAndInfo->SysInfo.CcsChargingData[index];
			return true;
		}
	}

	for (byte index = 0; index < GB_QUANTITY; index++)
	{
		if (ShmSysConfigAndInfo->SysInfo.GbChargingData[index].Index == target)
		{
			chargingData[target] = &ShmSysConfigAndInfo->SysInfo.GbChargingData[index];
			return true;
		}
	}

	return false;
}

void AddrAssignment(byte *data)
{
	byte target_number[8];
	byte index = 0x00;

	memcpy(target_number, data, sizeof(target_number));
	index = *(data + 4);

	if (CheckUniqNumber(index))
	{
		printf("EV board id = %x \n", index);
//		printf("target_number[0] = %x \n", target_number[0]);
//		printf("target_number[1] = %x \n", target_number[1]);
//		printf("target_number[2] = %x \n", target_number[2]);
//		printf("target_number[3] = %x \n", target_number[3]);
//		printf("target_number[4] = %x \n", target_number[4]);

		if (index < 1)
			return;

		printf("SetTargetAddr \n");
		SetTargetAddr(target_number, index);
	}
}

void ClearAbnormalStatus_CCS(byte gun_index)
{
	int codeValue = 0;

	if (strlen((char *)ShmSysConfigAndInfo->SysStopChargingAlarmCode.StopCode[gun_index]) == 6)
	{
		codeValue = atoi((char *)ShmSysConfigAndInfo->SysStopChargingAlarmCode.StopCode[gun_index]);

		if (codeValue >= 13600 && codeValue <= 13600)
		{
			memcpy(&ShmSysConfigAndInfo->SysStopChargingAlarmCode.StopCode[gun_index][0], "", 7);
			ShmSysConfigAndInfo->SysStopChargingAlarmCode.Level = 0;
		}
	}
	ShmStatusCodeData->InfoCode.InfoEvents.bits.NormalStopChargingByUser = 0x00;
}

void ClearAbnormalStatus_Chadmoe(byte gun_index)
{
	int codeValue = 0;

	if (strlen((char *)ShmSysConfigAndInfo->SysStopChargingAlarmCode.StopCode[gun_index]) == 6)
	{
		codeValue = atoi((char *)ShmSysConfigAndInfo->SysStopChargingAlarmCode.StopCode[gun_index]);

		if (codeValue >= 23700 && codeValue <= 23736)
		{
			memcpy(&ShmSysConfigAndInfo->SysStopChargingAlarmCode.StopCode[gun_index][0], "", 7);
			ShmSysConfigAndInfo->SysStopChargingAlarmCode.Level = 0;
		}
	}

	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoEvCommFail = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.PilotFault = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoBatteryMalfun = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoNoPermission = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoBatteryIncompatibility = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoBatteryOVP = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoBatteryUVP = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoBatteryOTP = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoBatteryCurrentDiff = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoBatteryVoltageDiff = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoShiftPosition = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoBatteryOtherFault = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoChargingSystemError = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoEvNormalStop = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoTempSensorBroken = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoConnectorLockFail = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoD1OnNoReceive = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoBmsKtoJTimeout = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoBmsChargeAllowTimeout = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoWaitGfdTimeout = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoBmsEvRelayTimeout = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoBmsReqCurrentTimeout = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoBmsKtoJOffTimeout = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoBmsEvRelayOffTimeout = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoAdcMoreThan10V = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoAdcMoreThan20V = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoBmsChargeBeforeStop = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoChargerGetNormalStop = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoChargerGetEmergencyStop = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoIsolationResultFail = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoMissLinkWithMotherBoard = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoOutputVolMoreThanLimit = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoReqCurrentMoreThanLimit = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoReCapBmsEqrCurrentExceed = 0x00;
	ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoChargeRemainCountDown = 0x00;
}

void AbnormalStopAnalysis(byte gun_index, byte *errCode)
{
	char string[7];
	sprintf(string, "%d%d%d%d%d%d", *(errCode + 5), *(errCode + 4), *(errCode + 3), *(errCode + 2), *(errCode + 1), *(errCode + 0));

	if (gun_index < gun_count)
	{
		if (strlen((char *)ShmSysConfigAndInfo->SysStopChargingAlarmCode.StopCode[gun_index]) <= 0)
		{
			memcpy(&ShmSysConfigAndInfo->SysStopChargingAlarmCode.StopCode[gun_index][0], string, 7);
			ShmSysConfigAndInfo->SysStopChargingAlarmCode.Level = 0x00;
		}
	}

	if (strcmp(string, "023700") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoEvCommFail = 0x01;
	if (strcmp(string, "023701") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.CcsEvCommFail = 0x01;
	if (strcmp(string, "023702") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.GbEvCommFail = 0x01;
	if (strcmp(string, "023703") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.PilotFault = 0x01;
	if (strcmp(string, "023704") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoBatteryMalfun = 0x01;
	if (strcmp(string, "023705") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoNoPermission = 0x01;
	if (strcmp(string, "023706") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoBatteryIncompatibility = 0x01;
	if (strcmp(string, "023707") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoBatteryOVP = 0x01;
	if (strcmp(string, "023708") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoBatteryUVP = 0x01;
	if (strcmp(string, "023709") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoBatteryOTP = 0x01;
	if (strcmp(string, "023710") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoBatteryCurrentDiff = 0x01;
	if (strcmp(string, "023711") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoBatteryVoltageDiff = 0x01;
	if (strcmp(string, "023712") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoShiftPosition = 0x01;
	if (strcmp(string, "023713") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoBatteryOtherFault = 0x01;
	if (strcmp(string, "023714") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoChargingSystemError = 0x01;
	if (strcmp(string, "023715") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoEvNormalStop = 0x01;
	if (strcmp(string, "023716") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoTempSensorBroken = 0x01;
	if (strcmp(string, "023717") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoConnectorLockFail = 0x01;
	if (strcmp(string, "023718") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoD1OnNoReceive = 0x01;
	if (strcmp(string, "023719") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoBmsKtoJTimeout = 0x01;
	if (strcmp(string, "023720") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoBmsChargeAllowTimeout = 0x01;
	if (strcmp(string, "023721") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoWaitGfdTimeout = 0x01;
	if (strcmp(string, "023722") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoBmsEvRelayTimeout = 0x01;
	if (strcmp(string, "023723") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoBmsReqCurrentTimeout = 0x01;
	if (strcmp(string, "023724") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoBmsKtoJOffTimeout = 0x01;
	if (strcmp(string, "023725") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoBmsEvRelayOffTimeout = 0x01;
	if (strcmp(string, "023726") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoAdcMoreThan10V = 0x01;
	if (strcmp(string, "023727") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoAdcMoreThan20V = 0x01;
	if (strcmp(string, "023728") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoBmsChargeBeforeStop = 0x01;
	if (strcmp(string, "023729") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoChargerGetNormalStop = 0x01;
	if (strcmp(string, "023730") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoChargerGetEmergencyStop = 0x01;
	if (strcmp(string, "023731") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoIsolationResultFail = 0x01;
	if (strcmp(string, "023732") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoMissLinkWithMotherBoard = 0x01;
	if (strcmp(string, "023733") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoOutputVolMoreThanLimit = 0x01;
	if (strcmp(string, "023734") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoReqCurrentMoreThanLimit = 0x01;
	if (strcmp(string, "023735") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoReCapBmsEqrCurrentExceed = 0x01;
	if (strcmp(string, "023736") == 0) ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoChargeRemainCountDown = 0x01;
}

void SendCmd(int cfd, 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(cfd, &frame, sizeof(struct can_frame));
    usleep(2000);
}

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

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

void CANReceiver()
{
	pid_t canRecPid;

	canRecPid = fork();

	if(canRecPid > 0)
	{
		int nbytes;
		struct can_frame frame;
		int intCmd;
		// 槍資訊
		//struct ChargingInfoData *_chargingData[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
		//struct timeval _cmd_ack_timeout[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
		/*
		bool isPass = false;

		while(!isPass)
		{
			isPass = true;
			for (byte _index = 0; _index < gun_count; _index++)
			{
				if (!FindChargingInfoData(_index, &_chargingData[0]))
				{
					//DEBUG_ERROR("EvComm (main) : FindChargingInfoData false \n");
					isPass = false;
					break;
				}
			}
		}

		for (byte _index = 0; _index < gun_count; _index++)
			gettimeofday(&_cmd_ack_timeout[_index], NULL);
*/
		while (1)
		{
			memset(&frame, 0, sizeof(struct can_frame));
			nbytes = read(CanFd, &frame, sizeof(struct can_frame));
/*
			for (byte _index = 0; _index < gun_count; _index++)
			{
				if (GetTimeoutValue(_cmd_ack_timeout[_index]) >= 5000000)
				{
					// ACK timeout
					//printf("gun = %x, ack timeout \n", _index);
				}
			}
*/
			if (nbytes > 0)
			{

				//byte target;
				//byte targetGun = 0x00;
				intCmd = (int) (frame.can_id & CAN_EFF_MASK);
				#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
				if (intCmd == ADDRESS_REQ)
				{
					AddrAssignment(frame.data);
					continue;
				}

				intCmd = (int) (frame.can_id & CAN_EFF_MASK & 0xFFFFFF00);
				//target = ((byte) (frame.can_id & 0x000000FF));		// 0x01 or 0x02
				//printf("test %d %d ==========\n", intCmd, target);
				/*
				for (byte _index = 0; _index < gun_count; _index++)
				{
					if (_chargingData[_index]->Evboard_id == target)
					{
						targetGun = _index;
						break;
					}
				}

				if(targetGun < 0 || targetGun >= CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY)
				{
					printf("EvComm (CANReceiver) : Target index = %x is < 0 or > QUANTITY \n", targetGun);
					continue;
				}
				*/
				if(intCmd == 256)
				{
					continue;
				}

				//gettimeofday(&_cmd_ack_timeout[targetGun], NULL);
				//printf ("intCmd = %x \n", intCmd);
				switch (intCmd)
				{
					case EV_BOARD_STATUS_NOTIFICATION:
					{
						ShmSysConfigAndInfo->ate.chademo.id03.ProximitySignal = frame.data[2];
						ShmSysConfigAndInfo->ate.chademo.id03.state = frame.data[3];
						//printf(" EV_BOARD_STATUS_NOTIFICATION 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] );

						//printf("EVBoardStatusNotification 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] );

						//printf("ConnectorPlugIn = %x, data[0] = %x \n", _chargingData[target]->ConnectorPlugIn, frame.data[0]);
						//printf("ConnectorPlugIn = %x \n", (-120 + frame.data[1]) / 10);
					}
						break;
					case ACK_EV_FW_VERSION:
					{
						/*
						if (_chargingData[targetGun]->Type == _Type_Chademo)
						{
							memcpy(ShmCHAdeMOData->evse[_chargingData[targetGun]->type_index].version, frame.data, ARRAY_SIZE(frame.data));
							ShmCHAdeMOData->evse[_chargingData[targetGun]->type_index].SelfTest_Comp = PASS;
						}
						else if (_chargingData[targetGun]->Type == _Type_CCS)
						{
							if (ShmCcsData->CommProtocol == 0x01)
							{
								memcpy(&ShmCcsData->V2GMessage_DIN70121[_chargingData[targetGun]->type_index].version, frame.data, ARRAY_SIZE(frame.data));
								ShmCcsData->V2GMessage_DIN70121[_chargingData[targetGun]->type_index].SelfTest_Comp = PASS;
							}
						}
						*/
					}
						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];//剩餘時間

						/*
						_chargingData[targetGun]->EvBatterySoc = frame.data[1];
						_chargingData[targetGun]->EvBatterytargetVoltage = ((short) frame.data[3] << 8) + (short) frame.data[2];
						_chargingData[targetGun]->EvBatterytargetCurrent = ((short) frame.data[5] << 8) + (short) frame.data[4];
						_chargingData[targetGun]->PresentChargedDuration = ((short) frame.data[7] << 8) + (short) frame.data[6];

						if (_chargingData[targetGun]->Type == _Type_Chademo)
						{
							if (ShmCHAdeMOData->ev[_chargingData[targetGun]->type_index].EvDetection != frame.data[0])
							{
								// log
							}

							ShmCHAdeMOData->ev[_chargingData[targetGun]->type_index].EvDetection = frame.data[0];
							ShmCHAdeMOData->ev[_chargingData[targetGun]->type_index].SOC = _chargingData[targetGun]->EvBatterySoc;
							ShmCHAdeMOData->ev[_chargingData[targetGun]->type_index].TargetBatteryVoltage = _chargingData[targetGun]->EvBatterytargetVoltage;
							ShmCHAdeMOData->ev[_chargingData[targetGun]->type_index].ChargingCurrentRequest = _chargingData[targetGun]->EvBatterytargetCurrent;
						}
						else if (_chargingData[targetGun]->Type == _Type_CCS)
						{
							if(ShmCcsData->CommProtocol == 0x01)
							{
								ShmCcsData->V2GMessage_DIN70121[_chargingData[targetGun]->type_index].PresentMsgFlowStatus = frame.data[0];
							}
						}
						*/
						//printf("frame.data_2 = %x, frame.data_3 = %x \n", frame.data[2], frame.data[3]);
						//printf("EvBatterytargetVoltage = %f \n", _chargingData[targetGun]->EvBatterytargetVoltage);
						//printf("EvBatterytargetCurrent = %f \n", _chargingData[targetGun]->EvBatterytargetCurrent);
						//printf("BatteryVoltage = %d \n", ShmCHAdeMOData->ev[_chargingData[target]->type_index].TargetBatteryVoltage);
						//printf("CurrentRequest = %d \n", ShmCHAdeMOData->ev[_chargingData[target]->type_index].ChargingCurrentRequest);
					}
						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];

						/*
						//_chargingData[target].EvACorDCcharging = frame.data[0];
						//_chargingData[target]->TotalBatteryCap = ((float) frame.data[4] << 8) + (short) frame.data[3];
						_chargingData[targetGun]->EvBatteryMaxVoltage = ((short) frame.data[4] << 8) + (short) frame.data[3];
						//_chargingData[target]->EvBatteryMaxCurrent = ((float) frame.data[4] << 8) + (short) frame.data[3];
						//_chargingData[target].MaxiBatteryCurrent = ((short) frame.data[6] << 8) + (short) frame.data[5];
						if (_chargingData[targetGun]->Type == _Type_Chademo)
						{
							ShmCHAdeMOData->ev[_chargingData[targetGun]->type_index].TotalBatteryCapacity = ((short) frame.data[2] << 8) + (short) frame.data[1];
							ShmCHAdeMOData->ev[_chargingData[targetGun]->type_index].MaxiBatteryVoltage = _chargingData[targetGun]->EvBatteryMaxVoltage;

							//printf("EvBatteryMaxVoltage = %f \n", _chargingData[target]->EvBatteryMaxVoltage);
							//printf("TotalBatteryCapacity = %d \n", ShmCHAdeMOData->ev[_chargingData[target]->type_index].TotalBatteryCapacity);
							//printf("MaxiBatteryVoltage = %d \n", ShmCHAdeMOData->ev[_chargingData[target]->type_index].MaxiBatteryVoltage);
						}
						else if (_chargingData[targetGun]->Type == _Type_CCS)
						{
							if(ShmCcsData->CommProtocol == 0x01)
							{

							}
						}
						*/
					}
						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;
						}
						//memcpy(&ShmSysConfigAndInfo->ate.chademo.id0D_ack, &frame.data, frame.can_dlc);
						//printf("%d %d\n", ShmSysConfigAndInfo->ate.chademo.id0D_ack.K1K2OnOff, ShmSysConfigAndInfo->ate.chademo.id0D_ack.EvBoardState);
						//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] );
/*
						float pilotVol = (float)(-120 + frame.data[3]) / 10;

//						if (pilotVol != _chargingData[targetGun]->PilotVoltage)
//							DEBUG_INFO("PilotVoltage = %f \n", _chargingData[targetGun]->PilotVoltage);

						if (_chargingData[targetGun]->Type == _Type_Chademo)
						{
							_chargingData[targetGun]->GunLocked = frame.data[0];
							ShmCHAdeMOData->evse[_chargingData[targetGun]->type_index].ConnectorTemperatureP = frame.data[1];
							ShmCHAdeMOData->evse[_chargingData[targetGun]->type_index].ConnectorTemperatureN = frame.data[2];
							_chargingData[targetGun]->PilotVoltage = pilotVol;
							ShmCHAdeMOData->evse[_chargingData[targetGun]->type_index].EvboardStatus = frame.data[7];
						}
						else if (_chargingData[targetGun]->Type == _Type_CCS)
						{
							if (ShmCcsData->CommProtocol == 0x01)
							{
								_chargingData[targetGun]->GunLocked = frame.data[0];
								//ShmCcsData->V2GMessage_DIN70121[_chargingData[targetGun]->type_index]. .ConnectorTemperatureP = frame.data[1];
								//ShmCcsData->V2GMessage_DIN70121[_chargingData[targetGun]->type_index]. .ConnectorTemperatureN = frame.data[2];
								_chargingData[targetGun]->PilotVoltage = pilotVol;
							}
						}
						*/

						//printf("ConnectorPlug locked = %x \n", frame.data[0]);
						//printf("ConnectorTemp 0= %d \n", ShmCHAdeMOData->evse[_chargingData[target]->type_index].ConnectorTemperatureP);
						//printf("ConnectorTemp 1= %d \n", ShmCHAdeMOData->evse[_chargingData[target]->type_index].ConnectorTemperatureN);
					}
						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];
						printf("EvStopReason = %d %d %d %d %d %d %d \n", ShmSysConfigAndInfo->ate.chademo.id0B.EvStopReason, ShmSysConfigAndInfo->ate.chademo.id0B.AlarmCode1, ShmSysConfigAndInfo->ate.chademo.id0B.AlarmCode2, ShmSysConfigAndInfo->ate.chademo.id0B.AlarmCode3, ShmSysConfigAndInfo->ate.chademo.id0B.AlarmCode4, ShmSysConfigAndInfo->ate.chademo.id0B.AlarmCode5, ShmSysConfigAndInfo->ate.chademo.id0B.AlarmCode6);
						//byte normalStop = 0x01;
						//byte stopReason[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
						//byte evstaus[5] = { 0x01, 0x02, 0x03, 0x04, 0x05 };
						setEVStatus2(evstaus[4]);
						ShmSysConfigAndInfo->ate.Permission = STOP;
						setChargerMode(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);
						/*
						time_t CurrentTime;
						struct tm *tm;
						CurrentTime = time(NULL);
						tm = localtime(&	CurrentTime);
						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] );

						printf("NOTIFICATION_EV_STOP : %04d-%02d-%02d %02d:%02d:%02d \n",
								tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec);
						// 車端要求停止
						// frame.data[0] : 0x01 => normal stop, 0x02 => ev emergency stop
						if (frame.data[0] == 0x02)
						{
							//printf("NOTIFICATION_EV_STOP -----------------------------\n");
							AbnormalStopAnalysis(targetGun, frame.data + 1);
						}
						_chargingData[targetGun]->StopChargeFlag = YES;
						*/
					}
						break;
					default:
						//printf("Ack none defined. intCmd = %d  \n", intCmd);
						break;
				}
			}
			usleep(10000);
		}
	}
}


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:{
						//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];
						int voltage = ShmSysConfigAndInfo->ate.chroma.ate_Connector_2.TargetVoltage * 10;
						int current = ShmSysConfigAndInfo->ate.chroma.ate_Connector_2.TargetCurrent * 10;
						//ShmSysConfigAndInfo->ate.RequireVoltage = ShmSysConfigAndInfo->ate.chroma.ate_Connector_2.PresentVoltage  * 10;
						//ShmSysConfigAndInfo->ate.RequireCurrent = ShmSysConfigAndInfo->ate.chroma.ate_Connector_2.PresentCurrent * 10;
						ShmSysConfigAndInfo->ate.targetVoltage_Value = voltage;
						ShmSysConfigAndInfo->ate.targetCurrent_Value = current;
						ShmSysConfigAndInfo->ate.RequireVoltage = voltage;
						ShmSysConfigAndInfo->ate.RequireCurrent = current;
						//ShmSysConfigAndInfo->ate.MaxBatteryVoltage = voltage + (voltage * 0.1);
						//ShmSysConfigAndInfo->ate.MaxBatteryVoltage = voltage + (voltage + 100);

						ShmSysConfigAndInfo->ate.MaxBatteryVoltage = voltage + ( 100);
						//ShmSysConfigAndInfo->ate.PresentBattVoltage = voltage;
						//printf("ATE_Connector1 Get-Msg : %08X - %02x %02x %02x %02x %02x %02x %02x %02x %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 );
						break;
					}
					case ATE_Connector1:{//MaxBatteryVoltage
						/*
						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.RequireVoltage = ShmSysConfigAndInfo->ate.chroma.ate_Connector_1.PresentVoltage  * 10;
						//ShmSysConfigAndInfo->ate.RequireCurrent = ShmSysConfigAndInfo->ate.chroma.ate_Connector_1.PresentCurrent * 10;
						int voltage = ShmSysConfigAndInfo->ate.chroma.ate_Connector_1.TargetVoltage * 10;
						int current = ShmSysConfigAndInfo->ate.chroma.ate_Connector_1.TargetCurrent * 10;
						//ShmSysConfigAndInfo->ate.MaxBatteryVoltage = voltage + (voltage * 0.1);
						//ShmSysConfigAndInfo->ate.MaxBatteryVoltage = voltage + (voltage + 100);
						ShmSysConfigAndInfo->ate.MaxBatteryVoltage = voltage + ( 100);
						ShmSysConfigAndInfo->ate.targetVoltage_Value = voltage;
						ShmSysConfigAndInfo->ate.targetCurrent_Value = current;
						ShmSysConfigAndInfo->ate.RequireVoltage = voltage;
						ShmSysConfigAndInfo->ate.RequireCurrent = current;
						*/
						//ShmSysConfigAndInfo->ate.PresentBattVoltage = voltage + (voltage * 0.1);
						//printf("ATE_Connector2 Get-Msg : %08X - %02x %02x %02x %02x %02x %02x %02x %02x %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 );
						break;
					}

					default:

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

//================================================
// Main process
//================================================
// 檢查 Byte 中某個 Bit 的值
// _byte : 欲改變的 byte
// _bit : 該 byte 的第幾個 bit
unsigned char EvDetectionStatus(unsigned char _byte, unsigned char _bit)
{
	return ( _byte & mask_table[_bit] ) != 0x00;
}

bool IsConnectorPlugIn(struct ChargingInfoData *chargingData)
{
	return (chargingData->ConnectorPlugIn == 0x01) ? true : false;
}

void SetBitValue(unsigned char *_byte, unsigned char _bit, unsigned char value)
{
	if(value == 1)
		*_byte |= (1 << _bit);
	else if (value == 0)
		*_byte ^= (1 << _bit);
}

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

void SetPresentChargingOutputPower(struct ChargingInfoData *chargingData_1, struct ChargingInfoData *chargingData_2)
{
	/*
	float vol1 = 0, cur1 = 0;
	float vol2 = 0, cur2 = 0;

	vol1 = chargingData_1->FireChargingVoltage;
	cur1 = chargingData_1->PresentChargingCurrent;

	vol2 = chargingData_2->FireChargingVoltage;
	cur2 = chargingData_2->PresentChargingCurrent;

	SetPresentInputPower(vol1, cur1, vol2, cur2);
	*/
}

void SetPresentChargingOutputCap(struct ChargingInfoData *chargingData_1, struct ChargingInfoData *chargingData_2)
{
	/*
	float pow1 = 0, cur1 = 0;
	float pow2 = 0, cur2 = 0;
	float vol = 0;

	pow1 = chargingData_1->AvailableChargingPower;
	cur1 = chargingData_1->AvailableChargingCurrent;
	vol = chargingData_1->MaximumChargingVoltage;
	GetMaxVolAndCurMethod(chargingData_1->Index, &vol, &cur1);

	pow2 = chargingData_2->AvailableChargingPower;
	cur2 = chargingData_2->AvailableChargingCurrent;
	vol = chargingData_2->MaximumChargingVoltage;
	GetMaxVolAndCurMethod(chargingData_2->Index, &vol, &cur2);

	//printf("voltage 1 ========================================%f \n", vol);
	//printf("current 1 ========================================%f \n", cur1);
	SetPresentInputRequirement(pow1, cur1, pow2, cur2);
	*/
}

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 SetOutputGpio(byte flash)
{
    Gpio_out gpio;
    gpio.Button_LED[0] = 0x00;
    gpio.Button_LED[1] = 0x00;

    gpio.System_LED[0] = 0x00;
    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");
    }
}
void Initialization()
{/*
	bool isPass = false;

	while(!isPass)
	{
		isPass = true;
		for (byte _index = 0; _index < gun_count; _index++)
		{
			if (!FindChargingInfoData(_index, &_chargingData[0]))
			{
				//DEBUG_ERROR("EvComm (main) : FindChargingInfoData false \n");
				isPass = false;
				break;
			}
		}
	}
*/

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

void GetMaxVolAndCurMethod(byte index, float *vol, float *cur)
{
	if (maxChargingVol != 0 && maxChargingVol <= *vol)
		*vol = maxChargingVol;

	if (maxChargingCur != 0 && maxChargingCur <= *cur)
		*cur = maxChargingCur;
}

void GetStopChargingReasonByEvse(byte gunIndex, byte *reason)
{
	if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.EmergencyStopTrip == 0x01)
	{
		// 012251
		*(reason + 5) = 0;
		*(reason + 4)  = 1;
		*(reason + 3)  = 2;
		*(reason + 2)  = 2;
		*(reason + 1)  = 5;
		*(reason + 0)  = 1;
	}
	else if (_chargingData[gunIndex]->Type == _Type_Chademo &&
			ShmStatusCodeData->FaultCode.FaultEvents.bits.ChademoOutputRelayDrivingFault == 0x01)
	{
		// 011012
		*(reason + 5) = 0;
		*(reason + 4) = 1;
		*(reason + 3) = 1;
		*(reason + 2) = 0;
		*(reason + 1) = 1;
		*(reason + 0) = 2;
	}
	else if (_chargingData[gunIndex]->Type == _Type_CCS &&
			ShmStatusCodeData->FaultCode.FaultEvents.bits.CcsOutputRelayDrivingFault == 0x01)
	{
		// 011014
		*(reason + 5) = 0;
		*(reason + 4) = 1;
		*(reason + 3) = 1;
		*(reason + 2) = 0;
		*(reason + 1) = 1;
		*(reason + 0) = 4;
	}
	else if (ShmStatusCodeData->InfoCode.InfoEvents.bits.NormalStopChargingByUser == 0x01)
	{
		// 013600
		*(reason + 5) = 0;
		*(reason + 4) = 1;
		*(reason + 3) = 3;
		*(reason + 2) = 6;
		*(reason + 1) = 0;
		*(reason + 0) = 0;
	}
}

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


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

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

			if (regRelay.relay_event.bits.Gun1_N == YES	&& regRelay.relay_event.bits.CCS_Precharge == YES)
				_chargingData[0]->RelayKPK2Status = YES;
			else
				_chargingData[0]->RelayKPK2Status = NO;

		}
		else if (_chargingData[index]->Evboard_id == 0x01)
		{
			if (regRelay.relay_event.bits.Gun2_N == YES && regRelay.relay_event.bits.Gun2_P == YES)
				_chargingData[0]->RelayK1K2Status = YES;
			else
				_chargingData[0]->RelayK1K2Status = NO;

			if (regRelay.relay_event.bits.Gun2_N == YES && regRelay.relay_event.bits.CCS_Precharge == YES)
				_chargingData[0]->RelayKPK2Status = YES;
			else
				_chargingData[0]->RelayKPK2Status = NO;
		}
	}
	else if (index == 1)
	{
		//printf("Evboard_id = %x \n", _chargingData[index]->Evboard_id);

		if (regRelay.relay_event.bits.Gun1_Parallel_N == YES && regRelay.relay_event.bits.Gun1_Parallel_P == YES)
			_chargingData[1]->RelayK1K2Status = YES;
		else
			_chargingData[1]->RelayK1K2Status = NO;

		if (regRelay.relay_event.bits.Gun1_N == YES && regRelay.relay_event.bits.Gun1_P == YES)
			_chargingData[1]->RelayK1K2Status = YES;
		else
			_chargingData[1]->RelayK1K2Status = NO;

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

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

	}
	*/
	//printf("====%d %d %d\n",ShmSysConfigAndInfo->ate.chademo.id0D_req.K1K2Status, _chargingData[index]->Evboard_id, outputRelay.relay_event.bits.Gun1_Parallel_P);
	if(ShmSysConfigAndInfo->ate.chademo.id0D_req.K1K2Status == 1){
		if(_chargingData[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;*/

/**/
			if(ShmSysConfigAndInfo->ate.cstatus != 0){
				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 (_chargingData[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;
*/

/**/
			if(ShmSysConfigAndInfo->ate.cstatus != 0){
				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);
		}
	}
}

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)||
		(regRelay.relay_event.bits.Gun1_Parallel_P != outputRelay.relay_event.bits.Gun1_Parallel_P) ||
		(regRelay.relay_event.bits.Gun1_Parallel_N != outputRelay.relay_event.bits.Gun1_Parallel_N))
	{
		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;
	regRelay.relay_event.bits.Gun1_Parallel_N = outputRelay.relay_event.bits.Gun1_Parallel_N;
	regRelay.relay_event.bits.Gun1_Parallel_P = outputRelay.relay_event.bits.Gun1_Parallel_P;
}



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;
	SendCmd(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;
	SendCmd(CanFd2, bn2, data, sizeof(data));
}

void handleEmulatorFaultStatus(){
	setEVStatus2(evstaus[4]);
	ShmSysConfigAndInfo->ate.Permission = STOP;
	setChargerMode(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);
}
void CreateTimeoutFork()
{
	pid_t timeoutPid;

	timeoutPid = fork();
	if (timeoutPid > 0)
	{

		while(true)
		{

		}
	}

}

//===============================================
// 確認 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;
}
bool CheckConnectorTypeStatus()
{
	bool result = true;
	printf("bd0_1_status = %d, bd0_2_status = %d, bd1_1_status = %d, bd1_2_status = %d \n",
				bd0_1_status, bd0_2_status, bd1_1_status, bd1_2_status);
	return result;
}
void CheckGunTypeFromHw()
{
	int pinIn[4] = { 22, 23, 44, 45 };
	unsigned int gpioValue = 0;
	for (int i = 0; i < ARRAY_SIZE(pinIn); i++)
	{
		gpio_get_value(pinIn[i], &gpioValue);

		switch (pinIn[i])
		{
			case 22:
				bd1_1_status = gpioValue;
				break;
			case 23:
				bd1_2_status = gpioValue;
				break;
			case 44:
				bd0_1_status = gpioValue;
				break;
			case 45:
				bd0_2_status = gpioValue;
				break;
		}
	}
}

int main(int argc, char *argv[])
{

	if(InitShareMemory() == FAIL)
	{

		#ifdef SystemLogMessage
		//StoreLogMsg("InitShareMemory NG\n");
		#endif
		if(ShmStatusCodeData != NULL)
		{
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FailToCreateShareMemory=1;
		}
		sleep(5);
		return 0;
	}
	Initialization();
	CanFd = InitCanBus();
	ShmSysConfigAndInfo->ate.chademo.relaystatus = 0;
	CanFd2 = CHROMAInitCanBus();
	CANReceiver();
	CHROMACANReceiver();
	printf ("chademo 1=====. \n");

	Uart1Fd = Init407ComPort();
	//printf("407 Port id = %d \n", Uart1Fd);
	flash = YES;
	SetOutputGpio(flash);
	//InitRS485DirectionIO();
	// Open Uart5 for RB

	InitRS485DirectionIO();
	Uart5Fd = InitComPort();
	printf ("2=====. \n");
	//printf("%d \n", Uart5Fd);
	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 = 0x00;
	//Gun1_Parallel_P
	Config_Relay_Output(Uart5Fd, Addr.Relay, &outputRelay);
	sleep(1);
	if(Uart5Fd < 0){
		printf ("open port error. \n");
		return 0;
	}

	printf ("3=====. \n");
	//int id = PackageIdCmd(Ev_Cmd.get_miscellaneous_info);
	//printf("==========%d\n",id);
	//SetEvseStatusNotification();

	//ShmSysConfigAndInfo->ate.chademo.id06.MaximumBatteryVoltage=1000;
	//printf("==========\n");
	//printf("==========%d\n", ShmSysConfigAndInfo->ate.chademo.id06.MaximumBatteryVoltage );
	ShmSysConfigAndInfo->ate.chademo.id0D_req.K1K2Status=0x00;
	ShmSysConfigAndInfo->ate.chademo.id0D_req.Soc = 50;
	//byte priorityLow = 1;
/*
	byte normalStop = 0x01;
	byte stopReason[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
	byte evstaus[5] = { 0x01, 0x02, 0x03, 0x04, 0x05 };
	*/
	/*
	 Emulator Status
	Idle: 0x01
	Preparing: 0x02
	Charging: 0x03
	Charging terminating: 0x04
	Fault: 0x05

	 * */
	//PresentInputRequirement

	//ShmSysConfigAndInfo->ate.PresentBattVoltage = 3700;
	ShmSysConfigAndInfo->ate.PresentBattVoltage = 4700;
	ShmSysConfigAndInfo->ate.MinimumChargeCurrent = 20;

	ShmSysConfigAndInfo->ate.RequireVoltage = 3800;
	//ShmSysConfigAndInfo->ate.RequireVoltage = 4700;
	ShmSysConfigAndInfo->ate.RequireCurrent = 600;
	ShmSysConfigAndInfo->ate.targetVoltage_Value = 4800;
	ShmSysConfigAndInfo->ate.targetCurrent_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;
	//ShmSysConfigAndInfo->ate.chademo.id0B.EvStopReason = 0;
	//RequireVoltage 380
	//targetVoltage_Value 380
	//PresentBattVoltage

	//PresentInputPower
/*
	outputRelay.relay_event.bits.Gun1_N = 0x01;
	outputRelay.relay_event.bits.Gun1_P = 0x01;*/
	/*
	outputRelay.relay_event.bits.Gun2_N = 0x01;
	outputRelay.relay_event.bits.Gun2_P = 0x01;*/
	//outputRelay.relay_event.bits.Gun1_Parallel_N = 0x01;
	//outputRelay.relay_event.bits.Gun1_Parallel_P = 0x01;
	//Gun1_Parallel_P
	//Config_Relay_Output(Uart5Fd, Addr.Relay, &outputRelay);


	/*
	for(byte _index = 0; _index < gun_count; _index++)
				{

		_chargingData[_index]->Evboard_id = 0x01;
				}
				*/
	//EvseStopChargingEvent(normalStop, stopReason, 1);
	//SetChargingPermission(CCS_QUANTITY, 0, 1000, 1200, 6000, 1);
	setChargerMode(CCS_QUANTITY, STOP);
	/*
	outputRelay.relay_event.bits.Gun1_N = 0x01;
	outputRelay.relay_event.bits.Gun1_P = 0x01;
	outputRelay.relay_event.bits.Gun1_Parallel_N = 0x01;
	outputRelay.relay_event.bits.Gun1_Parallel_P = 0x01;
	Config_Relay_Output(Uart5Fd, Addr.Relay, &outputRelay);
	sleep(1);
//	flash = NO;
//	SetOutputGpio(flash);

	CheckGunTypeFromHw();
	CheckConnectorTypeStatus();
	//ShmSysConfigAndInfo->ate.chademo.id0D_req.K1K2Status = 1;
	SetEvContactorRelayStatus(CCS_QUANTITY);
	//Config_Relay_Output(Uart5Fd, Addr.Relay, &outputRelay);
	 *
	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);
	return 0;
*/


	while(CanFd)
	{

		//printf("%d \n", _chargingData[_index]->Evboard_id);
		setBootNotification2();
		/**/
		if(ShmSysConfigAndInfo->ate.status == 0){
			int status = isModeChange(CCS_QUANTITY);

			// 輸出電壓
			//GetPersentOutputVol();

			/*480+48/2*/
			// 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]);
				}
			}
			/*
			printf("relaystatus  = 0  %d %d %d targetVoltage_Value= %d targetCurrent_Value= %d RequireVoltage = %d RequireVoltage= %d RequireCurrent= %d MaxBatteryVoltage = %d\n",
					ShmSysConfigAndInfo->ate.chademo.id03.state,ShmSysConfigAndInfo->ate.chademo.id0D_req.K1K2Status,
					ShmSysConfigAndInfo->ate.chademo.PresentChargedDuration, ShmSysConfigAndInfo->ate.targetVoltage_Value ,
					ShmSysConfigAndInfo->ate.targetCurrent_Value, ShmSysConfigAndInfo->ate.RequireVoltage, ShmSysConfigAndInfo->ate.RequireVoltage,
					ShmSysConfigAndInfo->ate.RequireCurrent, ShmSysConfigAndInfo->ate.MaxBatteryVoltage);


			struct   timeb   tp;
		    ftime(&tp);
		    printf("===== %ld /n", tp.time);
			ftime(&endChargingTime[CCS_QUANTITY]);
			ShmSysConfigAndInfo->ate.chademo.PresentChargedDuration = DiffTimeb(startChargingTime[CCS_QUANTITY], endChargingTime[CCS_QUANTITY]);
			*/

			/*
			if(ShmSysConfigAndInfo->ate.chademo.id0B.EvStopReason != 0){
				setEVStatus2(evstaus[4]);
				ShmSysConfigAndInfo->ate.Permission = STOP;
				setChargerMode(CCS_QUANTITY, ShmSysConfigAndInfo->ate.Permission);
				ShmSysConfigAndInfo->ate.ATEStatus = 0x00;
				EvseStopChargingEvent(normalStop, stopReason, 1);
			}
			*/

			//int status = isModeChange(CCS_QUANTITY);
			//switch(_chargingData[CCS_QUANTITY]->SystemStatus)

			usleep(1000);
			setMisc(1);

			if(ShmSysConfigAndInfo->ate.ATEStatus == 1){
				ShmSysConfigAndInfo->ate.Permission = START;
				setChargerMode(CCS_QUANTITY, ShmSysConfigAndInfo->ate.Permission);
				//printf("ATEStatus == 1 %d \n",ShmSysConfigAndInfo->ate.ATEStatus);
			}else if(ShmSysConfigAndInfo->ate.ATEStatus == 2){
				ShmSysConfigAndInfo->ate.Permission = STOP;
				setChargerMode(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;
				setChargerMode(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;
				setChargerMode(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.targetVoltage_Value, ShmSysConfigAndInfo->ate.targetCurrent_Value, 1);
			usleep(1000);
			//SetPresentInputRequirement(4800, 6000, 1920, 20);
			SetPresentInputRequirement(ShmSysConfigAndInfo->ate.RequireVoltage, ShmSysConfigAndInfo->ate.RequireCurrent, ShmSysConfigAndInfo->ate.PresentBattVoltage, ShmSysConfigAndInfo->ate.MinimumChargeCurrent, 1);

			//usleep(5000);

		}else{

		}
		//500000 whileLoopTime
		//usleep(50000);500000
		usleep(whileLoopTime);
						/*
			for(byte _index = 0; _index < gun_count; _index++)
			{

				//printf("Permission : %d, TotalBatteryCapacity : %d, MaximumBatteryCurrent : %d, MaximumBatteryVoltage : %d, targetVoltage_Value : %d, targetCurrent_Value : %d, RequireVoltage : %d, RequireCurrent : %d, PresentBattVoltage : %d, MinimumChargeCurrent : %d, soc : %d \n", ShmSysConfigAndInfo->ate.Permission, ShmSysConfigAndInfo->ate.TotalBatteryCap, ShmSysConfigAndInfo->ate.MaxBatteryCurrent, ShmSysConfigAndInfo->ate.MaxBatteryVoltage, ShmSysConfigAndInfo->ate.targetVoltage_Value, ShmSysConfigAndInfo->ate.targetCurrent_Value, ShmSysConfigAndInfo->ate.RequireVoltage, ShmSysConfigAndInfo->ate.RequireCurrent, ShmSysConfigAndInfo->ate.PresentBattVoltage, ShmSysConfigAndInfo->ate.MinimumChargeCurrent, ShmSysConfigAndInfo->ate.chademo.id0D_req.Soc);
				//printf("EV_BOARD_STATUS_NOTIFICATION %d, %d \n", ShmSysConfigAndInfo->ate.chademo.id03.ProximitySignal, ShmSysConfigAndInfo->ate.chademo.id03.state);
				//printf("ACK__GET_EVSE_OUTPUT_STATUS %d, %d,%d, %d, %d \n", ShmSysConfigAndInfo->ate.chademo.id09_ack.DcEvState, ShmSysConfigAndInfo->ate.chademo.id09_ack.ChargingMode, ShmSysConfigAndInfo->ate.chademo.id09_ack.EvsePresentOutputVoltage, ShmSysConfigAndInfo->ate.chademo.id09_ack.EvsePresentOutputCurrent, ShmSysConfigAndInfo->ate.chademo.id09_ack.RemainingTimeSec);
				//printf("ACK_GET_EVSE_Capacity_INFO %d, %d,%d, %d \n", ShmSysConfigAndInfo->ate.chademo.id0A_ack.EvseMaxChargeVoltage, ShmSysConfigAndInfo->ate.chademo.id0A_ack.EvseMaxChargeCurrent, ShmSysConfigAndInfo->ate.chademo.id0A_ack.EvseMinChargeVoltage, ShmSysConfigAndInfo->ate.chademo.id0A_ack.EvseMinChargeCurrent);
				//printf("K1K2OnOff %d\n",ShmSysConfigAndInfo->ate.chademo.id0D_ack.K1K2OnOff);

				//setChargerMode(_index, mode)
				switch (_chargingData[_index]->SystemStatus)
				{

					case S_IDLE:{

						break;
					}
					case S_PREPARING_FOR_EV:
					{

						break;
					}
					case S_PREPARING_FOR_EVSE:
					case S_CCS_PRECHARGE_ST0:
					case S_CCS_PRECHARGE_ST1:
					{

						break;
					}
					case S_CHARGING:
					{

						break;
					}
					case S_TERMINATING:
					{
						break;
					}
					case S_COMPLETE:
					{
						break;
					}




			}
			//usleep(50000); //EV 小板通訊 (50 ms)

		}*/

		/*
					switch(_chargingData[CCS_QUANTITY]->SystemStatus)
					{
						case AS_ZERO:{//初始階段
							if (status){
								printf("Processing 0....................\n");
								//ShmSysConfigAndInfo->ate.Permission = START;
								//setChargerMode(CCS_QUANTITY, ShmSysConfigAndInfo->ate.Permission);
								//SetChargingPermission(CCS_QUANTITY, ShmSysConfigAndInfo->ate.Permission, ShmSysConfigAndInfo->ate.TotalBatteryCap, ShmSysConfigAndInfo->ate.MaxBatteryCurrent, ShmSysConfigAndInfo->ate.MaxBatteryVoltage, 1);
							}
							break;
						}
						case AS_ONE:{//ONE
							if (status){
								printf("Processing 1....................\n");
								//ShmSysConfigAndInfo->ate.Permission = STOP;
							}
							break;
						}
						case AS_TWO:{
							if (status){
								printf("Processing 2....................\n");
								//ShmSysConfigAndInfo->ate.Permission = STOP;
							}
							break;
						}
						case AS_THREE:{
							if (status){
								printf("Processing 3....................\n");
								//ShmSysConfigAndInfo->ate.Permission = STOP;
							}
							break;
						}
						case AS_FOUR:{
							if (status){
								printf("Processing 4....................\n");
								//ShmSysConfigAndInfo->ate.Permission = STOP;
							}
							break;
						}
						case AS_FIVE:{
							if (status){
								printf("Processing 5....................\n");
								//ShmSysConfigAndInfo->ate.Permission = STOP;
							}
							//setEVStatus2(evstaus[1]);
							break;
						}
						case AS_SIX:{
							if (status){
								printf("Processing 6....................\n");
								//ShmSysConfigAndInfo->ate.Permission = STOP;
							}
							//setEVStatus2(evstaus[1]);
							break;
						}
						case AS_SEVEN:{
							if (status){
								printf("Processing 7....................\n");
								//ShmSysConfigAndInfo->ate.Permission = STOP;
							}
							//setEVStatus2(evstaus[2]);
							break;
						}
						case AS_EIGHT:{
							if (status){
								printf("Processing 8....................\n");
								//ShmSysConfigAndInfo->ate.Permission = STOP;
							}
							//setEVStatus2(evstaus[2]);
							break;
						}
						case AS_NINE:{
							if (status){
								printf("Processing 9....................\n");
								//ShmSysConfigAndInfo->ate.Permission = STOP;
								//setEVStatus2(evstaus[3]);
							}
							break;
						}
						case AS_TEN:{
							if (status){
								printf("Processing 10....................\n");
								//ShmSysConfigAndInfo->ate.Permission = STOP;
								//setEVStatus2(evstaus[3]);
							}
							break;
						}
						case AS_ELEVEN:{
							if (status){
								printf("Processing 11....................\n");
								//ShmSysConfigAndInfo->ate.Permission = STOP;
								//setEVStatus2(evstaus[3]);
							}
							break;
						}
						case AS_TWELVE:{
							if (status){
								printf("Processing 12....................\n");
								//ShmSysConfigAndInfo->ate.Permission = STOP;
								//setEVStatus2(evstaus[3]);
							}
							break;
						}
						case AS_THIRTEEN:{
							if (status){
								printf("Processing 13....................\n");
								//handleEmulatorFaultStatus();
							}
							break;
						}
						case AS_FOURTEEN:{
							if (status){
								printf("Processing 14....................\n");
								//handleEmulatorFaultStatus();
								//ShmSysConfigAndInfo->ate.Permission = STOP;
							}
							break;
						}
						case AS_FIFTEEN:{
							if (status){
								printf("Processing 15....................\n");
								//handleEmulatorFaultStatus();
							}
							break;
						}
						case AS_SIXTEEN:{
							if (status){
								printf("Processing 16....................\n");
								//handleEmulatorFaultStatus();
							}
							break;
						}
						case AS_SEVENTEEN:{
							if (status){
								printf("Processing 17....................\n");
								//handleEmulatorFaultStatus();
							}
							break;
						}
						case AS_EIGHTEEN:{
							if (status){
								printf("Processing 18....................\n");
								//handleEmulatorFaultStatus();
							}
							break;
						}
						default:{
							break;
						}
					}*/
	}
	/*
	byte priorityLow = 1;

#if (!DEMO)
	while(CanFd)
	{
		for(byte _index = 0; _index < gun_count; _index++)
		{
			if (priorityLow == 1)
			{
				// 優先權較低 - 只要有回應即不會再詢問
				if (_chargingData[_index]->Type == _Type_Chademo &&
						ShmCHAdeMOData->evse[_chargingData[_index]->type_index].SelfTest_Comp != PASS)
				{
					GetFirmwareVersion(_index, _chargingData[_index]->Evboard_id);
					GetHardwareVersion(_index, _chargingData[_index]->Evboard_id);
				}
				else if (_chargingData[_index]->Type == _Type_CCS)
				{
					if (ShmCcsData->CommProtocol == 0x01 &&
						ShmCcsData->V2GMessage_DIN70121[_chargingData[_index]->type_index].SelfTest_Comp != PASS)
					{
						GetFirmwareVersion(_index, _chargingData[_index]->Evboard_id);
						GetHardwareVersion(_index, _chargingData[_index]->Evboard_id);
					}
				}

				// 固定要取得的資訊 : 1.槍鎖狀態, 2."Connector 1" 溫度, 3."Connector 2" 溫度, 4.Pilot Voltage
				GetMiscellaneousInfo(_index, _chargingData[_index]->Evboard_id, 1);
			}

			switch (_chargingData[_index]->SystemStatus)
			{
				case S_IDLE:
					_chargingData[_index]->PresentChargedEnergy = 0;
					_chargingData[_index]->GroundFaultStatus = GFD_WAIT;
					_chargingData[_index]->StopChargeFlag = NO;
					_chargingData[_index]->PrechargeStatus = NO;
					chargingTime[_index] = 0;

					if (_chargingData[_index]->Type == _Type_Chademo)
					{
						ClearAbnormalStatus_Chadmoe(_index);
					}
					else if (_chargingData[_index]->Type == _Type_CCS)
					{
						ClearAbnormalStatus_CCS(_index);
					}
					break;
				case S_PREPARING_FOR_EV:
				{
					if (_chargingData[_index]->Type == _Type_Chademo)
					{
						// 開始確認車端是否同意開始充電 : 1.SOC, 2.Target Vol, 3.Target Cur, 4.Charging remaining time
						GetOutputReq(_index, _chargingData[_index]->Evboard_id);

						//printf("PresentChargingVoltage = %f \n", _chargingData[_index]->PresentChargingVoltage);
						//printf("PresentChargingCurrent = %f \n", _chargingData[_index]->PresentChargingCurrent);
						//printf("AvailableChargingPower = %f \n", _chargingData[_index]->AvailableChargingPower);
						//printf("AvailableChargingCurrent = %f \n", _chargingData[_index]->AvailableChargingCurrent);
						//printf("MaximumChargingVoltage = %f \n", _chargingData[_index]->MaximumChargingVoltage);

						// 設定當前輸出
						if (gun_count == 1)
							SetPresentChargingOutputPower(_chargingData[0], _chargingData[0]);
						else if (gun_count == 2)
							SetPresentChargingOutputPower(_chargingData[0], _chargingData[1]);

						if (priorityLow == 1)
						{
							float maxVol = _chargingData[_index]->MaximumChargingVoltage;
							float maxCur = _chargingData[_index]->AvailableChargingCurrent;

							GetMaxVolAndCurMethod(_index, &maxVol, &maxCur);
							// 樁端輸出能力
							SetChargingPermission(_index, START,
									_chargingData[_index]->AvailableChargingPower,
									maxCur,
									maxVol,
									_chargingData[_index]->Evboard_id);

							// 取得車端電池資訊 : 1.AC or DC ? 2.Total battery cap, 3.Max battery vol, 4.Max battery cur
							GetEvBatteryInfo(_index, _chargingData[_index]->Evboard_id);
						}
					}
					else if (_chargingData[_index]->Type == _Type_CCS)
					{
						// 開始確認車端是否同意開始充電 : 1.SOC, 2.Target Vol, 3.Target Cur, 4.Charging remaining time
						GetOutputReq(_index, _chargingData[_index]->Evboard_id);

						// 設定當前輸出
						if (gun_count == 1)
							SetPresentChargingOutputPower(_chargingData[0], _chargingData[0]);
						else if (gun_count == 2)
							SetPresentChargingOutputPower(_chargingData[0], _chargingData[1]);

						if (priorityLow == 1)
						{
							float maxVol = _chargingData[_index]->MaximumChargingVoltage;
							float maxCur = _chargingData[_index]->AvailableChargingCurrent;

							GetMaxVolAndCurMethod(_index, &maxVol, &maxCur);
							// 樁端輸出能力
							SetChargingPermission(_index, START,
									_chargingData[_index]->AvailableChargingPower,
									maxCur,
									maxVol,
									_chargingData[_index]->Evboard_id);

							// 取得車端電池資訊 : 1.AC or DC ? 2.Total battery cap, 3.Max battery vol, 4.Max battery cur
							GetEvBatteryInfo(_index, _chargingData[_index]->Evboard_id);
						}
					}
				}
					break;
				case S_PREPARING_FOR_EVSE:
				case S_CCS_PRECHARGE_ST0:
				case S_CCS_PRECHARGE_ST1:
				{
					// 開始確認車端是否同意開始充電
					GetOutputReq(_index, _chargingData[_index]->Evboard_id);

//					printf("PresentChargingVoltage = %f \n", _chargingData[_index]->PresentChargingVoltage);
//					printf("PresentChargingCurrent = %f \n", _chargingData[_index]->PresentChargingCurrent);
//					printf("AvailableChargingPower = %f \n", _chargingData[_index]->AvailableChargingPower);
//					printf("AvailableChargingCurrent = %f \n", _chargingData[_index]->AvailableChargingCurrent);
//					printf("MaximumChargingVoltage = %f \n", _chargingData[_index]->MaximumChargingVoltage);

					// 設定當前輸出
					if (gun_count == 1)
						SetPresentChargingOutputPower(_chargingData[0], _chargingData[0]);
					else if (gun_count == 2)
						SetPresentChargingOutputPower(_chargingData[0], _chargingData[1]);

					if (priorityLow % 5 == 1)
					{
						// 樁端輸出能力改變
						if (gun_count == 1)
							SetPresentChargingOutputCap(_chargingData[0], _chargingData[0]);
						else if (gun_count == 2)
							SetPresentChargingOutputCap(_chargingData[0], _chargingData[1]);
					}

					// 持續通知 Isolation 測試狀態
					if (priorityLow == 1)
					{
						// 拉 500 V 如果在一秒鐘內 GFD 都符合則 PASS
						//printf("GFD = %d \n", _chargingData[_index]->GroundFaultStatus);//
						if(_chargingData[_index]->GroundFaultStatus != GFD_WAIT)
						{
							SetIsolationStatus(_index, _chargingData[_index]->GroundFaultStatus, _chargingData[_index]->Evboard_id);
						}

						if(_chargingData[_index]->SystemStatus == S_CCS_PRECHARGE_ST0 &&
							_chargingData[_index]->PrechargeStatus == PRECHARGE_READY)
						{
							SetEvsePrechargeInfo(_index, PRECHARGE_PRERELAY_PASS, _chargingData[_index]->Evboard_id);
						}
					}
				}
					break;
				case S_CHARGING:
				{
					// 計算 Power
					_chargingData[_index]->PresentChargingPower = ((float)((_chargingData[_index]->PresentChargingVoltage / 10) * (_chargingData[_index]->PresentChargingCurrent / 10)) / 1000);

					if (chargingTime[_index] == 0)
					{
						chargingTime[_index] = _chargingData[_index]->RemainChargingDuration;
					}
					else
					{
						int passTime = _chargingData[_index]->RemainChargingDuration - chargingTime[_index];

						if (passTime > 0)
						{
							_chargingData[_index]->PresentChargedEnergy += (_chargingData[_index]->PresentChargingPower) * passTime / 3600;
							chargingTime[_index] = _chargingData[_index]->RemainChargingDuration;
						}
					}

					// 開始確認車端是否同意開始充電
					GetOutputReq(_index, _chargingData[_index]->Evboard_id);

//				printf("PresentChargingVoltage = %f \n",
//						_chargingData[_index]->PresentChargingVoltage);
//				printf("PresentChargingCurrent = %f \n",
//						_chargingData[_index]->PresentChargingCurrent);
//				printf("AvailableChargingPower = %f \n",
//						_chargingData[_index]->AvailableChargingPower);
//				printf("AvailableChargingCurrent = %f \n",
//						_chargingData[_index]->AvailableChargingCurrent);
//
//				printf("GFD : index = %d, result = %d, id = %d \n", _index, _chargingData[_index]->GroundFaultStatus, _chargingData[_index]->Evboard_id);
					// 設定當前輸出
					if (gun_count == 1)
						SetPresentChargingOutputPower(_chargingData[0], _chargingData[0]);
					else if (gun_count == 2)
						SetPresentChargingOutputPower(_chargingData[0], _chargingData[1]);

					// for test end
					if (priorityLow == 1)
					{
						// 樁端輸出能力改變
						if (gun_count == 1)
							SetPresentChargingOutputCap(_chargingData[0], _chargingData[0]);
						else if (gun_count == 2)
							SetPresentChargingOutputCap(_chargingData[0], _chargingData[1]);
					}

					// GFD 失敗再通知
					if (priorityLow == 1)
					{
						printf("GFD : index = %d, result = %d, id = %d \n", _index, _chargingData[_index]->GroundFaultStatus, _chargingData[_index]->Evboard_id);
						if(_chargingData[_index]->GroundFaultStatus == GFD_FAIL)
						{
							SetIsolationStatus(_index, _chargingData[_index]->GroundFaultStatus, _chargingData[_index]->Evboard_id);
						}

						if(_chargingData[_index]->Type == _Type_CCS &&
							_chargingData[_index]->PrechargeStatus == PRECHARGE_READY)
						{
							SetEvsePrechargeInfo(_index, PRECHARGE_CHARELAY_PASS, _chargingData[_index]->Evboard_id);
						}
					}
				}
					break;
				case S_TERMINATING:
				{
					// 設定當前輸出
					if (gun_count == 1)
						SetPresentChargingOutputPower(_chargingData[0], _chargingData[0]);
					else if (gun_count == 2)
						SetPresentChargingOutputPower(_chargingData[0], _chargingData[1]);

					// 槍鎖還在,則代表是樁端要求的停止
					if (_chargingData[_index]->GunLocked == START)
					{
						byte normalStop = 0x01;
						byte stopReason[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

						if (strlen((char *)ShmSysConfigAndInfo->SysStopChargingAlarmCode.StopCode[_index]) > 0)
						{
							normalStop = 0x02;
							GetStopChargingReasonByEvse(_index, stopReason);
						}
						else
						{
							DEBUG_INFO("EVSE Normal Stop by User, index = %d \n", _index);
							ShmStatusCodeData->InfoCode.InfoEvents.bits.NormalStopChargingByUser = 0x01;
							GetStopChargingReasonByEvse(_index, stopReason);
							char string[7];
							sprintf(string, "%d%d%d%d%d%d", *(stopReason + 5), *(stopReason + 4), *(stopReason + 3), *(stopReason + 2), *(stopReason + 1), *(stopReason + 0));
							memcpy(&ShmSysConfigAndInfo->SysStopChargingAlarmCode.StopCode[_index][0], string, 7);
							ShmSysConfigAndInfo->SysStopChargingAlarmCode.Level = 0x00;
						}

						EvseStopChargingEvent(normalStop, stopReason, _chargingData[_index]->Evboard_id);
					}
					GetOutputReq(_index, _chargingData[_index]->Evboard_id);
				}
					break;
				case S_COMPLETE:
				{
					if (priorityLow == 1)
					{
						float maxVol = _chargingData[_index]->MaximumChargingVoltage;
						float maxCur = _chargingData[_index]->AvailableChargingCurrent;

						GetMaxVolAndCurMethod(_index, &maxVol, &maxCur);
						SetChargingPermission(_index, STOP,
							_chargingData[_index]->AvailableChargingPower,
							maxCur,
							maxVol,
							_chargingData[_index]->Evboard_id);
					}
				}
					break;
			}
		}
		priorityLow >= 20 ? priorityLow = 1 : priorityLow++;
		usleep(45000); //EV 小板通訊 (50 ms)
	}
#else
	while (CanFd)
	{
		for (byte _index = 0; _index < gun_count; _index++)
		{
			if (priorityLow == 1)
			{
				// 優先權較低 - 只要有回應即不會再詢問
				if (_chargingData[_index]->Type	== _Type_Chademo &&
						ShmCHAdeMOData->evse[_chargingData[_index]->type_index].SelfTest_Comp != PASS)
				{
					GetFirmwareVersion(_index, _chargingData[_index]->Evboard_id);
					GetHardwareVersion(_index, _chargingData[_index]->Evboard_id);
				} else if (_chargingData[_index]->Type == _Type_CCS)
				{
					if (ShmCcsData->CommProtocol == 0x01&&
							ShmCcsData->V2GMessage_DIN70121[_chargingData[_index]->type_index].SelfTest_Comp != PASS)
					{
						GetFirmwareVersion(_index, _chargingData[_index]->Evboard_id);
						GetHardwareVersion(_index, _chargingData[_index]->Evboard_id);
					}
				}

				// 固定要取得的資訊 : 1.槍鎖狀態, 2."Connector 1" 溫度, 3."Connector 2" 溫度, 4.Pilot Voltage
				GetMiscellaneousInfo(_index, _chargingData[_index]->Evboard_id);
			}

			switch (_chargingData[_index]->SystemStatus)
			{
				case S_IDLE:
				{
					_chargingData[_index]->GroundFaultStatus = GFD_WAIT;
					_chargingData[_index]->StopChargeFlag = NO;
					chargingTime[_index] = 0;
					if (_chargingData[_index]->Type == _Type_Chademo)
					{
						ClearAbnormalStatus_Chadmoe(_index);
					}
					else if (_chargingData[_index]->Type == _Type_CCS)
					{

					}
				}
					break;
			case S_PREPARING_FOR_EV:
			{
				if (_chargingData[_index]->Type == _Type_Chademo)
				{
					// 開始確認車端是否同意開始充電 : 1.SOC, 2.Target Vol, 3.Target Cur, 4.Charging remaining time
					GetOutputReq(_index, _chargingData[_index]->Evboard_id);

					// 設定當前輸出
					if (gun_count == 1)
						SetPresentChargingOutputPower(_chargingData[0], _chargingData[0]);
					else if (gun_count == 2)
						SetPresentChargingOutputPower(_chargingData[0],	_chargingData[1]);

					if (priorityLow == 1)
					{
						SetChargingPermission(_index, START,
								_chargingData[_index]->AvailableChargingPower,
								1200, 5000, _chargingData[_index]->Evboard_id);

						// 取得車端電池資訊 : 1.AC or DC ? 2.Total battery cap, 3.Max battery vol, 4.Max battery cur
						GetEvBatteryInfo(_index, _chargingData[_index]->Evboard_id);
					}
				} else if (_chargingData[_index]->Type == _Type_CCS)
				{
					// 開始確認車端是否同意開始充電 : 1.SOC, 2.Target Vol, 3.Target Cur, 4.Charging remaining time
					GetOutputReq(_index, _chargingData[_index]->Evboard_id);

					// 設定當前輸出
					if (gun_count == 1)
						SetPresentChargingOutputPower(_chargingData[0],	_chargingData[0]);
					else if (gun_count == 2)
						SetPresentChargingOutputPower(_chargingData[0],	_chargingData[1]);

					if (priorityLow == 1)
					{
						// 樁端輸出能力
						SetChargingPermission(_index, START,
								_chargingData[_index]->AvailableChargingPower,
								_chargingData[_index]->AvailableChargingCurrent,
								_chargingData[_index]->MaximumChargingVoltage,
								_chargingData[_index]->Evboard_id);

						// 取得車端電池資訊 : 1.AC or DC ? 2.Total battery cap, 3.Max battery vol, 4.Max battery cur
						GetEvBatteryInfo(_index, _chargingData[_index]->Evboard_id);
					}
				}
			}
				break;
			case S_PREPARING_FOR_EVSE:
			case S_CCS_PRECHARGE_ST0:
			case S_CCS_PRECHARGE_ST1:
			{
				// 開始確認車端是否同意開始充電
				GetOutputReq(_index, _chargingData[_index]->Evboard_id);

				// 假裝從 Relay 量到的火線上電壓
				_chargingData[_index]->PresentChargingCurrent =	_chargingData[_index]->EvBatterytargetCurrent;
				_chargingData[_index]->PresentChargingVoltage =	_chargingData[_index]->EvBatterytargetVoltage;

				// 設定當前輸出
				if (gun_count == 1)
					SetPresentChargingOutputPower(_chargingData[0],	_chargingData[0]);
				else if (gun_count == 2)
					SetPresentChargingOutputPower(_chargingData[0],	_chargingData[1]);

				if (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag != 0x00)
				{
					if (priorityLow % 5 == 1)
					{
						// 樁端輸出能力改變
						if (gun_count == 1)
							SetPresentChargingOutputCap(_chargingData[0], _chargingData[0]);
						else if (gun_count == 2)
							SetPresentChargingOutputCap(_chargingData[0], _chargingData[1]);
					}
				}

				// 持續通知 Isolation 測試狀態
				if (priorityLow == 1) {
					// 拉 500 V 如果在一秒鐘內 GFD 都符合則 PASS
					_chargingData[_index]->GroundFaultStatus = GFD_PASS;
					if (_chargingData[_index]->GroundFaultStatus != GFD_WAIT)
					{
						SetIsolationStatus(_index,
								_chargingData[_index]->GroundFaultStatus,
								_chargingData[_index]->Evboard_id);
					}

					if (_chargingData[_index]->SystemStatus	== S_CCS_PRECHARGE_ST1&&
							_chargingData[_index]->PrechargeStatus == PRECHARGE_WAIT)
					{
						SetEvsePrechargeInfo(_index, PRECHARGE_PRERELAY_PASS, _chargingData[_index]->Evboard_id);
					}
				}
			}
				break;
			case S_CHARGING:
			{
				// 假裝從 Relay 量到的火線上電壓電流
				_chargingData[_index]->PresentChargingCurrent =	_chargingData[_index]->EvBatterytargetCurrent;
				_chargingData[_index]->PresentChargingVoltage =	_chargingData[_index]->EvBatterytargetVoltage;
				_chargingData[_index]->PresentChargingPower = ((float) ((_chargingData[_index]->PresentChargingVoltage / 10)
								* (_chargingData[_index]->PresentChargingCurrent / 10)) / 1000);

				if (chargingTime[_index] == 0)
				{
					chargingTime[_index] = _chargingData[_index]->RemainChargingDuration;
				}
				else
				{
					int passTime = _chargingData[_index]->RemainChargingDuration - chargingTime[_index];

					if (passTime > 0)
					{
						_chargingData[_index]->PresentChargedEnergy += (_chargingData[_index]->PresentChargingPower) * passTime / 3600;
						chargingTime[_index] = _chargingData[_index]->RemainChargingDuration;
					}
				}

				// 開始確認車端是否同意開始充電
				GetOutputReq(_index, _chargingData[_index]->Evboard_id);

				// 設定當前輸出
				if (gun_count == 1)
					SetPresentChargingOutputPower(_chargingData[0],	_chargingData[0]);
				else if (gun_count == 2)
					SetPresentChargingOutputPower(_chargingData[0],	_chargingData[1]);

				// for test end
				if (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag != 0x00)
				{
					if (priorityLow % 5 == 0)
					{
						// 樁端輸出能力改變
						if (gun_count == 1)
							SetPresentChargingOutputCap(_chargingData[0], _chargingData[0]);
						else if (gun_count == 2)
							SetPresentChargingOutputCap(_chargingData[0], _chargingData[1]);
					}
				}

				// GFD 失敗再通知
				if (priorityLow == 1)
				{
					if (_chargingData[_index]->GroundFaultStatus == GFD_FAIL)
					{
						SetIsolationStatus(_index,
								_chargingData[_index]->GroundFaultStatus,
								_chargingData[_index]->Evboard_id);
					}

					if (_chargingData[_index]->Type == _Type_CCS&&
					_chargingData[_index]->PrechargeStatus == PRECHARGE_WAIT)
					{
						SetEvsePrechargeInfo(_index, PRECHARGE_CHARELAY_PASS,
								_chargingData[_index]->Evboard_id);
					}
				}
			}
				break;
			case S_TERMINATING:
			{
				// 設定當前輸出
				if (gun_count == 1)
					SetPresentChargingOutputPower(_chargingData[0],	_chargingData[0]);
				else if (gun_count == 2)
					SetPresentChargingOutputPower(_chargingData[0], _chargingData[1]);

				// 槍鎖還在,則代表是樁端要求的停止
				if (_chargingData[_index]->GunLocked == START)
				{
					byte normalStop = 0x01;
					byte stopReason[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

					if (strlen((char *) ShmSysConfigAndInfo->SysStopChargingAlarmCode.StopCode[_index])	> 0)
					{
						normalStop = 0x02;
						GetStopChargingReasonByEvse(_index, stopReason);
					}

					EvseStopChargingEvent(normalStop, stopReason, _chargingData[_index]->Evboard_id);
				}
				GetOutputReq(_index, _chargingData[_index]->Evboard_id);
			}
				break;
			case S_COMPLETE:
			{
				if (priorityLow == 1)
				{
					SetChargingPermission(_index, STOP,
							_chargingData[_index]->AvailableChargingPower,
							_chargingData[_index]->AvailableChargingCurrent,
							_chargingData[_index]->MaximumChargingVoltage,
							_chargingData[_index]->Evboard_id);
				}
			}
				break;
			}
		}
		priorityLow >= 20 ? priorityLow = 1 : priorityLow++;
		usleep(45000); //EV 小板通訊 (50 ms)
	}
#endif
*/
	//DEBUG_INFO("Module_EvComm : Can-bus port = %d \n", CanFd);
	return FAIL;
}