Parcourir la source

2019-12-30 / Folus Wen

Actions:
1. EVSE/Projects/define.h add variable in struct CHAdeMOEvData & struct SysInfoData.

Files:
1. As follow commit history.
FolusWen il y a 5 ans
Parent
commit
486b634e53
34 fichiers modifiés avec 5741 ajouts et 0 suppressions
  1. 126 0
      EVSE/Projects/DM30/Apps/Config.h
  2. BIN
      EVSE/Projects/DM30/Apps/Ev_Comm.o
  3. 190 0
      EVSE/Projects/DM30/Apps/FactoryConfig.c
  4. 57 0
      EVSE/Projects/DM30/Apps/Makefile
  5. BIN
      EVSE/Projects/DM30/Apps/Module_EvComm
  6. BIN
      EVSE/Projects/DM30/Apps/Module_EvComm.o
  7. BIN
      EVSE/Projects/DM30/Apps/Module_EventLogging
  8. 298 0
      EVSE/Projects/DM30/Apps/Module_EventLogging.c
  9. BIN
      EVSE/Projects/DM30/Apps/Module_EventLogging.o
  10. BIN
      EVSE/Projects/DM30/Apps/Module_InternalComm
  11. 1312 0
      EVSE/Projects/DM30/Apps/Module_InternalComm.c
  12. BIN
      EVSE/Projects/DM30/Apps/Module_InternalComm.o
  13. BIN
      EVSE/Projects/DM30/Apps/Module_LcmControl
  14. BIN
      EVSE/Projects/DM30/Apps/Module_LcmControl.o
  15. BIN
      EVSE/Projects/DM30/Apps/Module_PrimaryComm
  16. BIN
      EVSE/Projects/DM30/Apps/Module_PrimaryComm.o
  17. BIN
      EVSE/Projects/DM30/Apps/Module_PsuComm
  18. BIN
      EVSE/Projects/DM30/Apps/Module_PsuComm.o
  19. BIN
      EVSE/Projects/DM30/Apps/PrimaryComm.o
  20. BIN
      EVSE/Projects/DM30/Apps/ReadCmdline
  21. BIN
      EVSE/Projects/DM30/Apps/ReadCmdline.o
  22. 751 0
      EVSE/Projects/DM30/Apps/internalComm.c
  23. 186 0
      EVSE/Projects/DM30/Apps/internalComm.h
  24. BIN
      EVSE/Projects/DM30/Apps/internalComm.o
  25. BIN
      EVSE/Projects/DM30/Apps/main
  26. 2761 0
      EVSE/Projects/DM30/Apps/main.c
  27. BIN
      EVSE/Projects/DM30/Apps/main.o
  28. 5 0
      EVSE/Projects/DM30/Apps/timeout.c
  29. 52 0
      EVSE/Projects/DM30/Apps/timeout.h
  30. BIN
      EVSE/Projects/DM30/Apps/timeout.o
  31. BIN
      EVSE/Projects/DM30/Images/root/FactoryConfig
  32. BIN
      EVSE/Projects/DM30/Images/root/Module_EventLogging
  33. BIN
      EVSE/Projects/DM30/Images/root/Module_InternalComm
  34. 3 0
      EVSE/Projects/define.h

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

@@ -0,0 +1,126 @@
+/*
+ * Config.h
+ *
+ *  Created on: 2019年4月23日
+ *      Author: foluswen
+ */
+
+#ifndef CONFIG_H_
+#define CONFIG_H_
+
+typedef unsigned char			byte;
+
+#define TOTAL_QUANTITY_GUN			4				//Max Count
+#define MODE_BOOT					0
+#define MODE_IDLE					1
+#define MODE_AUTHORIZING			2
+#define MODE_REASSIGN_CHECK			3
+#define MODE_REASSIGN				4
+#define MODE_PRECHARGE				5
+#define MODE_PREPARE_FOR_EV			6
+#define MODE_PREPARE_FOR_EVSE		7
+#define MODE_CHARGING				8
+#define MODE_TERMINATING			9
+#define MODE_COMPLETE				10
+#define MODE_ALARM					11
+#define MODE_RESERVATION			12
+#define MODE_BOOKING				13
+#define MODE_MAINTAIN				14
+#define MODE_DEBUG					15
+#define MODE_CCS_PRECHARGE_STEP0	16 	// ready for ccs precharge processing, For D+ relay to precharge relay
+#define MODE_CCS_PRECHARGE_STEP1	17	// waitting for ev board inform to enter to charging, For precharge relay to D+ relay
+#define MODE_SINGLE_RUN				18
+
+#define GFD_WAIT			0
+#define GFD_PASS			1
+#define GFD_FAIL			2
+
+#define PRECHARGE_WAIT				0
+#define PRECHARGE_READY				1
+#define PRECHARGE_PRERELAY_PASS		2
+#define PRECHARGE_CHARELAY_PASS		3
+
+#define BOOTTING			0
+#define BOOT_COMPLETE		1
+
+enum _SYSTEM_STATUS
+{
+	S_BOOTING = 						0,
+    S_IDLE,
+	S_AUTHORIZING,
+	S_REASSIGN_CHECK,
+	S_REASSIGN,
+	S_PREPARNING,
+	S_PREPARING_FOR_EV,
+	S_PREPARING_FOR_EVSE,
+    S_CHARGING,
+	S_TERMINATING,
+	S_COMPLETE,
+	S_ALARM,
+	S_RESERVATION,
+	S_BOOKING,
+	S_MAINTAIN,
+	S_DEBUG,
+	S_CCS_PRECHARGE_ST0,
+	S_CCS_PRECHARGE_ST1,
+	S_SINGLE_RUN,
+};
+
+enum _GUN_TYPE
+{
+	_Type_Chademo = 		0,
+	_Type_CCS,
+	_Type_GB,
+};
+
+enum _LCM_INDEX
+{
+	_LCM_INIT = 			0x00,
+	_LCM_IDLE = 			0x01,
+	_LCM_AUTHORIZING = 		0x04,
+	_LCM_AUTHORIZ_COMP = 	0x05,
+	_LCM_AUTHORIZ_FAIL = 	0x06,
+	_LCM_WAIT_FOR_PLUG = 	0x07,
+	_LCM_PRE_CHARGE = 		0x08,
+	_LCM_CHARGING = 		0x09,
+	_LCM_COMPLETE = 		0x0A,
+	_LCM_FIX = 				0x0B,
+	_LCM_NONE = 			0xFF,
+};
+
+enum _SELF_TEST_SEQ
+{
+	_STEST_VERSION = 0x00,
+	_STEST_AC_CONTACTOR = 0x01,
+	_STEST_PSU_DETECT = 0x02,
+	_STEST_PSU_CAP = 0x03,
+	_STEST_FAIL = 0x04,
+	_STEST_COMPLETE = 0xFE,
+};
+
+enum _MODULE_PSU_WORK_STEP
+{
+	ASSIGN_START 	= 			0,
+	ASSIGN_COMP 	= 			1,
+	ENABLE_POW		=			2,
+	_TEST_LINE_STEP 	= 		3,
+	_TEST_POWER_STEP 	= 		4,
+	_TEST_COMPLETE 		= 		5,
+
+	_WORK_CHARGING 	= 			10,
+
+	_NO_WORKING			= 		254,
+};
+
+enum _REASSIGNED_RESOURCE_STEP
+{
+	_REASSIGNED_NONE = 			0,	//
+	_REASSIGNED_PREPARE = 		1,	// 系統收到需要降載需求 (輸出總電流降低),PSU Task 收到將狀態切換至下個狀態
+	_REASSIGNED_GET_NEW_CAP = 	2,	// 充電中的重新取得屬於自己火線上的總能量並透過小板通知車端 - 超過10秒直接跳下一步
+	_REASSIGNED_ADJUST = 		3,	// 車端降載完成,模塊能量重新調整
+	_REASSIGNED_RELAY = 		4,	// 切斷橋接的 Relay
+	_REASSIGNED_MAIN = 			5,  // 重新分配 PSU
+	_REASSIGNED_COMP = 			6,	// 完成
+};
+
+#endif /* CONFIG_H_ */

BIN
EVSE/Projects/DM30/Apps/Ev_Comm.o


+ 190 - 0
EVSE/Projects/DM30/Apps/FactoryConfig.c

@@ -0,0 +1,190 @@
+#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"
+
+/**************************************************************************************/
+/************This task will create Factory default confgiuration file *****************/
+ /***********and store it into mtdblock 10,11,12                               ****************/
+/**************************************************************************************/
+int StoreLogMsg(const char *fmt, ...);
+#define DEBUG_INFO(format, args...) StoreLogMsg("[%s:%d][%s][Info] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+#define DEBUG_WARN(format, args...) StoreLogMsg("[%s:%d][%s][Warn] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+#define DEBUG_ERROR(format, args...) StoreLogMsg("[%s:%d][%s][Error] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+
+int StoreLogMsg(const char *fmt, ...)
+{
+	char Buf[4096+256];
+	char buffer[4096];
+	time_t CurrentTime;
+	struct tm *tm;
+	va_list args;
+
+	va_start(args, fmt);
+	int rc = vsnprintf(buffer, sizeof(buffer), fmt, args);
+	va_end(args);
+
+	memset(Buf,0,sizeof(Buf));
+	CurrentTime = time(NULL);
+	tm=localtime(&CurrentTime);
+	sprintf(Buf,"echo \"%04d-%02d-%02d %02d:%02d:%02d - %s\" >> /Storage/SystemLog/[%04d.%02d]SystemLog",
+			tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec,
+			buffer,
+			tm->tm_year+1900,tm->tm_mon+1);
+	system(Buf);
+
+	return rc;
+}
+
+int main(int argc,char *argv[])
+{
+	struct SysConfigData 	SysConfig;
+	unsigned int i,Chk;
+	unsigned char *ptr;
+	int fd,wrd;
+
+	ptr=malloc(sizeof(struct SysConfigData));
+	if(ptr==NULL)
+	{
+		#ifdef SystemLogMessage
+		StoreLogMsg("[FactoryConfig]main: malloc for SysConfigData NG");
+		#endif
+		return 0;
+	}
+	memset(ptr,0,sizeof(struct SysConfigData));
+	memset(&SysConfig,0,sizeof(struct SysConfigData));
+
+	//Set default configuration
+	strcpy((char *)SysConfig.Eth0Interface.EthIpAddress, "192.168.1.10");
+	strcpy((char *)SysConfig.Eth0Interface.EthSubmaskAddress,"255.255.255.0");
+	strcpy((char *)SysConfig.Eth0Interface.EthGatewayAddress,"192.168.1.254");
+	strcpy((char *)SysConfig.Eth1Interface.EthIpAddress,"192.168.0.10");
+	strcpy((char *)SysConfig.Eth1Interface.EthSubmaskAddress,"255.255.255.0");
+	strcpy((char *)SysConfig.Eth1Interface.EthGatewayAddress,"192.168.0.254");
+	SysConfig.BackendConnTimeout=300; //300 seconds
+
+	//copy default configuration to pointer
+	memcpy(ptr,&SysConfig,sizeof(struct SysConfigData));
+
+	//calculate CRC
+	Chk=0;
+	for(i=0;i<(sizeof(struct SysConfigData)-4);i++)
+	{
+		Chk+=*(ptr+i);
+	}
+	SysConfig.Checksum=Chk;
+
+	fd = open("/mnt/FactoryDefaultConfig.bin", O_RDWR|O_CREAT);
+	if (fd < 0)
+	{
+		#ifdef SystemLogMessage
+		StoreLogMsg("[FactoryConfig]main: open /mnt/FactoryDefaultConfig.bin NG");
+		#endif
+		free(ptr);
+		return 0;
+	}
+
+	wrd=write(fd, &SysConfig, sizeof(struct SysConfigData));
+	close(fd);
+	if(wrd!=(sizeof(struct SysConfigData)))
+	{
+		#ifdef SystemLogMessage
+		StoreLogMsg("[FactoryConfig]main: write /mnt/FactoryDefaultConfig.bin NG");
+		#endif
+		free(ptr);
+		return 0;
+	}
+
+	fd = open("/dev/mtdblock12", O_RDWR);
+	if (fd < 0)
+	{
+		#ifdef SystemLogMessage
+		StoreLogMsg("[FactoryConfig]main: open /dev/mtdblock12 NG");
+		#endif
+		free(ptr);
+		return 0;
+   	 }
+    	wrd=write(fd, &SysConfig, sizeof(struct SysConfigData));
+    	close(fd);
+    	if(wrd!=(sizeof(struct SysConfigData)))
+	{
+		#ifdef SystemLogMessage
+		StoreLogMsg("[FactoryConfig]main: write /dev/mtdblock12 NG");
+		#endif
+		free(ptr);
+		return 0;
+	}
+
+	fd = open("/dev/mtdblock11", O_RDWR);
+	if (fd < 0)
+	{
+		#ifdef SystemLogMessage
+		StoreLogMsg("[FactoryConfig]main: open /dev/mtdblock11 NG");
+		#endif
+		free(ptr);
+		return 0;
+   	 }
+    	wrd=write(fd, &SysConfig, sizeof(struct SysConfigData));
+    	close(fd);
+    	if(wrd!=(sizeof(struct SysConfigData)))
+	{
+		#ifdef SystemLogMessage
+		StoreLogMsg("[FactoryConfig]main: write /dev/mtdblock11 NG");
+		#endif
+		free(ptr);
+		return 0;
+	}
+
+	fd = open("/dev/mtdblock10", O_RDWR);
+	if (fd < 0)
+	{
+		#ifdef SystemLogMessage
+		StoreLogMsg("[FactoryConfig]main: open /dev/mtdblock10 NG");
+		#endif
+		free(ptr);
+		return 0;
+   	 }
+    	wrd=write(fd, &SysConfig, sizeof(struct SysConfigData));
+    	close(fd);
+    	if(wrd!=(sizeof(struct SysConfigData)))
+	{
+		#ifdef SystemLogMessage
+		StoreLogMsg("[FactoryConfig]main: write /dev/mtdblock10 NG");
+		#endif
+		free(ptr);
+		return 0;
+	}
+
+	free(ptr);
+	#ifdef SystemLogMessage
+	StoreLogMsg("[FactoryConfig]main: FactoryConfig OK");
+	#endif
+}
+

+ 57 - 0
EVSE/Projects/DM30/Apps/Makefile

@@ -0,0 +1,57 @@
+-include ../../../../Rules.make
+export PATH=/bin:/sbin:/usr/bin:$(SDK_PATH_TARGET)/usr/bin:$PATH
+
+#define library variable
+Lib_Module_RFID = -L../../../Modularization -lModule_RFID
+Lib_Module_Upgrade = "-L../../../Modularization" -lModule_Upgrade
+
+
+all: CopyFile apps
+apps: Module_InternalComm_Task Module_FactoryConfig_Task Module_EventLogging_Task Module_CSU_Task
+
+
+Module_InternalComm_Task:
+	@echo "===== Module_InternalComm_Task ==================================="
+	rm -f Module_InternalComm 
+	$(CC) "-I../../" "-include./Config.h" -O0 -g3 -Wall -c -fmessage-length=0 -o Module_InternalComm.o "./Module_InternalComm.c"
+	$(CC) "-I../../" "-include./Config.h" -O0 -g3 -Wall -c -fmessage-length=0 -o internalComm.o "./internalComm.c"
+	$(CC) -o Module_InternalComm Module_InternalComm.o internalComm.o
+	rm -f *.o
+	mv -f Module_InternalComm ../Images/root
+	@echo \ 
+	
+Module_FactoryConfig_Task:
+	@echo "===== Module_FactoryConfig_Task =================================="
+	rm -f FactoryConfig 
+	$(CC) "-I../../" -O0 -g3 -Wall -c -fmessage-length=0 -o FactoryConfig.o "./FactoryConfig.c"
+	$(CC) -o FactoryConfig FactoryConfig.o 
+	rm -f *.o
+	mv -f FactoryConfig ../Images/root
+	@echo \ 
+	
+Module_EventLogging_Task:
+	@echo "===== Module_EventLogging_Task ==================================="
+	rm -f Module_EventLogging 
+	$(CC) "-I../../" -O0 -g3 -Wall -c -fmessage-length=0 -o Module_EventLogging.o "./Module_EventLogging.c"
+	$(CC) -o Module_EventLogging Module_EventLogging.o 
+	rm -f *.o
+	mv -f Module_EventLogging ../Images/root
+	@echo \ 
+	
+Module_CSU_Task:
+	@echo "===== Module_CSU_Task ============================================"
+	rm -f main 
+	$(CC) -O0 -g3 -Wall -c -fmessage-length=0 -o timeout.o "./timeout.c"
+	$(CC) "-I../../../Modularization/" -O0 -g3 -Wall -c -fmessage-length=0 -o main.o "./main.c" 
+	$(CC) -o Module_CSU main.o timeout.o ${Lib_Module_RFID}
+	rm -f *.o
+	mv -f main ../Images/root		
+	@echo \ 
+	
+CopyFile: 
+	rm -rfv ../Images/root
+	mkdir -p ../Images/root
+
+
+
+	

BIN
EVSE/Projects/DM30/Apps/Module_EvComm


BIN
EVSE/Projects/DM30/Apps/Module_EvComm.o


BIN
EVSE/Projects/DM30/Apps/Module_EventLogging


+ 298 - 0
EVSE/Projects/DM30/Apps/Module_EventLogging.c

@@ -0,0 +1,298 @@
+#include 	<sys/time.h>
+#include 	<sys/timeb.h>
+#include    <sys/types.h>
+#include    <sys/stat.h>
+#include 	<sys/types.h>
+#include 	<sys/ioctl.h>
+#include 	<sys/socket.h>
+#include 	<sys/ipc.h>
+#include 	<sys/shm.h>
+#include 	<sys/shm.h>
+#include 	<sys/mman.h>
+#include 	<linux/wireless.h>
+#include 	<arpa/inet.h>
+#include 	<netinet/in.h>
+
+#include 	<unistd.h>
+#include 	<stdarg.h>
+#include    <stdio.h>      /*標準輸入輸出定義*/
+#include    <stdlib.h>     /*標準函數庫定義*/
+#include    <unistd.h>     /*Unix 標準函數定義*/
+#include    <fcntl.h>      /*檔控制定義*/
+#include    <termios.h>    /*PPSIX 終端控制定義*/
+#include    <errno.h>      /*錯誤號定義*/
+#include 	<errno.h>
+#include 	<string.h>
+#include	<time.h>
+#include	<ctype.h>
+#include 	<ifaddrs.h>
+#include	"../../define.h"
+
+#define Debug
+#define ARRAY_SIZE(A)		(sizeof(A) / sizeof(A[0]))
+#define PASS				1
+#define FAIL				-1
+
+struct SysConfigAndInfo			*ShmSysConfigAndInfo;
+struct StatusCodeData 			*ShmStatusCodeData;
+
+int StoreLogMsg(const char *fmt, ...);
+#define DEBUG_INFO(format, args...) StoreLogMsg("[%s:%d][%s][Info] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+#define DEBUG_WARN(format, args...) StoreLogMsg("[%s:%d][%s][Warn] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+#define DEBUG_ERROR(format, args...) StoreLogMsg("[%s:%d][%s][Error] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+
+int StoreLogMsg(const char *fmt, ...)
+{
+	char Buf[4096+256];
+	char buffer[4096];
+	time_t CurrentTime;
+	struct tm *tm;
+	va_list args;
+
+	va_start(args, fmt);
+	int rc = vsnprintf(buffer, sizeof(buffer), fmt, args);
+	va_end(args);
+
+	memset(Buf,0,sizeof(Buf));
+	CurrentTime = time(NULL);
+	tm=localtime(&CurrentTime);
+	sprintf(Buf,"echo \"%04d-%02d-%02d %02d:%02d:%02d - %s\" >> /Storage/SystemLog/[%04d.%02d]SystemLog",
+			tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec,
+			buffer,
+			tm->tm_year+1900,tm->tm_mon+1);
+	system(Buf);
+
+	return rc;
+}
+
+int DiffTimeb(struct timeb ST, struct timeb ET)
+{
+	//return milli-second
+	unsigned int StartTime,StopTime;
+
+	StartTime=(unsigned int)ST.time;
+	StopTime=(unsigned int)ET.time;
+	return (StopTime-StartTime)*1000+ET.millitm-ST.millitm;
+}
+
+//=================================
+// Common routine
+//=================================
+char* getTimeString(void)
+{
+	char *result=malloc(21);
+	time_t timep;
+	struct tm *p;
+	time(&timep);
+	p=gmtime(&timep);
+
+	sprintf(result, "[%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);
+
+	return result;
+}
+
+//==========================================
+// Init all share memory
+//==========================================
+int InitShareMemory()
+{
+	int result = PASS;
+	int MeterSMId;
+
+	//creat ShmSysConfigAndInfo
+	if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo),  0777)) < 0)
+    {
+		#ifdef SystemLogMessage
+		DEBUG_ERROR("shmget ShmSysConfigAndInfo NG\n");
+		#endif
+		result = FAIL;
+	}
+    else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+    {
+    	#ifdef SystemLogMessage
+    	DEBUG_ERROR("shmat ShmSysConfigAndInfo NG\n");
+		#endif
+    	result = FAIL;
+   	 }
+    else
+    {}
+
+   	 //creat ShmStatusCodeData
+   	 if ((MeterSMId = shmget(ShmStatusCodeKey, sizeof(struct StatusCodeData),  0777)) < 0)
+    {
+		#ifdef SystemLogMessage
+   		DEBUG_ERROR("shmget ShmStatusCodeData NG\n");
+		#endif
+   		result = FAIL;
+	}
+    else if ((ShmStatusCodeData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+    {
+    	#ifdef SystemLogMessage
+    	DEBUG_ERROR("shmat ShmStatusCodeData NG\n");
+		#endif
+    	result = FAIL;
+   	}
+    else
+    {}
+
+    return result;
+}
+
+//================================================
+// Main process
+//================================================
+void AddFaultCodeToBuf(unsigned char *Code)
+{
+	if(ShmSysConfigAndInfo->SysWarningInfo.WarningCount < 10)
+	{
+		memcpy(&ShmSysConfigAndInfo->SysWarningInfo.WarningCode[ShmSysConfigAndInfo->SysWarningInfo.WarningCount][0], Code, 7);
+		ShmSysConfigAndInfo->SysWarningInfo.WarningCount++;
+	}
+}
+
+void RemoveFaultCodeToBuf(unsigned char *Code)
+{
+	unsigned char find = 0x00;
+	char _code[7];
+	sprintf(_code,"%s", Code);
+
+	for(unsigned char i = 0; i < ShmSysConfigAndInfo->SysWarningInfo.WarningCount; i++)
+	{
+		if (find == 0x00)
+		{
+			if(memcmp(&ShmSysConfigAndInfo->SysWarningInfo.WarningCode[i][0], _code, 7) != 0)
+			{
+				find = 0x01;
+			}
+		}
+		else
+		{
+			if(i == ShmSysConfigAndInfo->SysWarningInfo.WarningCount - 1)
+			{
+				memcpy(&ShmSysConfigAndInfo->SysWarningInfo.WarningCode[i][0], "", 7);
+			}
+			else
+			{
+				memcpy(&ShmSysConfigAndInfo->SysWarningInfo.WarningCode[i][0],
+						&ShmSysConfigAndInfo->SysWarningInfo.WarningCode[i + 1][0], 7);
+			}
+		}
+	}
+
+	ShmSysConfigAndInfo->SysWarningInfo.WarningCount--;
+}
+
+int main(void)
+{
+	int ByteCount,BitCount;
+	unsigned char tmp, EventCodeTmp[7];
+
+	if(InitShareMemory() == FAIL)
+	{
+		#ifdef SystemLogMessage
+		DEBUG_ERROR("InitShareMemory NG\n");
+		#endif
+		if(ShmStatusCodeData!=NULL)
+		{
+			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FailToCreateShareMemory=1;
+		}
+		sleep(5);
+		return 0;
+	}
+
+	for(;;)
+	{
+		//check Fault Status
+		for(ByteCount=0;ByteCount<4;ByteCount++)
+		{
+			if(ShmStatusCodeData->FaultCode.FaultEvents.FaultVal[ByteCount] != ShmStatusCodeData->FaultCode.PreviousFaultVal[ByteCount])
+			{
+				tmp=ShmStatusCodeData->FaultCode.FaultEvents.FaultVal[ByteCount]; //prevent be modified during following process
+				for(BitCount=0;BitCount<8;BitCount++)
+				{
+					if(((tmp>>BitCount)&0x01) != ((ShmStatusCodeData->FaultCode.PreviousFaultVal[ByteCount]>>BitCount)&0x01))
+					{
+						memset(EventCodeTmp,0,sizeof(EventCodeTmp));
+						memcpy(EventCodeTmp,FaultStatusCode[ByteCount*8+BitCount],sizeof(EventCodeTmp)-1);
+						if(((tmp>>BitCount)&0x01)==0)//Recovered
+						{
+							//EventCodeTmp[0]=1;
+							DEBUG_INFO("Recovery Fault Code = %s\n", EventCodeTmp);
+							ShmStatusCodeData->FaultCode.PreviousFaultVal[ByteCount] &= ~(1<<BitCount);
+							RemoveFaultCodeToBuf(EventCodeTmp);
+						}
+						else
+						{
+							DEBUG_INFO("Fault Code = %s\n", EventCodeTmp);
+							ShmStatusCodeData->FaultCode.PreviousFaultVal[ByteCount] |= (1<<BitCount);
+							AddFaultCodeToBuf(EventCodeTmp);
+						}
+					}
+				}
+			}
+		}
+
+		//check Alarm Status
+		for(ByteCount=0;ByteCount<8;ByteCount++)
+		{
+			if(ShmStatusCodeData->AlarmCode.AlarmEvents.AlarmVal[ByteCount] != ShmStatusCodeData->AlarmCode.PreviousAlarmVal[ByteCount])
+			{
+				tmp=ShmStatusCodeData->AlarmCode.AlarmEvents.AlarmVal[ByteCount]; //prevent be modified during following process
+				for(BitCount=0;BitCount<8;BitCount++)
+				{
+					if(((tmp>>BitCount)&0x01) != ((ShmStatusCodeData->AlarmCode.PreviousAlarmVal[ByteCount]>>BitCount)&0x01))
+					{
+						memset(EventCodeTmp,0,sizeof(EventCodeTmp));
+						memcpy(EventCodeTmp,AlarmStatusCode[ByteCount*8+BitCount],sizeof(EventCodeTmp)-1);
+						if(((tmp>>BitCount)&0x01)==0)//Recovered
+						{
+							//EventCodeTmp[0]=1;
+							DEBUG_INFO("Recovery Alarm Code = %s\n", EventCodeTmp);
+							ShmStatusCodeData->AlarmCode.PreviousAlarmVal[ByteCount] &= ~(1<<BitCount);
+							RemoveFaultCodeToBuf(EventCodeTmp);
+						}
+						else
+						{
+							DEBUG_INFO("Alarm Code = %s\n", EventCodeTmp);
+							ShmStatusCodeData->AlarmCode.PreviousAlarmVal[ByteCount] |= (1<<BitCount);
+							AddFaultCodeToBuf(EventCodeTmp);
+						}
+					}
+				}
+			}
+		}
+
+		//check Info Status
+		for(ByteCount=0;ByteCount<8;ByteCount++)
+		{
+			if(ShmStatusCodeData->InfoCode.InfoEvents.InfoVal[ByteCount] != ShmStatusCodeData->InfoCode.PreviousInfoVal[ByteCount])
+			{
+				tmp=ShmStatusCodeData->InfoCode.InfoEvents.InfoVal[ByteCount]; //prevent be modified during following process
+				for(BitCount=0;BitCount<8;BitCount++)
+				{
+					if(((tmp>>BitCount)&0x01) != ((ShmStatusCodeData->InfoCode.PreviousInfoVal[ByteCount]>>BitCount)&0x01))
+					{
+						memset(EventCodeTmp,0,sizeof(EventCodeTmp));
+						memcpy(EventCodeTmp,InfoStatusCode[ByteCount*8+BitCount],sizeof(EventCodeTmp)-1);
+						if(((tmp>>BitCount)&0x01)==0)//Recovered
+						{
+							//EventCodeTmp[0]=1;
+							DEBUG_INFO("Recovery Info Code = %s\n", EventCodeTmp);
+							ShmStatusCodeData->InfoCode.PreviousInfoVal[ByteCount] &= ~(1<<BitCount);
+							RemoveFaultCodeToBuf(EventCodeTmp);
+						}
+						else
+						{
+							DEBUG_INFO("Info Code = %s\n", EventCodeTmp);
+							ShmStatusCodeData->InfoCode.PreviousInfoVal[ByteCount] |= (1<<BitCount);
+							AddFaultCodeToBuf(EventCodeTmp);
+						}
+					}
+				}
+			}
+		}
+		usleep(500000);
+	}
+
+	return FAIL;
+}

BIN
EVSE/Projects/DM30/Apps/Module_EventLogging.o


BIN
EVSE/Projects/DM30/Apps/Module_InternalComm


+ 1312 - 0
EVSE/Projects/DM30/Apps/Module_InternalComm.c

@@ -0,0 +1,1312 @@
+#include 	<sys/time.h>
+#include 	<sys/timeb.h>
+#include    <sys/types.h>
+#include    <sys/stat.h>
+#include 	<sys/types.h>
+#include 	<sys/ioctl.h>
+#include 	<sys/socket.h>
+#include 	<sys/ipc.h>
+#include 	<sys/shm.h>
+#include 	<sys/shm.h>
+#include 	<sys/mman.h>
+#include 	<linux/wireless.h>
+#include 	<arpa/inet.h>
+#include 	<netinet/in.h>
+
+#include 	<unistd.h>
+#include 	<stdarg.h>
+#include    <stdio.h>      /*標準輸入輸出定義*/
+#include    <stdlib.h>     /*標準函數庫定義*/
+#include    <unistd.h>     /*Unix 標準函數定義*/
+#include    <fcntl.h>      /*檔控制定義*/
+#include    <termios.h>    /*PPSIX 終端控制定義*/
+#include    <errno.h>      /*錯誤號定義*/
+#include 	<errno.h>
+#include 	<string.h>
+#include	<time.h>
+#include	<ctype.h>
+#include 	<ifaddrs.h>
+#include 	<math.h>
+#include	"define.h"
+#include	"internalComm.h"
+#include 	<stdbool.h>
+
+#define Debug
+#define ARRAY_SIZE(A)		(sizeof(A) / sizeof(A[0]))
+#define PASS				1
+#define FAIL				-1
+#define YES					1
+#define NO					0
+
+struct SysConfigAndInfo			*ShmSysConfigAndInfo;
+struct StatusCodeData 			*ShmStatusCodeData;
+struct FanModuleData			*ShmFanModuleData;
+struct RelayModuleData			*ShmRelayModuleData;
+struct CHAdeMOData				*ShmCHAdeMOData;
+struct CcsData					*ShmCcsData;
+
+#define VIN_MAX_VOLTAGE		250	// 大於該值 : OVP
+#define VIN_MIN_VOLTAGE		170	// 小於該值 : UVP
+#define VIN_DROP_VOLTAGE	150	// 小於該值 : ac drop
+
+#define VOUT_MAX_VOLTAGE	750
+#define VOUT_MIN_VOLTAGE	150
+#define IOUT_MAX_CURRENT	50
+
+#define MAX_FAN_SPEED		6000
+#define MIN_FAN_SPEED		300
+
+//Warning : 150, PreWarning : 500
+#define GFD_VALUE			500
+
+// 最小切換 Relay 電壓
+#define SELF_TO_CHANGE_RELAY_STATUS			600
+// 透過電壓確認 Relay 是否搭上的依據電壓
+#define CHECK_RELAY_STATUS					300
+#define CHECK_RELAY_STATUS_GAP				100
+// 安全在停止充電程序中斷開 Relay 的電流
+#define SEFETY_SWITCH_RELAY_CUR				20
+// 確認 Relay Welding 電壓
+#define RELAY_WELDING_DET					300
+
+byte gunCount = CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY;
+// 槍資訊
+struct ChargingInfoData *_chargingData[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
+byte gfdChkFailCount[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
+
+bool FindChargingInfoData(byte target, struct ChargingInfoData **chargingData);
+
+int Uart5Fd;
+char *relayRs485PortName = "/dev/ttyS5";
+unsigned short fanSpeedSmoothValue = 100;
+
+struct timeval _priority_time;
+
+Ver ver;
+PresentInputVoltage inputVoltage;
+PresentOutputVoltage outputVoltage;
+FanSpeed fanSpeed;
+Temperature temperature;
+AuxPower auxPower;
+Gfd gfd_adc;
+Gfd_config gfd_config;
+Gpio_in gpio_in;
+Gpio_out gpio_out;
+Relay outputRelay;
+Relay regRelay;
+
+int StoreLogMsg(const char *fmt, ...);
+#define DEBUG_INFO(format, args...) StoreLogMsg("[%s:%d][%s][Info] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+#define DEBUG_WARN(format, args...) StoreLogMsg("[%s:%d][%s][Warn] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+#define DEBUG_ERROR(format, args...) StoreLogMsg("[%s:%d][%s][Error] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+
+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 StoreLogMsg(const char *fmt, ...)
+{
+	char Buf[4096+256];
+	char buffer[4096];
+	time_t CurrentTime;
+	struct tm *tm;
+	va_list args;
+
+	va_start(args, fmt);
+	int rc = vsnprintf(buffer, sizeof(buffer), fmt, args);
+	va_end(args);
+
+	memset(Buf,0,sizeof(Buf));
+	CurrentTime = time(NULL);
+	tm=localtime(&CurrentTime);
+	sprintf(Buf,"echo \"%04d-%02d-%02d %02d:%02d:%02d - %s\" >> /Storage/SystemLog/[%04d.%02d]SystemLog",
+			tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec,
+			buffer,
+			tm->tm_year+1900,tm->tm_mon+1);
+	system(Buf);
+
+	return rc;
+}
+
+int DiffTimeb(struct timeb ST, struct timeb ET)
+{
+	//return milli-second
+	unsigned int StartTime,StopTime;
+
+	StartTime=(unsigned int)ST.time;
+	StopTime=(unsigned int)ET.time;
+	return (StopTime-StartTime)*1000+ET.millitm-ST.millitm;
+}
+
+unsigned short MaxValue(unsigned short value1, unsigned short value2)
+{
+	return value1 >= value2 ? value1 : value2;
+}
+
+//==========================================
+// Communication Function
+//==========================================
+void GetFwAndHwVersion_Aux()
+{
+	if (Query_FW_Ver(Uart5Fd, Addr.Aux, &ver) == PASS)
+	{
+		// SystemInfo
+		strcpy((char *) ShmSysConfigAndInfo->SysInfo.AuxPwrFwRev, ver.Version_FW);
+		printf("s1 = %s \n", ver.Version_FW);
+	}
+
+	if (Query_HW_Ver(Uart5Fd, Addr.Aux, &ver) == PASS)
+	{
+		// SystemInfo
+		strcpy((char *) ShmSysConfigAndInfo->SysInfo.AuxPwrHwRev, ver.Version_HW);
+		printf("s2 = %s \n", ver.Version_HW);
+	}
+}
+
+void GetFwAndHwVersion_Fan()
+{
+	if(Query_FW_Ver(Uart5Fd, Addr.Fan, &ver) == PASS)
+	{
+		// FanModuleData
+		strcpy((char *) ShmFanModuleData->version, ver.Version_FW);
+		// SystemInfo
+		strcpy((char *) ShmSysConfigAndInfo->SysInfo.FanModuleFwRev, ver.Version_FW);
+		printf("GetFwAndHwVersion_Fan s1 = %s \n", ver.Version_FW);
+	}
+
+	if (Query_HW_Ver(Uart5Fd, Addr.Fan, &ver) == PASS)
+	{
+		// SystemInfo
+		strcpy((char *) ShmSysConfigAndInfo->SysInfo.FanModuleHwRev, ver.Version_FW);
+		printf("GetFwAndHwVersion_Fan s2 = %s \n", ver.Version_HW);
+	}
+}
+
+void GetFwAndHwVersion_Relay()
+{
+	if (Query_FW_Ver(Uart5Fd, Addr.Relay, &ver) == PASS)
+	{
+		// FanModuleData
+		strcpy((char *) ShmRelayModuleData->version, ver.Version_FW);
+		// SystemInfo
+		strcpy((char *) ShmSysConfigAndInfo->SysInfo.RelayModuleFwRev, ver.Version_FW);
+		printf("GetFwAndHwVersion_Relay s1 = %s \n", ver.Version_FW);
+	}
+
+	if (Query_HW_Ver(Uart5Fd, Addr.Relay, &ver) == PASS)
+	{
+		// SystemInfo
+		strcpy((char *) ShmSysConfigAndInfo->SysInfo.RelayModuleHwRev, ver.Version_FW);
+		printf("GetFwAndHwVersion_Relay s2 = %s \n", ver.Version_HW);
+	}
+}
+
+void GetTemperature_Aux()
+{
+	memset(temperature.temperature, 0, ARRAY_SIZE(temperature.temperature));
+	if (Query_Temperature(Uart5Fd, Addr.Aux, &temperature) == PASS)
+	{
+		// aux temp
+		// UI 實際顯示溫度轉換
+		//char s[4];
+		//sprintf(s,"%d",(-60 + temperature[2].temperature[4])),
+		//printf("s = %s \n",s);
+
+		printf("Aux temp = %d,%d,%d,%d,%d,%d,%d,%d \n",
+				(-60 + temperature.temperature[0]),
+				(-60 + temperature.temperature[1]),
+				(-60 + temperature.temperature[2]),
+				(-60 + temperature.temperature[3]),
+				(-60 + temperature.temperature[4]),
+				(-60 + temperature.temperature[5]),
+				(-60 + temperature.temperature[6]),
+				(-60 + temperature.temperature[7]));
+	}
+}
+
+void GetTemperature_Relay()
+{
+	memset(temperature.temperature, 0, ARRAY_SIZE(temperature.temperature));
+	if (Query_Temperature(Uart5Fd, Addr.Relay, &temperature) == PASS)
+	{
+		// relay temp
+		printf("Relay temp = %d,%d,%d,%d,%d,%d,%d,%d \n",
+				(-60 + temperature.temperature[0]),
+				(-60 + temperature.temperature[1]),
+				(-60 + temperature.temperature[2]),
+				(-60 + temperature.temperature[3]),
+				(-60 + temperature.temperature[4]),
+				(-60 + temperature.temperature[5]),
+				(-60 + temperature.temperature[6]),
+				(-60 + temperature.temperature[7]));
+	}
+}
+
+// AC 三相輸入電壓
+void GetPresentInputVol()
+{
+	if (Query_Present_InputVoltage(Uart5Fd, Addr.Relay, &inputVoltage) == PASS)
+	{
+		// resolution : 0.1
+		//printf("InputVoltageR = %f \n", inputVoltage.L1N_L12);
+		//printf("InputVoltageS = %f \n", inputVoltage.L2N_L23);
+		//printf("InputVoltageT = %f \n", inputVoltage.L3N_L31);
+
+		ShmRelayModuleData->InputL1Volt = inputVoltage.L1N_L12;
+		ShmRelayModuleData->InputL2Volt = inputVoltage.L2N_L23;
+		ShmRelayModuleData->InputL3Volt = inputVoltage.L3N_L31;
+
+		//********************************************************************************************************//
+		// VIN < 170
+		if (inputVoltage.L1N_L12 < VIN_MIN_VOLTAGE)
+		{
+			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP = 0x01;
+		}
+		if (inputVoltage.L2N_L23 < VIN_MIN_VOLTAGE)
+		{
+			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP = 0x01;
+		}
+		if (inputVoltage.L3N_L31 < VIN_MIN_VOLTAGE)
+		{
+			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP = 0x01;
+		}
+
+		//********************************************************************************************************//
+		// VIN > 250
+		if (inputVoltage.L1N_L12 > VIN_MAX_VOLTAGE)
+		{
+			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP = 0x01;
+		}
+		if (inputVoltage.L2N_L23 > VIN_MAX_VOLTAGE)
+		{
+			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP = 0x01;
+		}
+		if (inputVoltage.L3N_L31 > VIN_MAX_VOLTAGE)
+		{
+			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP = 0x01;
+		}
+		//********************************************************************************************************//
+		// VIN < 150
+		if (inputVoltage.L1N_L12 < VIN_DROP_VOLTAGE)
+		{
+			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputDrop = 0x01;
+		}
+		if (inputVoltage.L2N_L23 < VIN_DROP_VOLTAGE)
+		{
+			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputDrop = 0x01;
+		}
+		if (inputVoltage.L3N_L31 < VIN_DROP_VOLTAGE)
+		{
+			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputDrop = 0x01;
+		}
+
+		//********************************************************************************************************//
+		// 150 <= VIN < 160
+//		if (inputVoltage.L1N_L12 >= VIN_MIN_VOLTAGE && inputVoltage.L1N_L12 <= VIN_LOW_VOLTAGE)
+//		{
+//			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputUVP = 0x00;
+//			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputOVP = 0x00;
+//			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL1InputDrop = 0x00;
+//		}
+//		if (inputVoltage.L2N_L23 >= VIN_MIN_VOLTAGE && inputVoltage.L2N_L23 <= VIN_LOW_VOLTAGE)
+//		{
+//			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputUVP = 0x00;
+//			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputOVP = 0x00;
+//			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL2InputDrop = 0x00;
+//		}
+//		if (inputVoltage.L3N_L31 >= VIN_MIN_VOLTAGE && inputVoltage.L3N_L31 <= VIN_LOW_VOLTAGE)
+//		{
+//			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputUVP = 0x00;
+//			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputOVP = 0x00;
+//			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemL3InputDrop = 0x00;
+//		}
+	}
+}
+
+// 左右槍的 Relay 前後的輸出電壓
+void GetPersentOutputVol()
+{
+	if (Query_Present_OutputVoltage(Uart5Fd, Addr.Relay, &outputVoltage) == PASS)
+	{
+//		printf("Conn1 fuse 1 = %f \n", outputVoltage.behindFuse_Voltage_C1);
+//		printf("Conn1 relay 1 = %f \n", outputVoltage.behindRelay_Voltage_C1);
+//		printf("Conn2 fuse 2 = %f \n", outputVoltage.behindFuse_Voltage_C2);
+//		printf("Conn2 relay 2 = %f \n", outputVoltage.behindRelay_Voltage_C2);
+
+		//printf("outputVoltage.behindFuse_Voltage_C1 = %f \n", outputVoltage.behindFuse_Voltage_C1);
+		//printf("outputVoltage.behindFuse_Voltage_C2 = %f \n", outputVoltage.behindFuse_Voltage_C2);
+
+		ShmRelayModuleData->Gun1FuseOutputVolt = outputVoltage.behindFuse_Voltage_C1;
+		ShmRelayModuleData->Gun1RelayOutputVolt = outputVoltage.behindRelay_Voltage_C1;
+		ShmRelayModuleData->Gun2FuseOutputVolt = outputVoltage.behindFuse_Voltage_C2;
+		ShmRelayModuleData->Gun2RelayOutputVolt = outputVoltage.behindRelay_Voltage_C2;
+
+		for (int index = 0; index < gunCount; index++)
+		{
+			if (index == 0)
+			{
+				if (_chargingData[index]->Evboard_id == 0x01)
+				{
+					_chargingData[index]->FuseChargingVoltage = ShmRelayModuleData->Gun1FuseOutputVolt;
+					_chargingData[index]->FireChargingVoltage = ShmRelayModuleData->Gun1RelayOutputVolt;
+				}
+				else if (_chargingData[index]->Evboard_id == 0x02)
+				{
+					_chargingData[index]->FuseChargingVoltage = ShmRelayModuleData->Gun2FuseOutputVolt;
+					_chargingData[index]->FireChargingVoltage = ShmRelayModuleData->Gun2RelayOutputVolt;
+				}
+			}
+			else if (index == 1)
+			{
+				_chargingData[index]->FuseChargingVoltage = ShmRelayModuleData->Gun2FuseOutputVolt;
+				_chargingData[index]->FireChargingVoltage = ShmRelayModuleData->Gun2RelayOutputVolt;
+			}
+
+			unsigned short Ovp = 0;
+			unsigned short Ocp = 0;
+			//Ovp = MIN [VOUT_MAX_VOLTAGE, EV_BATTERY_VOLTAGE] 	// 最大輸出電壓與電池電壓最大值
+			//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);
+				if (_chargingData[index]->PresentChargingVoltage >= Ovp)
+				{
+					ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemChademoOutputOVP = 0x01;
+				}
+				if (_chargingData[index]->PresentChargingCurrent >= Ocp)
+				{
+					ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemChademoOutputOCP = 0x01;
+				}
+			}
+			else if (_chargingData[index]->Type == _Type_CCS)
+			{
+
+			}
+		}
+	}
+}
+
+// 風扇速度
+void GetFanSpeed()
+{
+	//printf("Get fan board speed \n");
+	if (Query_Fan_Speed(Uart5Fd, Addr.Fan, &fanSpeed) == PASS)
+	{
+		ShmFanModuleData->PresentFan1Speed = fanSpeed.speed[0];
+		ShmFanModuleData->PresentFan2Speed = fanSpeed.speed[1];
+		ShmFanModuleData->PresentFan3Speed = fanSpeed.speed[2];
+		ShmFanModuleData->PresentFan4Speed = fanSpeed.speed[3];
+		printf("SystemFanRotaSpeed_1 = %d \n", fanSpeed.speed[0]);
+		printf("SystemFanRotaSpeed_2 = %d \n", fanSpeed.speed[1]);
+		printf("SystemFanRotaSpeed_3 = %d \n", fanSpeed.speed[2]);
+		printf("SystemFanRotaSpeed_4 = %d \n", fanSpeed.speed[3]);
+		// Config_Fan_Speed(Uart5Fd, Addr.Fan, &fanSpeed[0]);
+		//SysInfoData (SystemFanRotaSpeed)
+	}
+}
+
+// 讀取 Relay 狀態
+void GetRelayOutputStatus()
+{
+	if (Query_Relay_Output(Uart5Fd, Addr.Relay, &regRelay) == PASS)
+	{
+		regRelay.relay_event.bits.AC_Contactor = ShmSysConfigAndInfo->SysInfo.AcContactorStatus;
+	}
+}
+
+// 確認 K1 K2 relay 的狀態
+void CheckK1K2RelayOutput(byte index)
+{
+	if (index == 0)
+	{
+		if (_chargingData[index]->Evboard_id == 0x01)
+		{
+			if (regRelay.relay_event.bits.Gun1_N == YES && regRelay.relay_event.bits.Gun1_P == YES)
+				_chargingData[index]->RelayK1K2Status = YES;
+			else
+				_chargingData[index]->RelayK1K2Status = NO;
+
+			if(_chargingData[index]->Type == _Type_CCS)
+			{
+				if (regRelay.relay_event.bits.Gun1_N == YES	&& regRelay.relay_event.bits.CCS_Precharge == YES)
+					_chargingData[index]->RelayKPK2Status = YES;
+				else
+					_chargingData[index]->RelayKPK2Status = NO;
+			}
+		}
+		else if (_chargingData[index]->Evboard_id == 0x02)
+		{
+			if (regRelay.relay_event.bits.Gun2_N == YES && regRelay.relay_event.bits.Gun2_P == YES)
+				_chargingData[index]->RelayK1K2Status = YES;
+			else
+				_chargingData[index]->RelayK1K2Status = NO;
+
+			if(_chargingData[index]->Type == _Type_CCS)
+			{
+				if (regRelay.relay_event.bits.Gun2_N == YES	&& regRelay.relay_event.bits.CCS_Precharge == YES)
+					_chargingData[index]->RelayKPK2Status = YES;
+				else
+					_chargingData[index]->RelayKPK2Status = NO;
+			}
+
+		}
+	}
+	else if (index == 1)
+	{
+		if (regRelay.relay_event.bits.Gun2_N == YES && regRelay.relay_event.bits.Gun2_P == YES)
+			_chargingData[index]->RelayK1K2Status = YES;
+		else
+			_chargingData[index]->RelayK1K2Status = NO;
+
+		if(_chargingData[index]->Type == _Type_CCS)
+		{
+			if (regRelay.relay_event.bits.Gun2_N == YES && regRelay.relay_event.bits.CCS_Precharge == YES)
+				_chargingData[index]->RelayKPK2Status = YES;
+			else
+				_chargingData[index]->RelayKPK2Status = NO;
+		}
+	}
+
+	if (regRelay.relay_event.bits.Gun1_Parallel_N == YES && regRelay.relay_event.bits.Gun1_Parallel_P == YES)
+		ShmSysConfigAndInfo->SysInfo.BridgeRelayStatus = YES;
+	else
+		ShmSysConfigAndInfo->SysInfo.BridgeRelayStatus = NO;
+}
+
+void GetGfdAdc()
+{
+	// define : 每 0.2 ~ 1 秒一次
+	// occur : <= 75k 歐姆 @ 150 - 750 Vdc
+	// warning : >= 100 歐姆 && <= 500 歐姆 @ 150-750 Vdc
+	if (Query_Gfd_Adc(Uart5Fd, Addr.Relay, &gfd_adc) == PASS)
+	{
+		for (int i = 0; i < gunCount; i++)
+		{
+			if (i == 0)
+			{
+				_chargingData[i]->GroundFaultStatus = gfd_adc.result_conn1;
+				if (_chargingData[i]->GroundFaultStatus == GFD_FAIL)
+				{
+					DEBUG_ERROR("GFD Fail. index = %d, R = %d, Vol = %d \n",
+							i, gfd_adc.Resister_conn1, gfd_adc.voltage_conn1);
+				}
+			}
+			else if (i == 1)
+			{
+				_chargingData[i]->GroundFaultStatus = gfd_adc.result_conn2;
+				if (_chargingData[i]->GroundFaultStatus == GFD_FAIL)
+				{
+					DEBUG_ERROR("GFD Fail. index = %d, R = %d, Vol = %d \n",
+							i, gfd_adc.Resister_conn2, gfd_adc.voltage_conn2);
+				}
+			}
+		}
+
+		//if (gfd_adc.result_conn1 != 0)
+		{
+			printf("******************Resister_conn1 = %d, voltage_conn1 = %d, result_conn1 = %d, step = %d \n",
+				gfd_adc.Resister_conn1,
+				gfd_adc.voltage_conn1,
+				gfd_adc.result_conn1,
+				gfd_adc.rb_step_1);
+		}
+	}
+}
+
+void GetGpioInput()
+{
+	if (Query_Gpio_Input(Uart5Fd, Addr.Aux, &gpio_in) == PASS)
+	{
+		// AC Contactor Status
+		//ShmSysConfigAndInfo->SysInfo.AcContactorStatus = gpio_in.AC_Connector;
+
+		if (gpio_in.AC_MainBreaker == 1)
+		{
+			// AC Main Breaker ON
+			printf("RB AC Main Breaker. \n");
+		}
+
+		if (gpio_in.SPD == 1)
+		{
+			// SPD (雷擊保護) ON
+			printf("RB SPD. \n");
+		}
+
+		if (gpio_in.Door_Open == 1)
+		{
+			// Door Open
+			printf("RB Door Open. \n");
+		}
+
+		if (gpio_in.GFD[0] == 1)
+		{
+			// GFD_1 Trigger
+		}
+
+		if (gpio_in.GFD[1] == 1)
+		{
+			// GFD_2 Trigger
+		}
+
+		if (gpio_in.AC_Drop == 1)
+		{
+			// AC Drop
+			printf("RB AC Drop. \n");
+		}
+
+		if (gpio_in.Emergency_IO == 1)
+		{
+			// Emergency IO ON
+			printf("RB Emergency IO ON. \n");
+		}
+
+		if (gpio_in.Button_Emergency_Press == 1)
+		{
+			// Emergency button Press
+		}
+
+		if (gpio_in.Button_On_Press == 1)
+		{
+			// On button Press
+		}
+
+		if (gpio_in.Button_Off_Press == 1)
+		{
+			// Off button Press
+		}
+
+		if (gpio_in.Key_1_Press == 1)
+		{
+			// key 1 press
+		}
+
+		if (gpio_in.Key_2_Press == 1)
+		{
+			// key 2 press
+		}
+
+		if (gpio_in.Key_3_Press == 1)
+		{
+			// key 3 press
+		}
+
+		if (gpio_in.Key_4_Press == 1)
+		{
+			// key 4 press
+		}
+	}
+}
+
+// 5V 12V 24V 48V
+void GetAuxPower()
+{
+	if (Query_Aux_PowerVoltage(Uart5Fd, Addr.Fan, &auxPower) == PASS)
+	{
+		ShmSysConfigAndInfo->SysInfo.AuxPower48V = auxPower.voltage[0];
+		ShmSysConfigAndInfo->SysInfo.AuxPower24V = auxPower.voltage[1];
+		//ShmSysConfigAndInfo->SysInfo.AuxPower12V = auxPower.voltage[4];
+		//ShmSysConfigAndInfo->SysInfo.AuxPower5V = auxPower.voltage[6];
+		// aux power voltage
+		//printf("aux1 = %x, \n", auxPower.voltage[0]);
+		//printf("aux2 = %x, \n", auxPower.voltage[1]);
+	}
+}
+
+void SetFanModuleSpeed()
+{
+	// 調整風扇速度要漸進式 : 500 rpm/p
+	if (ShmFanModuleData->PresentFan1Speed != ShmFanModuleData->SetFan1Speed ||
+			ShmFanModuleData->PresentFan2Speed != ShmFanModuleData->SetFan2Speed ||
+			ShmFanModuleData->PresentFan3Speed != ShmFanModuleData->SetFan3Speed ||
+			ShmFanModuleData->PresentFan4Speed != ShmFanModuleData->SetFan4Speed)
+	{
+		FanSpeed _fanSpeed;
+
+		unsigned short speed = ShmFanModuleData->PresentFan1Speed + fanSpeedSmoothValue;
+		if (speed >= ShmFanModuleData->SetFan1Speed)
+			speed = ShmFanModuleData->SetFan1Speed;
+		_fanSpeed.speed[0] = speed & 0xff;
+		_fanSpeed.speed[1] = (speed >> 8) & 0xff;
+
+		speed = ShmFanModuleData->PresentFan2Speed + fanSpeedSmoothValue;
+		if (speed >= ShmFanModuleData->SetFan2Speed)
+			speed = ShmFanModuleData->SetFan2Speed;
+		_fanSpeed.speed[2] = speed & 0xff;
+		_fanSpeed.speed[3] = (speed >> 8) & 0xff;
+
+		speed = ShmFanModuleData->PresentFan3Speed + fanSpeedSmoothValue;
+		if (speed >= ShmFanModuleData->SetFan3Speed)
+			speed = ShmFanModuleData->SetFan3Speed;
+		_fanSpeed.speed[4] = speed & 0xff;
+		_fanSpeed.speed[5] = (speed >> 8) & 0xff;
+
+		speed = ShmFanModuleData->PresentFan4Speed + fanSpeedSmoothValue;
+		if (speed >= ShmFanModuleData->SetFan4Speed)
+			speed = ShmFanModuleData->SetFan4Speed;
+		_fanSpeed.speed[6] = speed & 0xff;
+		_fanSpeed.speed[7] = (speed >> 8) & 0xff;
+
+		if (Config_Fan_Speed(Uart5Fd, Addr.Fan, &_fanSpeed) == PASS)
+		{
+			printf("successfully Fan\n");
+		}
+		else
+			printf("fail Fan\n");
+	}
+}
+
+void SetRelayModuleFanSpeed()
+{
+	// 調整風扇速度要漸進式 : 100 rpm/p
+	if (ShmFanModuleData->PresentFan1Speed != ShmFanModuleData->SetFan1Speed)
+	{
+		FanSpeed _fanSpeed;
+		unsigned short speed = 0;
+
+		if (ShmFanModuleData->SetFan1Speed > ShmFanModuleData->PresentFan1Speed)
+		{
+			speed = ShmFanModuleData->PresentFan1Speed + fanSpeedSmoothValue;
+			if (speed >= ShmFanModuleData->SetFan1Speed)
+				speed = ShmFanModuleData->SetFan1Speed;
+		}
+		else
+		{
+			speed = ShmFanModuleData->PresentFan1Speed - fanSpeedSmoothValue;
+			if (speed <= 0)
+				speed = ShmFanModuleData->SetFan1Speed;
+		}
+
+		_fanSpeed.speed[0] = speed & 0xff;
+		_fanSpeed.speed[1] = (speed >> 8) & 0xff;
+		ShmFanModuleData->PresentFan1Speed = speed;
+
+		Config_Fan_Speed(Uart5Fd, Addr.Relay, &_fanSpeed);
+	}
+}
+
+void GetRelayModuleFanSpeed()
+{
+	printf("Get fan board speed \n");
+	if (Query_Fan_Speed(Uart5Fd, Addr.Relay, &fanSpeed) == PASS)
+	{
+		ShmFanModuleData->PresentFan1Speed = fanSpeed.speed[0] + (fanSpeed.speed[1] >> 8);
+		printf("SystemFanRotaSpeed_1 = %d \n", fanSpeed.speed[0]);
+	}
+}
+
+//==========================================
+// Common Function
+//==========================================
+void SetK1K2RelayStatus(byte index)
+{
+	if (_chargingData[index]->SystemStatus < S_PREPARING_FOR_EVSE)
+	{
+		if (_chargingData[index]->Evboard_id == 0x01)
+		{
+			if(regRelay.relay_event.bits.Gun1_P == YES)
+				outputRelay.relay_event.bits.Gun1_P = NO;
+			else if (regRelay.relay_event.bits.Gun1_N == YES)
+				outputRelay.relay_event.bits.Gun1_N = NO;
+
+			if (_chargingData[index]->Type == _Type_CCS)
+			{
+				if(regRelay.relay_event.bits.CCS_Precharge == YES)
+					outputRelay.relay_event.bits.CCS_Precharge = NO;
+			}
+		}
+		else if (_chargingData[index]->Evboard_id == 0x02)
+		{
+			if(regRelay.relay_event.bits.Gun2_P == YES)
+				outputRelay.relay_event.bits.Gun2_P = NO;
+			else if (regRelay.relay_event.bits.Gun2_N == YES)
+				outputRelay.relay_event.bits.Gun2_N = NO;
+
+			if (_chargingData[index]->Type == _Type_CCS)
+			{
+				if(regRelay.relay_event.bits.CCS_Precharge == YES)
+					outputRelay.relay_event.bits.CCS_Precharge = NO;
+			}
+		}
+	}
+	else if ((_chargingData[index]->SystemStatus >= S_PREPARING_FOR_EVSE && _chargingData[index]->SystemStatus <= S_CHARGING))
+	{
+		if (_chargingData[index]->Evboard_id == 0x01)
+		{
+			if(regRelay.relay_event.bits.Gun1_N == NO)
+				outputRelay.relay_event.bits.Gun1_N = YES;
+			else if (regRelay.relay_event.bits.Gun1_P == NO)
+				outputRelay.relay_event.bits.Gun1_P = YES;
+		}
+		else if (_chargingData[index]->Evboard_id == 0x02)
+		{
+			if(regRelay.relay_event.bits.Gun2_N == NO)
+				outputRelay.relay_event.bits.Gun2_N = YES;
+			else if (regRelay.relay_event.bits.Gun2_P == NO)
+				outputRelay.relay_event.bits.Gun2_P = YES;
+		}
+	}
+	else if (_chargingData[index]->SystemStatus == S_COMPLETE)
+	{
+		if (_chargingData[index]->PresentChargingCurrent <= SEFETY_SWITCH_RELAY_CUR)
+		{
+			if (_chargingData[index]->Evboard_id == 0x01)
+			{
+				if(regRelay.relay_event.bits.Gun1_P == YES)
+					outputRelay.relay_event.bits.Gun1_P = NO;
+				else if (regRelay.relay_event.bits.Gun1_N == YES)
+					outputRelay.relay_event.bits.Gun1_N = NO;
+			}
+			else if (_chargingData[index]->Evboard_id == 0x02)
+			{
+				if(regRelay.relay_event.bits.Gun2_P == YES)
+					outputRelay.relay_event.bits.Gun2_P = NO;
+				else if (regRelay.relay_event.bits.Gun2_N == YES)
+					outputRelay.relay_event.bits.Gun2_N = NO;
+			}
+		}
+	}
+	else if (_chargingData[index]->SystemStatus == S_CCS_PRECHARGE_ST0)
+	{
+		if (_chargingData[index]->Evboard_id == 0x01)
+		{
+			if (_chargingData[index]->Type == _Type_CCS)
+			{
+				if (regRelay.relay_event.bits.CCS_Precharge == NO)
+					outputRelay.relay_event.bits.CCS_Precharge = YES;
+				else if (regRelay.relay_event.bits.CCS_Precharge == YES)
+					outputRelay.relay_event.bits.Gun1_P = NO;
+			}
+		}
+		else if (_chargingData[index]->Evboard_id == 0x02)
+		{
+			if (_chargingData[index]->Type == _Type_CCS)
+			{
+				if (regRelay.relay_event.bits.CCS_Precharge == NO)
+					outputRelay.relay_event.bits.CCS_Precharge = YES;
+				else if (regRelay.relay_event.bits.CCS_Precharge == YES)
+					outputRelay.relay_event.bits.Gun2_P = NO;
+			}
+		}
+	}
+	else if (_chargingData[index]->SystemStatus == S_CCS_PRECHARGE_ST1)
+	{
+		if (_chargingData[index]->Evboard_id == 0x01)
+		{
+			if (_chargingData[index]->Type == _Type_CCS)
+			{
+				if (regRelay.relay_event.bits.Gun1_P == NO)
+					outputRelay.relay_event.bits.Gun1_P = YES;
+				else if(regRelay.relay_event.bits.Gun1_P == YES)
+					outputRelay.relay_event.bits.CCS_Precharge = NO;
+			}
+		}
+		else if (_chargingData[index]->Evboard_id == 0x02)
+		{
+			if (_chargingData[index]->Type == _Type_CCS)
+			{
+				if (regRelay.relay_event.bits.Gun2_P == NO)
+					outputRelay.relay_event.bits.Gun2_P = YES;
+				else if(regRelay.relay_event.bits.Gun2_P == YES)
+					outputRelay.relay_event.bits.CCS_Precharge = NO;
+			}
+		}
+	}
+}
+
+void SetParalleRelayStatus()
+{
+	if (gunCount >= 2)
+	{
+		if (_chargingData[0]->SystemStatus == S_BOOTING || _chargingData[1]->SystemStatus == S_BOOTING)
+		{
+			// 初始化~ 不搭橋接
+			if (regRelay.relay_event.bits.Gun1_Parallel_P == YES)
+				outputRelay.relay_event.bits.Gun1_Parallel_P = NO;
+			else if (regRelay.relay_event.bits.Gun1_Parallel_N == YES)
+				outputRelay.relay_event.bits.Gun1_Parallel_N = NO;
+		}
+		else
+		{
+			// 單槍充電中 - 搭上橋接
+			if((_chargingData[0]->IsReadyToCharging == YES && _chargingData[1]->IsReadyToCharging == NO) ||
+					(_chargingData[0]->IsReadyToCharging == NO && _chargingData[1]->IsReadyToCharging == YES))
+			{
+				if (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag >= _REASSIGNED_RELAY)
+				{
+					if (regRelay.relay_event.bits.Gun1_Parallel_P == YES)
+						outputRelay.relay_event.bits.Gun1_Parallel_P = NO;
+					else if (regRelay.relay_event.bits.Gun1_Parallel_N == YES)
+						outputRelay.relay_event.bits.Gun1_Parallel_N = NO;
+				}
+				else
+				{
+					if (regRelay.relay_event.bits.Gun1_Parallel_N == NO)
+						outputRelay.relay_event.bits.Gun1_Parallel_N = YES;
+					else if (regRelay.relay_event.bits.Gun1_Parallel_P == NO)
+						outputRelay.relay_event.bits.Gun1_Parallel_P = YES;
+				}
+			}
+			else
+			{
+				// 雙槍充電中~ 不搭橋接
+				if (regRelay.relay_event.bits.Gun1_Parallel_P == YES)
+					outputRelay.relay_event.bits.Gun1_Parallel_P = NO;
+				else if (regRelay.relay_event.bits.Gun1_Parallel_N == YES)
+					outputRelay.relay_event.bits.Gun1_Parallel_N = NO;
+			}
+		}
+	}
+}
+
+//==========================================
+// Init all share memory
+//==========================================
+int InitShareMemory()
+{
+	int result = PASS;
+	int MeterSMId;
+
+	//creat ShmSysConfigAndInfo
+	if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo),  0777)) < 0)
+	{
+		#ifdef SystemLogMessage
+		DEBUG_ERROR("shmget ShmSysConfigAndInfo NG\n");
+		#endif
+		result = FAIL;
+	}
+	else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+	{
+		#ifdef SystemLogMessage
+		DEBUG_ERROR("[shmat ShmSysConfigAndInfo NG\n");
+		#endif
+		result = FAIL;
+	 }
+	 //creat ShmStatusCodeData
+	if ((MeterSMId = shmget(ShmStatusCodeKey, sizeof(struct StatusCodeData),  0777)) < 0)
+	{
+		#ifdef SystemLogMessage
+		DEBUG_ERROR("shmget ShmStatusCodeData NG\n");
+		#endif
+		result = FAIL;
+	}
+	else if ((ShmStatusCodeData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+	{
+		#ifdef SystemLogMessage
+		DEBUG_ERROR("shmat ShmStatusCodeData NG\n");
+		#endif
+		result = FAIL;
+	}
+
+	//creat ShmFanModuleData
+	if ((MeterSMId = shmget(ShmFanBdKey, sizeof(struct FanModuleData),  0777)) < 0)
+	{
+		#ifdef SystemLogMessage
+		DEBUG_ERROR("shmget ShmFanModuleData NG\n");
+		#endif
+		result = FAIL;
+	}
+	else if ((ShmFanModuleData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+	{
+		#ifdef SystemLogMessage
+		DEBUG_ERROR("shmat ShmFanModuleData NG\n");
+		#endif
+		result = FAIL;
+	 }
+	 memset(ShmFanModuleData,0,sizeof(struct FanModuleData));
+	 //creat ShmRelayModuleData
+	if ((MeterSMId = shmget(ShmRelayBdKey, sizeof(struct RelayModuleData),  0777)) < 0)
+	{
+		#ifdef SystemLogMessage
+		DEBUG_ERROR("shmget ShmRelayModuleData NG\n");
+		#endif
+		result = FAIL;
+	}
+	else if ((ShmRelayModuleData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+	{
+		#ifdef SystemLogMessage
+		DEBUG_ERROR("shmat ShmRelayModuleData NG\n");
+		#endif
+		result = FAIL;
+	}
+
+	if(CHAdeMO_QUANTITY > 0)
+	{
+		if ((MeterSMId = shmget(ShmCHAdeMOCommKey, sizeof(struct CHAdeMOData),	IPC_CREAT | 0777)) < 0)
+		{
+			#ifdef SystemLogMessage
+			DEBUG_ERROR("[shmget ShmCHAdeMOData NG \n");
+			#endif
+			return FAIL;
+		}
+		else if ((ShmCHAdeMOData = shmat(MeterSMId, NULL, 0)) == (void *) -1) {
+			#ifdef SystemLogMessage
+			DEBUG_ERROR("shmat ShmCHAdeMOData NG \n");
+			#endif
+			return FAIL;
+		}
+	}
+
+	if(CCS_QUANTITY > 0)
+	{
+		if ((MeterSMId = shmget(ShmCcsCommKey, sizeof(struct CcsData),	IPC_CREAT | 0777)) < 0)
+		{
+			#ifdef SystemLogMessage
+			DEBUG_ERROR("shmget ShmCcsData NG \n");
+			#endif
+			return FAIL;
+		}
+		else if ((ShmCcsData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+		{
+			#ifdef SystemLogMessage
+		   	DEBUG_ERROR("shmat ShmCcsData NG \n");
+			#endif
+			return FAIL;
+		}
+	}
+
+
+	return result;
+}
+
+int InitComPort()
+{
+	int fd;
+	struct termios tios;
+
+	fd = open(relayRs485PortName, O_RDWR);
+	if(fd <= 0)
+	{
+		#ifdef SystemLogMessage
+		DEBUG_ERROR("Module_InternalComm. InitComPort NG\n");
+		#endif
+		if(ShmStatusCodeData!=NULL)
+		{
+			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CsuInitFailed=1;
+		}
+		sleep(5);
+		return -1;
+	}
+	ioctl (fd, TCGETS, &tios);
+	tios.c_cflag = B115200 | CS8 | CLOCAL | CREAD;
+	tios.c_lflag = 0;
+	tios.c_iflag = 0;
+	tios.c_oflag = 0;
+	tios.c_cc[VMIN]=0;
+	tios.c_cc[VTIME]=(byte)0;		// timeout 0.5 second
+	tios.c_lflag=0;
+	tcflush(fd, TCIFLUSH);
+	ioctl (fd, TCSETS, &tios);
+
+	return fd;
+}
+
+//================================================
+// Main process
+//================================================
+bool FindChargingInfoData(byte target, struct ChargingInfoData **chargingData)
+{
+	for (byte index = 0; index < CHAdeMO_QUANTITY; index++) {
+		if (ShmSysConfigAndInfo->SysInfo.ChademoChargingData[index].Index
+				== target) {
+			chargingData[target] =
+					&ShmSysConfigAndInfo->SysInfo.ChademoChargingData[index];
+			return true;
+		}
+	}
+
+	for (byte index = 0; index < CCS_QUANTITY; index++) {
+		if (ShmSysConfigAndInfo->SysInfo.CcsChargingData[index].Index
+				== target) {
+			chargingData[target] =
+					&ShmSysConfigAndInfo->SysInfo.CcsChargingData[index];
+			return true;
+		}
+	}
+
+	for (byte index = 0; index < GB_QUANTITY; index++) {
+		if (ShmSysConfigAndInfo->SysInfo.GbChargingData[index].Index
+				== target) {
+			chargingData[target] =
+					&ShmSysConfigAndInfo->SysInfo.GbChargingData[index];
+			return true;
+		}
+	}
+
+	return false;
+}
+
+void Initialization()
+{
+	bool isPass = false;
+
+	for (byte index = 0; index < ARRAY_SIZE(outputRelay.relay_event.relay_status); index++)
+	{
+		outputRelay.relay_event.relay_status[index] = 0x00;
+	}
+
+	while(!isPass)
+	{
+		isPass = true;
+		for (byte _index = 0; _index < gunCount; _index++)
+		{
+			if (!FindChargingInfoData(_index, &_chargingData[0]))
+			{
+				DEBUG_ERROR("EvComm (main) : FindChargingInfoData false \n");
+				isPass = false;
+				break;
+			}
+		}
+	}
+}
+
+bool IsNoneMatchRelayStatus()
+{
+	bool result = false;
+
+//	printf("Real Relay, AC = %x, g1_p = %x, g1_n = %x, g2_p = %x, g2_n = %x, pre = %x, bri_p = %x, bri_n = %x \n",
+//			regRelay.relay_event.bits.AC_Contactor,
+//			regRelay.relay_event.bits.Gun1_P,
+//			regRelay.relay_event.bits.Gun1_N,
+//			regRelay.relay_event.bits.Gun2_P,
+//			regRelay.relay_event.bits.Gun2_N,
+//			regRelay.relay_event.bits.CCS_Precharge,
+//			regRelay.relay_event.bits.Gun1_Parallel_P,
+//			regRelay.relay_event.bits.Gun1_Parallel_N);
+
+	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_P = outputRelay.relay_event.bits.Gun1_Parallel_P;
+	regRelay.relay_event.bits.Gun1_Parallel_N = outputRelay.relay_event.bits.Gun1_Parallel_N;
+}
+
+void CheckRelayStatusByADC()
+{
+	if (ShmRelayModuleData->Gun1FuseOutputVolt > 0 && ShmRelayModuleData->Gun1RelayOutputVolt > 0 &&
+			(ShmRelayModuleData->Gun1FuseOutputVolt == ShmRelayModuleData->Gun1RelayOutputVolt))
+	{
+		// Relay 前後電壓一致
+		_chargingData[0]->RelayK1K2Status = 0x01;
+	}
+	else
+		_chargingData[0]->RelayK1K2Status = 0x00;
+
+	if (ShmRelayModuleData->Gun2FuseOutputVolt > 0 && ShmRelayModuleData->Gun2RelayOutputVolt > 0 &&
+				(ShmRelayModuleData->Gun2FuseOutputVolt == ShmRelayModuleData->Gun2RelayOutputVolt))
+	{
+		// Relay 前後電壓一致
+		_chargingData[1]->RelayK1K2Status = 0x01;
+	}
+	else
+		_chargingData[1]->RelayK1K2Status = 0x00;
+}
+
+void SetGfdConfig(byte index, short resister)
+{
+	gfd_config.index = index;
+	gfd_config.reqVol = _chargingData[index]->EvBatterytargetVoltage;
+	gfd_config.resister = resister;
+
+	//printf("************************GFD Vol = %d, GFD Res = %d \n", gfd_config.reqVol, gfd_config.resister);
+	if (Config_Gfd_Value(Uart5Fd, Addr.Relay, &gfd_config) == PASS)
+	{
+//		printf("Set reqVol = %f, resister = %d \n",
+//				gfd_config.reqVol,
+//				gfd_config.resister);
+	}
+}
+
+void CableCheckDetected(byte index)
+{
+	// Cable Check
+	// 當火線上的電壓 = 車端要求的電壓電流
+	// _chargingData[targetGun]->EvBatterytargetVoltage
+	// 才可以開始偵測 1s
+	// Warning : Rgfd <= 150 歐/V 假設電壓為 500V 則~ Rgfd <= 75000 歐
+	// Pre-Warning : 150 歐/V < Rgfd <= 500 歐/V 假設電壓為 500V 則 75000 歐 < Rgfd <= 250000
+	// SO Normal : Rgfd > 500 歐/V 假設電壓為 500 V 則 Rgfd > 250000 歐
+	if ((_chargingData[index]->SystemStatus >= S_PREPARING_FOR_EVSE && _chargingData[index]->SystemStatus <= S_CHARGING) ||
+			(_chargingData[index]->SystemStatus >= S_CCS_PRECHARGE_ST0 && _chargingData[index]->SystemStatus <= S_CCS_PRECHARGE_ST1))
+	{
+		// Cable check
+		SetGfdConfig(index, GFD_VALUE);
+	}
+	else if(_chargingData[index]->SystemStatus == S_COMPLETE || _chargingData[index]->SystemStatus == S_PREPARNING
+			|| _chargingData[index]->SystemStatus == S_IDLE)
+	{
+		SetGfdConfig(index, 0);
+	}
+}
+
+int main(void)
+{
+	if(InitShareMemory() == FAIL)
+	{
+		#ifdef SystemLogMessage
+		DEBUG_ERROR("InitShareMemory NG\n");
+		#endif
+		if(ShmStatusCodeData!=NULL)
+		{
+			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FailToCreateShareMemory=1;
+		}
+		sleep(5);
+		return 0;
+	}
+	// Open Uart5 for RB
+	Uart5Fd = InitComPort();
+	Initialization();
+	sleep(1);
+
+	if(Uart5Fd < 0)
+	{
+		printf ("open port error. \n");
+		return 0;
+	}
+
+	outputRelay.relay_event.bits.AC_Contactor = 0x00;
+	//outputRelay.relay_event.bits.CCS_Precharge = 0x01;
+	//outputRelay.relay_event.bits.Gun1_Parallel_P = 0x01;
+	//outputRelay.relay_event.bits.Gun1_Parallel_N = 0x01;
+	//outputRelay.relay_event.bits.Gun1_P = 0x00;
+	//outputRelay.relay_event.bits.Gun1_N = 0x00;
+	//outputRelay.relay_event.bits.Gun2_P = 0x01;
+	//outputRelay.relay_event.bits.Gun2_N = 0x01;
+	Config_Relay_Output(Uart5Fd, Addr.Relay, &outputRelay);
+
+	gettimeofday(&_priority_time, NULL);
+	for(;;)
+	{
+		// 程序開始之前~ 必須先確定 FW 版本與硬體版本,確認後!!~ 該模組才算是真正的 Initial Comp.
+		if (ShmRelayModuleData->SelfTest_Comp == NO)
+		{
+			printf("(RB) Get Fw and Hw Ver. \n");
+			GetFwAndHwVersion_Relay();
+			GetFwAndHwVersion_Fan();
+			sleep(1);
+		}
+		else if (ShmRelayModuleData->SelfTest_Comp == YES)
+		{
+			// ==============優先權最高 10 ms ==============
+			// 輸出電壓
+			GetPersentOutputVol();
+
+			// 三相輸入電壓
+			GetPresentInputVol();
+
+			// 讀取當前 relay 狀態
+			GetRelayOutputStatus();
+
+			bool isCharging = false;
+			for (int i = 0; i < gunCount; i++)
+			{
+				// Cable check (Set)
+				//CableCheckDetected(i);
+
+				// check k1 k2 relay 狀態
+				CheckK1K2RelayOutput(i);
+
+				// 依據當前各槍的狀態選擇 搭上/放開 Relay
+				SetK1K2RelayStatus(i);
+
+				if (_chargingData[i]->SystemStatus == S_IDLE)
+					gfdChkFailCount[i] = 0;
+
+				if (_chargingData[i]->SystemStatus == S_BOOTING	||
+					(_chargingData[i]->SystemStatus >= S_PREPARNING && _chargingData[i]->SystemStatus <= S_COMPLETE) ||
+					(_chargingData[i]->SystemStatus >= S_CCS_PRECHARGE_ST0 && _chargingData[i]->SystemStatus <= S_CCS_PRECHARGE_ST1))
+				{
+					_chargingData[i]->IsReadyToCharging = YES;
+					isCharging = true;
+				}
+				else
+					_chargingData[i]->IsReadyToCharging = NO;
+			}
+			// Cable check (Get)
+			//GetGfdAdc();
+
+			SetParalleRelayStatus();
+
+			// 搭上 AC Contactor
+			if (isCharging)
+				outputRelay.relay_event.bits.AC_Contactor = YES;
+			else
+				outputRelay.relay_event.bits.AC_Contactor = NO;
+
+			// 搭上/鬆開 Relay
+			// 放開 Relay 之前要先確認輸出的電壓電流是否已經降到某個值
+			if(IsNoneMatchRelayStatus())
+			{
+				if (Config_Relay_Output(Uart5Fd, Addr.Relay, &outputRelay))
+				{
+					printf("Match Relay, AC = %x, g1_p = %x, g1_n = %x, g2_p = %x, g2_n = %x, pre = %x, bri_p = %x, bri_n = %x \n",
+							regRelay.relay_event.bits.AC_Contactor,
+							regRelay.relay_event.bits.Gun1_P,
+							regRelay.relay_event.bits.Gun1_N,
+							regRelay.relay_event.bits.Gun2_P,
+							regRelay.relay_event.bits.Gun2_N,
+							regRelay.relay_event.bits.CCS_Precharge,
+							regRelay.relay_event.bits.Gun1_Parallel_P,
+							regRelay.relay_event.bits.Gun1_Parallel_N);
+				}
+			}
+			// 風扇控制
+			//GetFanSpeed();
+
+			if (GetTimeoutValue(_priority_time) / 1000 >= 1000)
+			{
+				gettimeofday(&_priority_time, NULL);
+				if (isCharging)
+				{
+					if (ShmFanModuleData->PresentFan1Speed < MAX_FAN_SPEED)
+					{
+						ShmFanModuleData->SetFan1Speed = MAX_FAN_SPEED;
+						ShmFanModuleData->SetFan2Speed = MAX_FAN_SPEED;
+						ShmFanModuleData->SetFan3Speed = MAX_FAN_SPEED;
+						ShmFanModuleData->SetFan4Speed = MAX_FAN_SPEED;
+					}
+				}
+				else
+				{
+					if (ShmFanModuleData->PresentFan1Speed > MIN_FAN_SPEED)
+					{
+						ShmFanModuleData->SetFan1Speed = MIN_FAN_SPEED;
+						ShmFanModuleData->SetFan2Speed = MIN_FAN_SPEED;
+						ShmFanModuleData->SetFan3Speed = MIN_FAN_SPEED;
+						ShmFanModuleData->SetFan4Speed = MIN_FAN_SPEED;
+					}
+				}
+				//SetFanModuleSpeed();
+			}
+		}
+		usleep(10000);
+	}
+
+	return FAIL;
+}

BIN
EVSE/Projects/DM30/Apps/Module_InternalComm.o


BIN
EVSE/Projects/DM30/Apps/Module_LcmControl


BIN
EVSE/Projects/DM30/Apps/Module_LcmControl.o


BIN
EVSE/Projects/DM30/Apps/Module_PrimaryComm


BIN
EVSE/Projects/DM30/Apps/Module_PrimaryComm.o


BIN
EVSE/Projects/DM30/Apps/Module_PsuComm


BIN
EVSE/Projects/DM30/Apps/Module_PsuComm.o


BIN
EVSE/Projects/DM30/Apps/PrimaryComm.o


BIN
EVSE/Projects/DM30/Apps/ReadCmdline


BIN
EVSE/Projects/DM30/Apps/ReadCmdline.o


+ 751 - 0
EVSE/Projects/DM30/Apps/internalComm.c

@@ -0,0 +1,751 @@
+/*
+ * internalComm.c
+ *
+ *  Created on: 2019年5月7日
+ *      Author: foluswen
+ */
+#include 	<sys/time.h>
+#include 	<sys/timeb.h>
+#include    <sys/types.h>
+#include    <sys/stat.h>
+#include 	<sys/types.h>
+#include 	<sys/ioctl.h>
+#include 	<sys/socket.h>
+#include 	<sys/ipc.h>
+#include 	<sys/shm.h>
+#include 	<sys/shm.h>
+#include 	<sys/mman.h>
+#include 	<linux/wireless.h>
+#include 	<arpa/inet.h>
+#include 	<netinet/in.h>
+
+#include 	<unistd.h>
+#include 	<stdarg.h>
+#include    <stdio.h>      /*標準輸入輸出定義*/
+#include    <stdlib.h>     /*標準函數庫定義*/
+#include    <unistd.h>     /*Unix 標準函數定義*/
+#include    <fcntl.h>      /*檔控制定義*/
+#include    <termios.h>    /*PPSIX 終端控制定義*/
+#include    <errno.h>      /*錯誤號定義*/
+#include 	<errno.h>
+#include 	<string.h>
+#include	<time.h>
+#include	<ctype.h>
+#include 	<ifaddrs.h>
+#include 	<math.h>
+#include 	"internalComm.h"
+
+#define PASS				1
+#define FAIL				-1
+
+struct Address Addr={0x01,0x02,0x03,0xFF};
+struct Command Cmd={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x81,0x85,0x86,0x87,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(10000);
+		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);
+
+//	for (int i = 0; i < 7; i++)
+//		printf("tx = %x \n", tx[i]);
+//	for (int i = 0; i < len; i++)
+//		printf("rx = %x \n", rx[i]);
+
+	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);
+
+//	for(int i = 0; i < 7; i++)
+//		printf ("tx = %d \n", tx[i]);
+	if(len > 6)
+	{
+		if (len < 6+(rx[4] | rx[5]<<8))
+		{
+			printf("Query_Gfd_Adc fail \n");
+			return result;
+		}
+
+//		for(int i = 0; i < len; i++)
+//			printf ("rx = %d \n", rx[i]);
+
+		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->Resister_conn1 = (rx[6] | (rx[7] << 8));
+			Ret_Buf->voltage_conn1 = (rx[8] | (rx[9] << 8));
+			Ret_Buf->result_conn1 = rx[10];
+			Ret_Buf->rb_step_1 = rx[11];
+
+			Ret_Buf->Resister_conn2 = (rx[12] | (rx[13] << 8));
+			Ret_Buf->voltage_conn2 = (rx[14] | (rx[15] << 8));
+			Ret_Buf->result_conn2 = rx[16];
+			Ret_Buf->rb_step_2 = rx[17];
+
+			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[15] = {0xaa, 0x00, targetAddr, Cmd.config_Fan_Speed, 0x08, 0x00, Set_Buf->speed[0]&0xff, (Set_Buf->speed[0]>>8)&0xff, Set_Buf->speed[1]&0xff, (Set_Buf->speed[1]>>8)&0xff, Set_Buf->speed[2]&0xff, (Set_Buf->speed[2]>>8)&0xff, Set_Buf->speed[3]&0xff, (Set_Buf->speed[3]>>8)&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[14] = 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 = 6;idx<8;idx++)
+		chksum ^= tx[idx];
+	tx[9] = chksum;
+
+//	for (int i = 0; i < 10; i++)
+//		printf("set relay cmd : tx = %x \n", tx[i]);
+
+	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] == 0x01))
+		{
+			result = PASS;
+		}
+	}
+
+	return result;
+}
+
+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;
+
+	tx[6] |= (Set_Buf->AC_Connector?0x01:0x00);
+
+	for(int idx = 0;idx<2;idx++)
+		tx[6] |= (Set_Buf->Button_LED[idx]?0x01:0x00)<<(1+idx);
+
+	for(int idx = 0;idx<4;idx++)
+			tx[6] |= (Set_Buf->System_LED[idx]?0x01:0x00)<<(3+idx);
+
+	for(int idx = 0;idx<(tx[4] | tx[5]<<8);idx++)
+		chksum ^= tx[6+idx];
+	tx[14] = 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 Config_Gfd_Value(unsigned char fd, unsigned char targetAddr, Gfd_config *Set_Buf)
+{
+	unsigned char result = FAIL;
+	unsigned char tx[12] = {0xaa, 0x00, targetAddr, Cmd.config_Gfd_Value, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+	unsigned char rx[512];
+	unsigned char chksum = 0x00;
+
+	tx[6] = Set_Buf->index;
+	tx[7] = (unsigned char)(Set_Buf->reqVol) & 0xff;
+	tx[8] = (Set_Buf->reqVol >> 8) & 0xff;
+	tx[9] = (unsigned char)(Set_Buf->resister) & 0xff;
+	tx[10] = (Set_Buf->resister >> 8) & 0xff;
+
+	for(int idx = 0; idx<(tx[4] | tx[5]<<8);idx++)
+		chksum ^= tx[6+idx];
+	tx[11] = 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;
+}

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

@@ -0,0 +1,186 @@
+/*
+ * internalComm.h
+ *
+ *  Created on: 2019¦~5¤ë7¤é
+ *      Author: foluswen
+ */
+
+#ifndef INTERNALCOMM_H_
+#define INTERNALCOMM_H_
+
+extern struct Address
+{
+	unsigned char Aux;
+	unsigned char Fan;
+	unsigned char Relay;
+	unsigned char Broadcast;
+}Addr;
+
+extern struct Command
+{
+	unsigned char query_FW_Ver; 				//0x01
+	unsigned char query_HW_Ver; 				//0x02
+	unsigned char query_Present_InputVoltage;	//0x03
+	unsigned char query_Present_OutputVoltage;	//0x04
+	unsigned char query_Fan_Speed;				//0x05
+	unsigned char query_Temperature;			//0x06
+	unsigned char query_Aux_PowerVoltage;		//0x07
+	unsigned char query_Relay_Output;			//0x08
+	unsigned char query_Gfd_Adc;				//0x09
+	unsigned char query_Gpio_In;				//0x0a
+
+	unsigned char config_Fan_Speed;			//0x81
+	unsigned char config_Relay_Output;			//0x85
+	unsigned char config_Gpio_Output;			//0x86
+	unsigned char config_Gfd_Value;			//0x87
+
+	unsigned char update_Start;				//0xe0
+	unsigned char update_Abort;				//0xe1
+	unsigned char update_Transfer;				//0xe2
+	unsigned char update_Finish;				//0xe3
+
+}Cmd;
+
+typedef struct Verion
+{
+	char Version_FW[9];
+	char Version_HW[9];
+}Ver;
+
+typedef struct PRESENTINPUTVOLTAGE
+{
+	unsigned char inputType;	// 0x00: Line to Line       0x01: Line to Neutral
+	double L1N_L12;
+	double L2N_L23;
+	double L3N_L31;
+}PresentInputVoltage;
+
+typedef struct PRESENTOUTPUTVOLTAGE
+{
+	double behindFuse_Voltage_C1;
+	double behindRelay_Voltage_C1;
+	double behindFuse_Voltage_C2;
+	double behindRelay_Voltage_C2;
+}PresentOutputVoltage;
+
+typedef struct FANSPEED
+{
+	unsigned short int speed[8];
+}FanSpeed;
+
+typedef struct TEMPERATURE
+{
+	unsigned char temperature[8];
+}Temperature;
+
+typedef struct AUXPOWER
+{
+	unsigned char voltage[8];
+}AuxPower;
+
+typedef struct RELAY
+{
+	union
+	{
+		unsigned char relay_status[8];
+		struct
+		{
+			unsigned char AC_Contactor :1;		//bit 0
+			unsigned char CCS_Precharge :1;	//bit 1
+			unsigned char :1;  				//bit 2 reserved
+			unsigned char :1;					//bit 3 reserved
+			unsigned char :1;					//bit 4 reserved
+			unsigned char :1;					//bit 5 reserved
+			unsigned char :1;					//bit 6 reserved
+			unsigned char :1;					//bit 7 reserved
+
+			unsigned char Gun1_N :1;			//bit 0
+			unsigned char Gun1_P :1;			//bit 1
+			unsigned char Gun1_Parallel_N :1;  //bit 2
+			unsigned char Gun1_Parallel_P :1;	//bit 3
+			unsigned char :1;					//bit 4 reserved
+			unsigned char :1;					//bit 5 reserved
+			unsigned char :1;					//bit 6 reserved
+			unsigned char :1;					//bit 7 reserved
+
+			unsigned char Gun2_N :1;			//bit 0
+			unsigned char Gun2_P :1;			//bit 1
+			unsigned char :1; 					//bit 2 reserved
+			unsigned char :1;					//bit 3 reserved
+			unsigned char :1;					//bit 4 reserved
+			unsigned char :1;					//bit 5 reserved
+			unsigned char :1;					//bit 6 reserved
+			unsigned char :1;					//bit 7 reserved
+		}bits;
+	}relay_event;
+}Relay;
+
+typedef struct GFD
+{
+	unsigned short Resister_conn1;
+	unsigned short voltage_conn1;
+	unsigned char result_conn1;
+	unsigned char rb_step_1;
+
+	unsigned short Resister_conn2;
+	unsigned short voltage_conn2;
+	unsigned char result_conn2;
+	unsigned char rb_step_2;
+}Gfd;
+
+typedef struct Gfd_CONFIG
+{
+	unsigned char index;
+	short reqVol;
+	short resister;
+}Gfd_config;
+
+typedef struct GPIO_IN
+{
+	unsigned char AC_Connector;			// bit 0
+	unsigned char AC_MainBreaker;			// bit 1
+	unsigned char SPD;						// bit 2
+	unsigned char Door_Open;				// bit 3
+	unsigned char GFD[2];					// bit 4,5
+	unsigned char AC_Drop;					// bit 6
+
+	unsigned char Emergency_IO;			// bit 0
+
+	unsigned char Button_Emergency_Press;	// bit 0
+	unsigned char Button_On_Press;			// bit 1
+	unsigned char Button_Off_Press;		// bit 2
+	unsigned char Key_1_Press;				// bit 3
+	unsigned char Key_2_Press;				// bit 4
+	unsigned char Key_3_Press;				// bit 5
+	unsigned char Key_4_Press;				// bit 6
+}Gpio_in;
+
+typedef struct GPIO_OUT
+{
+	unsigned char AC_Connector;
+	unsigned char Button_LED[2];
+	unsigned char System_LED[4];
+}Gpio_out;
+
+extern unsigned char Query_FW_Ver(unsigned char fd, unsigned char targetAddr, Ver *Ret_Buf);
+extern unsigned char Query_HW_Ver(unsigned char fd, unsigned char targetAddr, Ver *Ret_Buf);
+extern unsigned char Query_Present_InputVoltage(unsigned char fd, unsigned char targetAddr, PresentInputVoltage *Ret_Buf);
+extern unsigned char Query_Present_OutputVoltage(unsigned char fd, unsigned char targetAddr, PresentOutputVoltage *Ret_Buf);
+extern unsigned char Query_Fan_Speed(unsigned char fd, unsigned char targetAddr, FanSpeed *Ret_Buf);
+extern unsigned char Query_Temperature(unsigned char fd, unsigned char targetAddr, Temperature *Ret_Buf);
+extern unsigned char Query_Aux_PowerVoltage(unsigned char fd, unsigned char targetAddr, AuxPower *Ret_Buf);
+extern unsigned char Query_Relay_Output(unsigned char fd, unsigned char targetAddr, Relay *Ret_Buf);
+extern unsigned char Query_Gfd_Adc(unsigned char fd, unsigned char targetAddr, Gfd *Ret_Buf);
+extern unsigned char Query_Gpio_Input(unsigned char fd, unsigned char targetAddr, Gpio_in *Ret_Buf);
+
+extern unsigned char Config_Fan_Speed(unsigned char fd, unsigned char targetAddr, FanSpeed *Set_Buf);
+extern unsigned char Config_Relay_Output(unsigned char fd, unsigned char targetAddr, Relay *Set_Buf);
+extern unsigned char Config_Gpio_Output(unsigned char fd, unsigned char targetAddr, Gpio_out *Set_Buf);
+extern unsigned char Config_Gfd_Value(unsigned char fd, unsigned char targetAddr, Gfd_config *Set_Buf);
+
+extern unsigned char Update_Start(unsigned char fd, unsigned char targetAddr, unsigned int crc32);
+extern unsigned char Update_Abord(unsigned char fd, unsigned char targetAddr);
+extern unsigned char Update_Transfer(unsigned char fd, unsigned char targetAddr, unsigned int startAddr, unsigned char *data, unsigned short int length);
+extern unsigned char Update_Finish(unsigned char fd, unsigned char targetAddr);
+
+#endif /* INTERNALCOMM_H_ */

BIN
EVSE/Projects/DM30/Apps/internalComm.o


BIN
EVSE/Projects/DM30/Apps/main


+ 2761 - 0
EVSE/Projects/DM30/Apps/main.c

@@ -0,0 +1,2761 @@
+#include    <sys/types.h>
+#include    <sys/stat.h>
+#include 	<sys/time.h>
+#include 	<sys/timeb.h>
+#include 	<sys/types.h>
+#include 	<sys/ioctl.h>
+#include 	<sys/socket.h>
+#include 	<sys/ipc.h>
+#include 	<sys/shm.h>
+#include 	<sys/mman.h>
+#include 	<linux/wireless.h>
+#include 	<arpa/inet.h>
+#include 	<netinet/in.h>
+
+#include 	<unistd.h>
+#include 	<stdarg.h>
+#include    <stdio.h>      /*標準輸入輸出定義*/
+#include    <stdlib.h>     /*標準函數庫定義*/
+#include    <unistd.h>     /*Unix 標準函數定義*/
+#include    <fcntl.h>      /*檔控制定義*/
+#include    <termios.h>    /*PPSIX 終端控制定義*/
+#include    <errno.h>      /*錯誤號定義*/
+#include 	<errno.h>
+#include 	<string.h>
+#include	<time.h>
+#include	<ctype.h>
+#include 	<ifaddrs.h>
+#include 	<math.h>
+#include 	"../../define.h"
+#include 	"Config.h"
+#include 	<stdbool.h>
+#include 	<dirent.h>
+#include 	"Module_Upgrade.h"
+#include	"timeout.h"
+
+#define 	ARRAY_SIZE(A)		(sizeof(A) / sizeof(A[0]))
+#define 	PASS				1
+#define 	FAIL				-1
+#define 	BUFFER_SIZE			128
+#define 	YES					1
+#define 	NO					0
+#define 	NORMAL				0
+#define		ABNORMAL			1
+#define 	EQUAL				0
+#define 	BTN_RELEASE			0
+#define 	BTN_PRESS			1
+#define 	MAX_BUF 			64
+#define 	SYSFS_GPIO_DIR 		"/sys/class/gpio"
+
+bool IsAuthorizingMode();
+void ClearAuthorizedFlag();
+bool isDetectPlugin();
+void ClearDetectPluginFlag();
+int mystrcmp(unsigned char *p1, unsigned char *p2);
+
+unsigned char DetectBitValue(unsigned char _byte, unsigned char _bit);
+void SetBitValue(unsigned char *_byte, unsigned char _bit, unsigned char value);
+void ChargingTerminalProcess(byte gunIndex);
+void ChkPrimaryStatus();
+void StartSystemTimeoutDet(unsigned char flag);
+void StopSystemTimeoutDet();
+void StartGunInfoTimeoutDet(unsigned char gunIndex, unsigned char flag);
+void StopGunInfoTimeoutDet(unsigned char gunIndex);
+
+struct SysConfigAndInfo			*ShmSysConfigAndInfo;
+struct StatusCodeData 			*ShmStatusCodeData;
+struct PsuData 					*ShmPsuData;
+struct CHAdeMOData				*ShmCHAdeMOData;
+struct CcsData					*ShmCcsData;
+struct PrimaryMcuData			*ShmPrimaryMcuData;
+struct FanModuleData			*ShmFanModuleData;
+struct RelayModuleData			*ShmRelayModuleData;
+struct OCPP16Data				*ShmOCPP16Data;
+
+struct ChargingInfoData			*chargingInfo[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
+struct timeb 					startChargingTime[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
+struct timeb 					endChargingTime[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY];
+
+byte _gunCount = 0;
+// for initial index to check EV board type is correct
+byte _gunIndex = 0;
+byte _chademoIndex = 0;
+byte _ccsIndex = 0;
+byte _gb_Index = 0;
+byte bd0_1_status = 0;
+byte bd0_2_status = 0;
+byte bd1_1_status = 0;
+byte bd1_2_status = 0;
+
+bool isCardScan = false;
+
+int rfidFd = -1;
+char* rfidPortName = "/dev/ttyS2";
+byte autoReturnTimeoutFlag = 0x00;
+int whileLoopTime = 10000; // 10 ms
+unsigned char mask_table[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
+
+int StoreLogMsg(const char *fmt, ...);
+
+#define DEBUG_INFO(format, args...) StoreLogMsg("[%s:%d][%s][Info] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+#define DEBUG_WARN(format, args...) StoreLogMsg("[%s:%d][%s][Warn] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+#define DEBUG_ERROR(format, args...) StoreLogMsg("[%s:%d][%s][Error] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
+
+//================================================
+// 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;
+}
+
+//================================================
+// initial uart port
+//================================================
+char *priPortName = "/dev/ttyS1";
+
+int InitComPort(byte id)
+{
+	int fd;
+	struct termios tios;
+
+	if (id == 0x04)
+		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;
+}
+
+//=================================
+// Common routine
+//=================================
+int mystrcmp(unsigned char *p1, unsigned char *p2)
+{
+    while(*p1==*p2)
+    {
+        if(*p1=='\0' || *p2=='\0')
+            break;
+        p1++;
+        p2++;
+    }
+    if(*p1=='\0' && *p2=='\0')
+        return(PASS);
+    else
+        return(FAIL);
+}
+
+int DiffTimeb(struct timeb ST, struct timeb ET)
+{
+	//return milli-second
+	unsigned int StartTime,StopTime;
+
+	StartTime=(unsigned int)ST.time;
+	StopTime=(unsigned int)ET.time;
+	//return (StopTime-StartTime)*1000+ET.millitm-ST.millitm;
+	return (StopTime-StartTime);
+}
+
+int StoreLogMsg(const char *fmt, ...)
+{
+	char Buf[4096+256];
+	char buffer[4096];
+	time_t CurrentTime;
+	struct tm *tm;
+	va_list args;
+
+	va_start(args, fmt);
+	int rc = vsnprintf(buffer, sizeof(buffer), fmt, args);
+	va_end(args);
+
+	memset(Buf,0,sizeof(Buf));
+	CurrentTime = time(NULL);
+	tm=localtime(&CurrentTime);
+	sprintf(Buf,"echo \"%04d-%02d-%02d %02d:%02d:%02d - %s\" >> /Storage/SystemLog/[%04d.%02d]SystemLog",
+			tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec,
+			buffer,
+			tm->tm_year+1900,tm->tm_mon+1);
+	system(Buf);
+
+	return rc;
+}
+
+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;
+}
+
+void setChargerMode(byte gun_index, byte mode)
+{
+	chargingInfo[gun_index]->SystemStatus = mode;
+}
+
+//==========================================
+// Check interface status
+//==========================================
+int isInterfaceUp(const char *interface)
+{
+	int result = FAIL;
+
+	FILE *fp;
+	char cmd[256];
+	char buf[512];
+
+	strcpy(cmd, "ifconfig");
+	fp = popen(cmd, "r");
+	if(fp != NULL)
+	{
+		while(fgets(buf, sizeof(buf), fp) != NULL)
+		{
+			if(strstr(buf, interface) > 0)
+			{
+				result = PASS;
+			}
+		}
+	}
+	pclose(fp);
+
+	return result;
+}
+
+//=================================
+// Create all share memory
+//=================================
+int CreateShareMemory()
+{
+	int MeterSMId;
+
+	if ((MeterSMId = shmget(ShmSysConfigAndInfoKey,	sizeof(struct SysConfigAndInfo), IPC_CREAT | 0777)) < 0)
+	{
+		#ifdef SystemLogMessage
+		StoreLogMsg("[main]CreatShareMemory:shmget ShmSysConfigAndInfo NG \n");
+		#endif
+		return 0;
+	}
+	else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0))	== (void *) -1)
+	{
+		#ifdef SystemLogMessage
+		StoreLogMsg("[main]CreatShareMemory:shmat ShmSysConfigAndInfo NG \n");
+		#endif
+		return 0;
+	}
+	memset(ShmSysConfigAndInfo, 0, sizeof(struct SysConfigAndInfo));
+
+	if ((MeterSMId = shmget(ShmStatusCodeKey, sizeof(struct StatusCodeData), IPC_CREAT | 0777)) < 0)
+	{
+		#ifdef SystemLogMessage
+		StoreLogMsg("[main]CreatShareMemory:shmget ShmStatusCodeData NG \n");
+		#endif
+		return 0;
+	}
+	else if ((ShmStatusCodeData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+	{
+		#ifdef SystemLogMessage
+		StoreLogMsg("[main]CreatShareMemory:shmat ShmStatusCodeData NG \n");
+		#endif
+		return 0;
+	}
+
+	memset(ShmStatusCodeData, 0, sizeof(struct StatusCodeData));
+
+	//creat ShmPsuData
+	if ((MeterSMId = shmget(ShmPsuKey, sizeof(struct PsuData), IPC_CREAT | 0777)) < 0)
+	{
+		#ifdef SystemLogMessage
+		StoreLogMsg("[main]CreatShareMemory:shmget ShmPsuData NG \n");
+		#endif
+		return 0;
+	}
+	else if ((ShmPsuData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+	{
+		#ifdef SystemLogMessage
+		StoreLogMsg("[main]CreatShareMemory:shmat ShmPsuData NG \n");
+		#endif
+		return 0;
+	}
+	memset(ShmPsuData, 0, sizeof(struct PsuData));
+
+	if(CHAdeMO_QUANTITY > 0)
+	{
+		if ((MeterSMId = shmget(ShmCHAdeMOCommKey, sizeof(struct CHAdeMOData),	IPC_CREAT | 0777)) < 0)
+		{
+			#ifdef SystemLogMessage
+			StoreLogMsg("[main]CreatShareMemory:shmget ShmCHAdeMOData NG \n");
+			#endif
+			return 0;
+		}
+		else if ((ShmCHAdeMOData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+		{
+			#ifdef SystemLogMessage
+			StoreLogMsg("[main]CreatShareMemory:shmat ShmCHAdeMOData NG \n");
+			#endif
+			return 0;
+		}
+		memset(ShmCHAdeMOData, 0, sizeof(struct CHAdeMOData));
+	}
+
+	//creat ShmCcsData
+	if(CCS_QUANTITY > 0)
+	{
+		if ((MeterSMId = shmget(ShmCcsCommKey, sizeof(struct CcsData),	IPC_CREAT | 0777)) < 0)
+		{
+			#ifdef SystemLogMessage
+			StoreLogMsg("[main]CreatShareMemory:shmget ShmCcsData NG \n");
+			#endif
+			return 0;
+		}
+		else if ((ShmCcsData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+		{
+			#ifdef SystemLogMessage
+			StoreLogMsg("[main]CreatShareMemory:shmat ShmCcsData NG \n");
+			#endif
+			return 0;
+		}
+		memset(ShmCcsData, 0, sizeof(struct CcsData));
+	}
+
+	//creat ShmPrimaryMcuData
+	if ((MeterSMId = shmget(ShmPrimaryMcuKey, sizeof(struct PrimaryMcuData), IPC_CREAT | 0777)) < 0)
+	{
+		#ifdef SystemLogMessage
+		StoreLogMsg("[main]CreatShareMemory:shmget ShmPrimaryMcuData NG \n");
+		#endif
+		return 0;
+	}
+	else if ((ShmPrimaryMcuData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+	{
+		#ifdef SystemLogMessage
+		StoreLogMsg("[main]CreatShareMemory:shmat ShmPrimaryMcuData NG \n");
+		#endif
+		return 0;
+	}
+	memset(ShmPrimaryMcuData, 0, sizeof(struct PrimaryMcuData));
+
+	//creat ShmFanModuleData
+	if ((MeterSMId = shmget(ShmFanBdKey, sizeof(struct FanModuleData),	IPC_CREAT | 0777)) < 0)
+	{
+		#ifdef SystemLogMessage
+		StoreLogMsg("[main]CreatShareMemory:shmget ShmFanModuleData NG \n");
+		#endif
+		return 0;
+	}
+	else if ((ShmFanModuleData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+	{
+		#ifdef SystemLogMessage
+		StoreLogMsg("[main]CreatShareMemory:shmat ShmFanModuleData NG \n");
+		#endif
+		return 0;
+	}
+	memset(ShmFanModuleData, 0, sizeof(struct FanModuleData));
+
+	//creat ShmRelayModuleData
+	if ((MeterSMId = shmget(ShmRelayBdKey, sizeof(struct RelayModuleData),	IPC_CREAT | 0777)) < 0)
+	{
+		#ifdef SystemLogMessage
+		StoreLogMsg("[main]CreatShareMemory:shmget ShmRelayModuleData NG \n");
+		#endif
+		return 0;
+	}
+	else if ((ShmRelayModuleData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+	{
+		#ifdef SystemLogMessage
+		StoreLogMsg("[main]CreatShareMemory:shmat ShmRelayModuleData NG \n");
+		#endif
+		return 0;
+	}
+	memset(ShmRelayModuleData, 0, sizeof(struct RelayModuleData));
+
+	//creat ShmOCPP16Data
+	if ((MeterSMId = shmget(ShmOcppModuleKey, sizeof(struct OCPP16Data), IPC_CREAT | 0777)) < 0)
+	{
+		#ifdef SystemLogMessage
+		StoreLogMsg("[main]CreatShareMemory:shmget ShmOCPP16Data NG \n");
+		#endif
+		return 0;
+	}
+	else if ((ShmOCPP16Data = shmat(MeterSMId, NULL, 0)) == (void *) -1)
+	{
+		#ifdef SystemLogMessage
+		StoreLogMsg("[main]CreatShareMemory:shmat ShmOCPP16Data NG \n");
+		#endif
+		return 0;
+	}
+	// memset(ShmOCPP16Data,0,sizeof(struct OCPP16Data));
+	return 1;
+}
+
+//=================================
+// LCM Page
+//=================================
+void ChangeLcmByIndex(byte page_index)
+{
+	if (ShmSysConfigAndInfo->SysStopChargingAlarmCode.Level != 2 ||
+			page_index == _LCM_COMPLETE || page_index == _LCM_FIX)
+	{
+		ShmSysConfigAndInfo->SysInfo.PageIndex = page_index;
+	}
+}
+
+//======================================================
+// Peripheral initial
+//======================================================
+void InitGPIO()
+{
+	/*****************0~3, 4 bank, bank x 32+ num*********************/
+	/***************************************************************/
+	/*************** GPIO 0 ***************************************/
+	/***************************************************************/
+	/* GPMC_AD8			=> 	GPIO0_22 *//*ID BD1_1*/
+	system("echo 22 > /sys/class/gpio/export");
+	system("echo \"in\" > /sys/class/gpio/gpio22/direction");
+	/* GPMC_AD9			=>	GPIO0_23 *//*ID BD1_2*/
+	system("echo 23 > /sys/class/gpio/export");
+	system("echo \"in\" > /sys/class/gpio/gpio23/direction");
+	/* GPMC_AD10		=>	GPIO0_26 *//*IO BD1_1*/
+	system("echo 26 > /sys/class/gpio/export");
+	system("echo \"out\" > /sys/class/gpio/gpio26/direction");
+	system("echo 1 > /sys/class/gpio/gpio26/value");
+	/* GPMC_AD11		=>	GPIO0_27 *//*IO BD1_2*/
+	system("echo 27 > /sys/class/gpio/export");
+	system("echo \"in\" > /sys/class/gpio/gpio27/direction");
+	/* RMII1_REF_CLK		=>	GPIO0_29 *//*USB 0 OCP detection*/
+	system("echo 29 > /sys/class/gpio/export");
+	system("echo \"in\" > /sys/class/gpio/gpio29/direction");
+	/*XDMA_EVENT_INTR0	=>	GPIO0_19 *//*AM_RFID_RST*/
+	system("echo 19 > /sys/class/gpio/export");
+	system("echo \"out\" > /sys/class/gpio/gpio19/direction");
+	system("echo 0 > /sys/class/gpio/gpio19/value");
+	/*XDMA_EVENT_INTR1	=>	GPIO0_20 *//*AM_RFID_ICC*/
+	system("echo 20 > /sys/class/gpio/export");
+	system("echo \"in\" > /sys/class/gpio/gpio20/direction");
+	/***************************************************************/
+	/*************** GPIO 1 ***************************************/
+	/***************************************************************/
+	/* GPMC_AD12	=> 	GPIO1_12 *//*ID BD2_1*/
+	system("echo 44 > /sys/class/gpio/export");
+	system("echo \"in\" > /sys/class/gpio/gpio44/direction");
+	/* GPMC_AD13	=>	GPIO1_13 *//*ID BD2_2*/
+	system("echo 45 > /sys/class/gpio/export");
+	system("echo \"in\" > /sys/class/gpio/gpio45/direction");
+	/* GPMC_AD14	=>	GPIO1_14 *//*IO BD2_1*/
+	system("echo 46 > /sys/class/gpio/export");
+	system("echo \"out\" > /sys/class/gpio/gpio46/direction");
+	system("echo 0 > /sys/class/gpio/gpio46/value");
+	/* GPMC_AD15	=>	GPIO1_15 *//*IO BD2_2*/
+	system("echo 47 > /sys/class/gpio/export");
+	system("echo \"in\" > /sys/class/gpio/gpio47/direction");
+	/***************************************************************/
+	/*************** GPIO 2 ***************************************/
+	/***************************************************************/
+	/*LCD_AC_BIAS_EN	=>	GPIO2_25*//*RS-485 for module DE control*/
+	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*/
+	system("echo 87 > /sys/class/gpio/export");
+	system("echo \"out\" > /sys/class/gpio/gpio87/direction");
+	system("echo 0 > /sys/class/gpio/gpio87/value");
+	/*LCD_PCLK		=>	GPIO2_24*//*CCS communication board 1 proximity*/
+	system("echo 88 > /sys/class/gpio/export");
+	system("echo \"in\" > /sys/class/gpio/gpio88/direction");
+	/*LCD_VSYNC		=>	GPIO2_22*//*CCS communication board 2 proximity*/
+	system("echo 86 > /sys/class/gpio/export");
+	system("echo \"in\" > /sys/class/gpio/gpio86/direction");
+	/***************************************************************/
+	/*************** GPIO 3 ***************************************/
+	/***************************************************************/
+	/*MCASP0_FSX		=>	GPIO3_15*//*Emergency Stop button detect*/
+	system("echo 111 > /sys/class/gpio/export");
+	system("echo \"in\" > /sys/class/gpio/gpio111/direction");
+	/*MCASP0_ACLKR	=>	GPIO3_18*//*USB1 OCP detect*/
+	system("echo 114 > /sys/class/gpio/export");
+	system("echo \"in\" > /sys/class/gpio/gpio114/direction");
+	/*MCASP0_AHCLKR	=>	GPIO3_17*//*Emergency IO for AM3352 and STM32F407*/
+	system("echo 113 > /sys/class/gpio/export");
+	system("echo \"in\" > /sys/class/gpio/gpio113/direction");
+	/*MCASP0_ACLKX	=>	GPIO3_14*//*Ethernet PHY reset*/
+	system("echo 110 > /sys/class/gpio/export");
+	system("echo \"out\" > /sys/class/gpio/gpio110/direction");
+	system("echo 0 > /sys/class/gpio/gpio110/value");
+	/* MCASP0_FSR		=>	GPIO3_19 *//*SMR Enable control_1*/
+	system("echo 115 > /sys/class/gpio/export");
+	system("echo \"out\" > /sys/class/gpio/gpio115/direction");
+	system("echo 0 > /sys/class/gpio/gpio115/value");
+	/* MCASP0_AXR0	=>	GPIO3_16 *//*CSU board function OK indicator.*/
+	system("echo 112 > /sys/class/gpio/export");
+	system("echo \"out\" > /sys/class/gpio/gpio112/direction");
+	system("echo 0 > /sys/class/gpio/gpio112/value");
+	/* MCASP0_AXR1	=>	GPIO3_20 *//*SMR Enable control_2*/
+	system("echo 116 > /sys/class/gpio/export");
+	system("echo \"out\" > /sys/class/gpio/gpio116/direction");
+	system("echo 0 > /sys/class/gpio/gpio116/value");
+#ifdef SystemLogMessage
+	StoreLogMsg("[main]InitGPIO: Initial GPIO OK");
+#endif
+}
+
+int LoadSysConfigAndInfo(struct SysConfigData *ptr)
+{
+	int fd,wrd;
+	struct SysConfigData *buf;
+	byte *PtrBuf;
+	unsigned int ChkSum, ChkSumOrg;
+
+	if ((buf = malloc(sizeof(struct SysConfigData))) == NULL)
+	{
+		#ifdef SystemLogMessage
+		StoreLogMsg("[main]LoadSysConfigAndInfo:malloc buffer NG,rebooting..");
+		#endif
+		if (ShmStatusCodeData != NULL)
+		{
+			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CsuInitFailed = 1;
+		}
+		sleep(5);
+		system("reboot -f");
+		sleep(5);
+		system("reboot -f");
+	}
+	memset(buf, 0, sizeof(struct SysConfigData));
+
+	fd = open("/dev/mtdblock10", O_RDWR);
+	if (fd < 0)
+	{
+		free(buf);
+		#ifdef SystemLogMessage
+		StoreLogMsg("[main]LoadSysConfigAndInfo:open mtdblock10 NG,rebooting..");
+		#endif
+		if (ShmStatusCodeData != NULL)
+		{
+			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CsuInitFailed = 1;
+		}
+		sleep(5);
+		system("reboot -f");
+		sleep(5);
+		system("reboot -f");
+	}
+	wrd = read(fd, buf, sizeof(struct SysConfigData));
+	close(fd);
+	if (wrd != (sizeof(struct SysConfigData)))
+	{
+		free(buf);
+		#ifdef SystemLogMessage
+		StoreLogMsg("[main]LoadSysConfigAndInfo: read SysConfigData data NG,rebooting..");
+		#endif
+		if (ShmStatusCodeData != NULL)
+		{
+			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CsuInitFailed = 1;
+		}
+		sleep(5);
+		system("reboot -f");
+		sleep(5);
+		system("reboot -f");
+	}
+	PtrBuf = (byte *) buf;
+	ChkSum = 0;
+	for (wrd = 0; wrd < (sizeof(struct SysConfigData) - 4); wrd++)
+	{
+		ChkSum += PtrBuf[wrd];
+	}
+	ChkSumOrg = buf->Checksum;
+
+	if (ChkSum != ChkSumOrg)
+	{
+		#ifdef SystemLogMessage
+		StoreLogMsg("[main]LoadSysConfigAndInfo: Primary SysConfigData checksum NG, read backup");
+		#endif
+		fd = open("/dev/mtdblock11", O_RDWR);
+		if (fd < 0)
+		{
+			free(buf);
+			#ifdef SystemLogMessage
+			StoreLogMsg("[main]LoadSysConfigAndInfo: open mtdblock11 (backup) NG,rebooting..");
+			#endif
+			if (ShmStatusCodeData != NULL)
+			{
+				ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CsuInitFailed = 1;
+			}
+			sleep(5);
+			system("reboot -f");
+			sleep(5);
+			system("reboot -f");
+		}
+		memset(buf, 0, sizeof(struct SysConfigData));
+		wrd = read(fd, buf, sizeof(struct SysConfigData));
+		close(fd);
+		if (wrd != sizeof(struct SysConfigData))
+		{
+			free(buf);
+			#ifdef SystemLogMessage
+			StoreLogMsg("[main]LoadSysConfigAndInfo: read backup SysConfigData data NG,rebooting..");
+			#endif
+			if (ShmStatusCodeData != NULL)
+			{
+				ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CsuInitFailed = 1;
+			}
+			sleep(5);
+			system("reboot -f");
+			sleep(5);
+			system("reboot -f");
+		}
+		PtrBuf = (byte *) buf;
+		ChkSum = 0;
+		for (wrd = 0; wrd < (sizeof(struct SysConfigData) - 4); wrd++)
+		{
+			ChkSum += PtrBuf[wrd];
+		}
+		ChkSumOrg = buf->Checksum;
+		if (ChkSum != ChkSumOrg)
+		{
+			#ifdef SystemLogMessage
+			StoreLogMsg("[main]LoadSysConfigAndInfo: backup SysConfigData checksum NG, read Factory default");
+			#endif
+			fd = open("/dev/mtdblock12", O_RDWR);
+			if (fd < 0)
+			{
+				free(buf);
+				#ifdef SystemLogMessage
+				StoreLogMsg("[main]LoadSysConfigAndInfo: open mtdblock12 (Factory default) NG,rebooting..");
+				#endif
+				if (ShmStatusCodeData != NULL)
+				{
+					ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CsuInitFailed = 1;
+				}
+				sleep(5);
+				system("reboot -f");
+				sleep(5);
+				system("reboot -f");
+			}
+			memset(buf, 0, sizeof(struct SysConfigData));
+			wrd = read(fd, buf, sizeof(struct SysConfigData));
+			close(fd);
+			if (wrd != sizeof(struct SysConfigData))
+			{
+				free(buf);
+				#ifdef SystemLogMessage
+				StoreLogMsg("[main]LoadSysConfigAndInfo: read factory default  SysConfigData data NG,rebooting..");
+				#endif
+				if (ShmStatusCodeData != NULL)
+				{
+					ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CsuInitFailed = 1;
+				}
+				sleep(5);
+				system("reboot -f");
+				sleep(5);
+				system("reboot -f");
+			}
+			PtrBuf = (byte *) buf;
+			ChkSum = 0;
+			for (wrd = 0; wrd < (sizeof(struct SysConfigData) - 4); wrd++)
+			{
+				ChkSum += PtrBuf[wrd];
+			}
+			ChkSumOrg = buf->Checksum;
+			if (ChkSum != ChkSumOrg)
+			{
+				#ifdef SystemLogMessage
+				StoreLogMsg("[main]LoadSysConfigAndInfo: factory default  SysConfigData checksum NG, restore factory default");
+				#endif
+				goto DefaultShm;
+			}
+		}
+	}
+	//load OK
+	memcpy((struct SysConfigData *) ptr, (struct SysConfigData *) buf,	sizeof(struct SysConfigData));
+	free(buf);
+	#ifdef SystemLogMessage
+	StoreLogMsg("[main]LoadSysConfigAndInfo: Load SysConfigData OK");
+	#endif
+	return 1;
+
+	DefaultShm: system("cd /root;./FactoryConfig");
+	system("sync");
+	sleep(5);
+	system("reboot -f");
+	sleep(5);
+	system("reboot -f");
+	return FAIL;
+}
+
+void InitEthernet()
+{
+	char tmpbuf[256];
+	// /sbin/ifconfig eth0 192.168.1.10 netmask 255.255.255.0 down
+	system("echo 1 > /sys/class/gpio/gpio110/value");//reset PHY
+	sleep(2);
+	//Init Eth0 for internet
+	return;
+	memset(tmpbuf,0,256);
+	sprintf(tmpbuf,"/sbin/ifconfig eth0 %s netmask %s up",
+	ShmSysConfigAndInfo->SysConfig.Eth0Interface.EthIpAddress,
+	ShmSysConfigAndInfo->SysConfig.Eth0Interface.EthSubmaskAddress);
+	system(tmpbuf);
+	memset(tmpbuf,0,256);
+	sprintf(tmpbuf,"route add default gw %s eth0 ",
+	ShmSysConfigAndInfo->SysConfig.Eth0Interface.EthGatewayAddress);
+    system(tmpbuf);
+
+    //Init Eth1 for administrator tool
+	memset(tmpbuf,0,256);
+	sprintf(tmpbuf,"/sbin/ifconfig eth1 %s netmask %s up",
+	ShmSysConfigAndInfo->SysConfig.Eth1Interface.EthIpAddress,
+	ShmSysConfigAndInfo->SysConfig.Eth1Interface.EthSubmaskAddress);
+	system(tmpbuf);
+
+    //Run DHCP client if enabled
+	system("killall udhcpc");
+	system("rm -rf /etc/resolv.conf");
+	system("echo nameserver 8.8.8.8 > /etc/resolv.conf");		//Google DNS server
+	system("echo nameserver 180.76.76.76 > /etc/resolv.conf");	//Baidu DNS server
+	if(ShmSysConfigAndInfo->SysConfig.Eth0Interface.EthDhcpClient==0)
+		system("/sbin/udhcpc -i eth0 -s /root/simple.script > /dev/null &");
+
+	#ifdef SystemLogMessage
+	StoreLogMsg("[main]InitEthernet: Initial Ethernet OK");
+	#endif
+}
+
+int InitialRfidPort()
+{
+	int uartO2 = open(rfidPortName, O_RDWR);
+	struct termios tios;
+
+	if (uartO2 != FAIL)
+	{
+		ioctl (uartO2, TCGETS, &tios);
+		tios.c_cflag = B19200 | 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(uartO2, TCIFLUSH);
+		ioctl(uartO2, TCSETS, &tios);
+	}
+
+	if (uartO2 < 0)
+	{
+		ShmStatusCodeData->AlarmCode.AlarmEvents.bits.RfidModuleCommFail = 1;
+	}
+
+	return uartO2;
+}
+
+int Initialization()
+{
+	//InitGPIO();
+	//LoadSysConfigAndInfo(&ShmSysConfigAndInfo->SysConfig);
+	//InitEthernet();
+
+	sprintf((char *)ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomApn, "Internet");
+	sprintf((char *)ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomChapPapId, " ");
+	sprintf((char *)ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomChapPapPwd, " ");
+
+	// 初始化卡號驗證的 Flag
+	ClearAuthorizedFlag();
+	// 初始化插槍驗證的 Flag
+	ClearDetectPluginFlag();
+
+	// UART 2 for Rfid
+	rfidFd = InitialRfidPort();
+
+	memset(ShmSysConfigAndInfo->SysInfo.FanModuleFwRev, 0, ARRAY_SIZE(ShmSysConfigAndInfo->SysInfo.FanModuleFwRev));
+	memset(ShmSysConfigAndInfo->SysInfo.RelayModuleFwRev, 0, ARRAY_SIZE(ShmSysConfigAndInfo->SysInfo.RelayModuleFwRev));
+	ShmPrimaryMcuData->SelfTest_Comp = NO;
+	ShmRelayModuleData->SelfTest_Comp = NO;
+	ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_NONE;
+
+	for (byte count = 0; count < _gunCount; count++)
+	{
+		if (chargingInfo[count]->Type == _Type_Chademo)
+		{
+			ShmCHAdeMOData->evse[chargingInfo[count]->type_index].SelfTest_Comp = NO;
+		}
+		else if (chargingInfo[count]->Type == _Type_CCS)
+		{
+			if (ShmCcsData->CommProtocol == 0x01)
+			{
+				ShmCcsData->V2GMessage_DIN70121[chargingInfo[count]->type_index].SelfTest_Comp = NO;
+			}
+		}
+	}
+
+	#ifdef SystemLogMessage
+	printf("Initialization OK \n");
+	#endif
+
+	return PASS;
+}
+
+void SelfTestRun()
+{
+	bool evInitFlag = false;
+
+	StartSystemTimeoutDet(Timeout_SelftestChk);
+	ShmSysConfigAndInfo->SysInfo.SelfTestSeq = _STEST_VERSION;
+	while (ShmSysConfigAndInfo->SysInfo.SelfTestSeq != _STEST_COMPLETE)
+	{
+		ChkPrimaryStatus();
+		if (ShmSysConfigAndInfo->SysStopChargingAlarmCode.Level == 2)
+		{
+			ShmSysConfigAndInfo->SysInfo.SelfTestSeq = _STEST_FAIL;
+			return;
+		}
+
+		if (_gunCount > 0)
+		{
+			if (ShmPsuData->Work_Step == _NO_WORKING)
+			{
+				ShmSysConfigAndInfo->SysInfo.SelfTestSeq = _STEST_FAIL;
+				break;
+			}
+
+			switch(ShmSysConfigAndInfo->SysInfo.SelfTestSeq)
+			{
+				case _STEST_VERSION:
+				{
+					// RB Version
+					if (strlen((char *)ShmSysConfigAndInfo->SysInfo.RelayModuleFwRev) != 0 ||
+							ShmSysConfigAndInfo->SysInfo.RelayModuleFwRev[0] != '\0')
+					{
+						//printf("RB pass \n");
+						ShmRelayModuleData->SelfTest_Comp = YES;
+					}
+					// 407 Version
+					if (strlen((char *)ShmPrimaryMcuData->version) != 0 ||
+							ShmPrimaryMcuData->version[0] != '\0')
+					{
+						//printf("407 pass \n");
+						ShmPrimaryMcuData->SelfTest_Comp = YES;
+					}
+					// EV 小板
+					if (!evInitFlag)
+					{
+						evInitFlag = YES;
+						for (byte index = 0; index < _gunCount; index++)
+						{
+							if (chargingInfo[index]->Type == _Type_Chademo)
+							{
+								if (strlen((char *)ShmCHAdeMOData->evse[chargingInfo[index]->type_index].version) != 0 ||
+										ShmCHAdeMOData->evse[chargingInfo[index]->type_index].version[0] != '\0')
+								{
+									//printf("chademo pass \n");
+									ShmCHAdeMOData->evse[chargingInfo[index]->type_index].SelfTest_Comp = YES;
+								}
+								else
+								{
+									printf("chademo fw lose...... \n");
+									evInitFlag = NO;
+								}
+							}
+							else if (chargingInfo[index]->Type == _Type_CCS)
+							{
+								if (ShmCcsData->CommProtocol == 0x01)
+								{
+									if (strlen((char *)ShmCcsData->V2GMessage_DIN70121[chargingInfo[index]->type_index].version) != 0 ||
+										ShmCcsData->V2GMessage_DIN70121[chargingInfo[index]->type_index].version[0] != '\0')
+									{
+										ShmCcsData->V2GMessage_DIN70121[chargingInfo[index]->type_index].SelfTest_Comp = YES;
+									}
+									else
+									{
+										printf("ccs fw lose \n");
+										evInitFlag = NO;
+									}
+								}
+							}
+						}
+					}
+
+					if (ShmRelayModuleData->SelfTest_Comp && ShmPrimaryMcuData->SelfTest_Comp && evInitFlag)
+					{
+						ShmSysConfigAndInfo->SysInfo.SelfTestSeq = _STEST_AC_CONTACTOR;
+					}
+				}
+					break;
+				case _STEST_AC_CONTACTOR:
+				{
+					//ShmPsuData->Work_Step = _TEST_COMPLETE;
+					// 因為 30KW 以下沒有 Relay feedback 功能,所以暫時先直接跳過
+					if (ShmSysConfigAndInfo->SysInfo.AcContactorStatus == YES)
+					{
+						ShmSysConfigAndInfo->SysInfo.SelfTestSeq = _STEST_PSU_DETECT;
+						printf("Communication board pass. \n");
+					}
+				}
+					break;
+				case _STEST_PSU_DETECT:
+				{
+					// 此測試主要測試 PSU 對應是否為正確的火線上電壓
+					// 如果沒有 PSU 模組請 bypass
+					if (ShmPsuData->Work_Step == _TEST_POWER_STEP || ShmPsuData->Work_Step == _TEST_COMPLETE)
+					{
+						ShmSysConfigAndInfo->SysInfo.SelfTestSeq = _STEST_PSU_CAP;
+					}
+				}
+					break;
+				case _STEST_PSU_CAP:
+				{
+					// 此測試是要確認當前總輸出能力
+					// 如果沒有 PSU 模組請 bypass
+					if (ShmPsuData->Work_Step == _TEST_COMPLETE)
+					{
+						sleep(1);
+						ShmSysConfigAndInfo->SysInfo.SelfTestSeq = _STEST_COMPLETE;
+						ShmSysConfigAndInfo->SysInfo.BootingStatus = BOOT_COMPLETE;
+					}
+				}
+					break;
+			}
+		}
+		else
+			break;
+
+		usleep(100000);
+	}
+}
+
+int SpawnTask()
+{
+	system("/root/Module_EventLogging &");
+	system("/root/Module_PrimaryComm &");
+	system("/root/Module_EvComm &");
+	system("/root/Module_LcmControl &");
+	system("/root/Module_InternalComm &");
+	system("/root/Module_PsuComm &");
+
+	//system("/root/OcppBackend &");
+	//system("/root/Module_4g &");
+	//system("/root/Module_Wifi &");
+	//system("/root/Module_PsuComm &");
+	//system("/root/InfyPowerPsu_Comm &");
+
+	// 加入參數
+//	char str[64];
+//	memset(str, '\0', sizeof(65));
+//	sprintf(str, "/root/Module_EvComm %x &", (CHAdeMO_QUANTITY + CCS_QUANTITY));
+//	printf("%s \n", str);
+//	system(str);
+
+	return PASS;
+}
+
+int StoreUsrConfigData(struct SysConfigData *UsrData)
+{
+	int fd,wrd;
+	unsigned int i, Chk;
+	byte *ptr;
+
+	Chk = 0;
+	ptr = (byte *) UsrData;
+	for (i = 0; i < sizeof(struct SysConfigData) - 4; i++)
+	{
+		Chk += *(ptr + i);
+	}
+	UsrData->Checksum = Chk;
+
+	fd = open("/dev/mtdblock10", O_RDWR);
+	if (fd < 0)
+	{
+		#ifdef SystemLogMessage
+		StoreLogMsg("[main]StoreUsrConfigData: open /dev/mtdblock10 NG");
+		#endif
+		return 0;
+	}
+	wrd = write(fd, UsrData, sizeof(struct SysConfigData));
+	close(fd);
+	if (wrd != (sizeof(struct SysConfigData)))
+	{
+		#ifdef SystemLogMessage
+		StoreLogMsg("[main]StoreUsrConfigData: write /dev/mtdblock10 NG");
+		#endif
+		return 0;
+	}
+
+	fd = open("/dev/mtdblock11", O_RDWR);
+	if (fd < 0)
+	{
+		#ifdef SystemLogMessage
+		StoreLogMsg("[main]StoreUsrConfigData: open /dev/mtdblock11(backup) NG");
+		#endif
+		return 0;
+	}
+	wrd = write(fd, UsrData, sizeof(struct SysConfigData));
+	close(fd);
+	if (wrd != (sizeof(struct SysConfigData)))
+	{
+		#ifdef SystemLogMessage
+		StoreLogMsg("[main]StoreUsrConfigData: write /dev/mtdblock11(backup) NG");
+		#endif
+		return 0;
+	}
+	return 1;
+}
+
+//===============================================
+// Common Detect Chk - Stop Charging ?
+//===============================================
+bool isEvBoardStopChargeFlag(byte gunIndex)
+{
+	return chargingInfo[gunIndex]->StopChargeFlag;
+}
+
+//===============================================
+// Common Detect Chk - Chademo
+//===============================================
+bool isEvGunLocked_chademo(byte gunIndex)
+{
+	return (DetectBitValue(chargingInfo[gunIndex]->GunLocked , 0) == 0)? NO : YES;
+}
+
+bool isEvContactorWelding_chademo(byte gunIndex)
+{
+	return DetectBitValue(ShmCHAdeMOData->ev[chargingInfo[gunIndex]->type_index].EvDetection, 3);
+}
+
+bool isEvStopReq_chademo(byte gunIndex)
+{
+	return DetectBitValue(ShmCHAdeMOData->ev[chargingInfo[gunIndex]->type_index].EvDetection, 4);
+}
+
+bool isEvStopCharging_chademo(byte gunIndex)
+{
+	if (isEvGunLocked_chademo(gunIndex) == NO)
+	{
+		// 無鎖槍 = 停止
+		printf("gun locked none. \n");
+		return YES;
+	}
+
+	return NO;
+}
+
+byte isPrechargeStatus_chademo(byte gunIndex)
+{
+	byte result = 0x00;
+
+	result = ShmCHAdeMOData->ev[chargingInfo[gunIndex]->type_index].PresentMsgFlowStatus;
+
+	return result;
+}
+//===============================================
+// Common Detect Chk - CCS
+//===============================================
+bool isEvGunLocked_ccs(byte gunIndex)
+{
+	return (DetectBitValue(chargingInfo[gunIndex]->GunLocked , 0) == 0)? NO : YES;
+}
+
+byte isPrechargeStatus_ccs(byte gunIndex)
+{
+	byte result = 0x00;
+
+	if (ShmCcsData->CommProtocol == 0x01)
+	{
+		result = ShmCcsData->V2GMessage_DIN70121[chargingInfo[gunIndex]->type_index].PresentMsgFlowStatus;
+	}
+
+	return result;
+}
+
+bool isEvStopCharging_ccs(byte gunIndex)
+{
+	if (isEvGunLocked_ccs(gunIndex) == NO)
+	{
+		// 無鎖槍 = 停止
+		printf("gun locked none. \n");
+		return YES;
+	}
+
+	return NO;
+}
+
+//===============================================
+// Callback
+//===============================================
+void _AutoReturnTimeout()
+{
+	if (ShmSysConfigAndInfo->SysInfo.PageIndex == _LCM_WAIT_FOR_PLUG)
+	{
+		ClearDetectPluginFlag();
+	}
+
+	ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_NONE;
+//
+//	for (byte i = 0; i < CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY; i++)
+//	{
+//		if (chargingInfo[i]->SystemStatus > S_IDLE)
+//		{
+//			switch(chargingInfo[i]->SystemStatus)
+//			{
+//				case S_PREPARNING:
+//				case S_PREPARING_FOR_EV:
+//				case S_PREPARING_FOR_EVSE:
+//				{
+//					ChangeLcmByIndex(i, _LCM_PRE_CHARGE);
+//				}
+//					break;
+//				case S_CHARGING:
+//				{
+//					ChangeLcmByIndex(i, _LCM_CHARGING);
+//				}
+//					break;
+//				case S_TERMINATING:
+//				{
+//					ChangeLcmByIndex(i, _LCM_COMPLETE);
+//				}
+//					break;
+//			}
+//			return;
+//		}
+//	}
+
+//	if (!IsAuthorizingMode())
+//		ChangeLcmByIndex(255, _LCM_IDLE);
+}
+
+void _SelfTestTimeout()
+{
+	if (ShmSysConfigAndInfo->SysInfo.BootingStatus != BOOT_COMPLETE)
+	{
+		for (byte gun_index = 0; gun_index < _gunCount; gun_index++)
+		{
+			setChargerMode(gun_index, MODE_ALARM);
+		}
+		ShmPsuData->Work_Step = _NO_WORKING;
+	}
+}
+
+void _AuthorizedTimeout()
+{
+	if(IsAuthorizingMode())
+	{
+		printf("_AuthorizedTimeout \n");
+		ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_AUTHORIZ_FAIL;
+		//ChangeLcmByIndex(_LCM_AUTHORIZ_FAIL);
+		ClearAuthorizedFlag();
+	}
+}
+
+void _DetectPlugInTimeout()
+{
+	if(isDetectPlugin())
+	{
+		printf("_DetectPlugInTimeout \n");
+		ClearDetectPluginFlag();
+	}
+	ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_NONE;
+}
+
+void _DetectEvChargingEnableTimeout(byte gunIndex)
+{
+	if (chargingInfo[gunIndex]->Type == _Type_Chademo)
+	{
+		if(!isEvGunLocked_chademo(gunIndex))
+		{
+			printf("_DetectEvChargingEnableTimeout (chademo) \n");
+			ChargingTerminalProcess(gunIndex);
+			_AutoReturnTimeout();
+		}
+	}
+	else if (chargingInfo[gunIndex]->Type == _Type_CCS)
+	{
+		if(!isEvGunLocked_ccs(gunIndex))
+		{
+			printf("_DetectEvChargingEnableTimeout (ccs) \n");
+			ChargingTerminalProcess(gunIndex);
+			_AutoReturnTimeout();
+		}
+	}
+}
+
+void _DetectEvseChargingEnableTimeout(byte gunIndex)
+{
+	printf("_DetectEvseChargingEnableTimeout (GFD timeout) \n");
+	if (chargingInfo[gunIndex]->GroundFaultStatus != GFD_PASS)
+	{
+		setChargerMode(gunIndex, MODE_IDLE);
+		_AutoReturnTimeout();
+	}
+}
+
+void _PrepareTimeout(byte gunIndex)
+{
+	printf("_PrechargeTimeout \n");
+	setChargerMode(gunIndex, MODE_IDLE);
+	_AutoReturnTimeout();
+}
+
+void _CompleteTimeout(byte gunIndex)
+{
+	printf("_CompleteTimeout ====> %d \n", gunIndex);
+	setChargerMode(gunIndex, MODE_IDLE);
+}
+
+void _CcsPrechargeTimeout(byte gunIndex)
+{
+	printf("_CcsPrechargeTimeout \n");
+	setChargerMode(gunIndex, MODE_IDLE);
+}
+
+//===============================================
+// 取得卡號與卡號驗證
+//===============================================
+bool canStartCharging()
+{
+	char buf2[16] = "";
+	memset(buf2, 0, ARRAY_SIZE(buf2));
+
+	for (byte index = 0; index < strlen((char *)ShmOCPP16Data->Authorize.ResponseIdTagInfo.Status); index++)
+	{
+		sprintf(buf2 + (index - 1) * 2, "%02X",	ShmOCPP16Data->Authorize.ResponseIdTagInfo.Status[index]);
+	}
+	sprintf(buf2, "%s",	ShmOCPP16Data->Authorize.ResponseIdTagInfo.Status);
+
+	// 因為無法得知實際的長度,所以只能用搜尋的方式
+	if(strstr(buf2, "Accepted") != 0)
+		return true;
+	else
+	{
+
+	}
+
+	return false;
+}
+
+void AuthorizingStart()
+{
+	ShmOCPP16Data->SpMsg.bits.AuthorizeReq = YES;
+}
+
+void ClearAuthorizedFlag()
+{
+	ShmOCPP16Data->SpMsg.bits.AuthorizeReq = NO;
+	ShmOCPP16Data->SpMsg.bits.AuthorizeConf = NO;
+}
+
+bool isAuthorizedComplete()
+{
+	if (ShmOCPP16Data->SpMsg.bits.AuthorizeConf == NO)
+		return false;
+
+	return true;
+}
+
+bool IsAuthorizingMode()
+{
+	if(ShmOCPP16Data->SpMsg.bits.AuthorizeReq == NO)
+		return false;
+
+	return true;
+}
+
+byte GetCardNumber()
+{
+	byte card_number[16];
+
+	if (strlen((char *)ShmSysConfigAndInfo->SysConfig.UserId) == 0)
+	{
+		if(getRequestCardSN(rfidFd, 0, card_number))
+		{
+			//Get Card Number
+			byte len = card_number[0];
+			char buf2[32] = "";
+
+			memcpy(buf2, (card_number + 1), len);
+			memset(ShmSysConfigAndInfo->SysConfig.UserId, 0x0, ARRAY_SIZE(ShmSysConfigAndInfo->SysConfig.UserId));
+			for (byte index = 0; index < len; index++)
+			{
+				sprintf((char *)ShmSysConfigAndInfo->SysConfig.UserId + (index * 2), "%02X", buf2[index]);
+			}
+
+			printf("card number = %s\n", ShmSysConfigAndInfo->SysConfig.UserId);
+			return PASS;
+		}
+	}
+
+	return FAIL;
+}
+
+//===============================================
+// 掃描插槍狀況
+//===============================================
+void ClearDetectPluginFlag()
+{
+	ShmSysConfigAndInfo->SysInfo.WaitForPlugit = NO;
+}
+
+void DetectPluginStart()
+{
+	ShmSysConfigAndInfo->SysInfo.WaitForPlugit = YES;
+}
+
+bool isDetectPlugin()
+{
+	if(ShmSysConfigAndInfo->SysInfo.WaitForPlugit == YES)
+		return YES;
+
+	return NO;
+}
+
+//===============================================
+// EmergencyStop and Charging Stop
+//===============================================
+void ChargingTerminalProcess(byte gunIndex)
+{
+	setChargerMode(gunIndex, MODE_TERMINATING);
+}
+
+void StopChargingProcessByString(byte level, byte gun_index, char *string)
+{
+	if (strlen((char *)ShmSysConfigAndInfo->SysStopChargingAlarmCode.StopCode[gun_index]) == 0 ||
+		level > ShmSysConfigAndInfo->SysStopChargingAlarmCode.Level)
+	{
+		memcpy(&ShmSysConfigAndInfo->SysStopChargingAlarmCode.StopCode[gun_index][0], string, 7);
+		ShmSysConfigAndInfo->SysStopChargingAlarmCode.Level = level;
+	}
+}
+
+void ReleaseChargingProcessByString(byte gun_index, char *code)
+{
+	memcpy(&ShmSysConfigAndInfo->SysStopChargingAlarmCode.StopCode[gun_index][0], "", 7);
+	ShmSysConfigAndInfo->SysStopChargingAlarmCode.Level = 0;
+}
+
+// 各小板的停止充電處理函式
+void EmcOccureByString(byte index, char *code)
+{
+	bool isStopCharger = false;
+	if (strncmp(code, "012251", 6) == 0 || strncmp(code, "012252", 6) == 0 ||
+			strncmp(code, "012237", 6) == 0 || strncmp(code, "012238", 6) == 0)
+	{
+		isStopCharger = true;
+	}
+
+	if (isStopCharger)
+	{
+		for (byte gun = 0; gun < _gunCount; gun++)
+		{
+			if ((chargingInfo[gun]->SystemStatus > S_IDLE && chargingInfo[gun]->SystemStatus < S_TERMINATING) ||
+					(chargingInfo[gun]->SystemStatus >= S_CCS_PRECHARGE_ST0 && chargingInfo[gun]->SystemStatus <= S_CCS_PRECHARGE_ST1))
+			{
+				ChargingTerminalProcess(gun);
+			}
+
+			StopChargingProcessByString(2, gun, code);
+		}
+	}
+	else
+	{
+		if ((chargingInfo[index]->SystemStatus > S_IDLE && chargingInfo[index]->SystemStatus < S_TERMINATING) ||
+				(chargingInfo[index]->SystemStatus >= S_CCS_PRECHARGE_ST0 && chargingInfo[index]->SystemStatus <= S_CCS_PRECHARGE_ST1))
+		{
+			ChargingTerminalProcess(index);
+		}
+
+		StopChargingProcessByString(2, index, code);
+	}
+}
+
+void ReleaseEmsOccureByString(byte index, char *code)
+{
+	bool isReleaseCharger = false;
+	bool isTrigger = false;
+	if (strncmp(code, "012251", 6) == 0 && ShmStatusCodeData->AlarmCode.AlarmEvents.bits.EmergencyStopTrip == YES)
+	{
+		isTrigger = true;
+		ShmStatusCodeData->AlarmCode.AlarmEvents.bits.EmergencyStopTrip = NO;
+		isReleaseCharger = true;
+	}
+	else if (strncmp(code, "012252", 6) == 0 && ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DoorOpen == YES)
+	{
+		isTrigger = true;
+		ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DoorOpen = NO;
+		isReleaseCharger = true;
+	}
+	else if (strncmp(code, "012237", 6) == 0 && ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SpdTrip == YES)
+	{
+		isTrigger = true;
+		ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SpdTrip = NO;
+		isReleaseCharger = true;
+	}
+	else if (strncmp(code, "012238", 6) == 0 && ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MainPowerBreakerTrip == YES)
+	{
+		isTrigger = true;
+		ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MainPowerBreakerTrip = NO;
+		isReleaseCharger = true;
+	}
+	else if (strncmp(code, "023730", 6) == 0 && ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoChargerGetEmergencyStop == YES)
+	{
+		isTrigger = true;
+		ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoChargerGetEmergencyStop = NO;
+	}
+
+	if (isTrigger)
+	{
+		if (isReleaseCharger)
+		{
+			for (byte gun = 0; gun < _gunCount; gun++)
+			{
+				ReleaseChargingProcessByString(gun, code);
+			}
+		}
+		else
+		{
+			ReleaseChargingProcessByString(index, code);
+		}
+	}
+}
+
+//===============================================
+// 確認硬體 (按鈕) 狀態
+//===============================================
+bool leftBtnPush = false;
+bool rightBtnPush = false;
+
+void ChkPrimaryStatus()
+{
+	if (ShmPrimaryMcuData->InputDet.bits.EmergencyButton == ABNORMAL)
+	{
+		ShmStatusCodeData->AlarmCode.AlarmEvents.bits.EmergencyStopTrip = YES;
+		EmcOccureByString(0, "012251");
+	}
+	else
+		ReleaseEmsOccureByString(0, "012251");
+
+	if (ShmPrimaryMcuData->InputDet.bits.AcMainBreakerDetec == ABNORMAL)
+	{
+		ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MainPowerBreakerTrip = YES;
+		EmcOccureByString(0, "012238");
+	}
+	else
+		ReleaseEmsOccureByString(0, "012238");
+
+	if (ShmPrimaryMcuData->InputDet.bits.SpdDetec == ABNORMAL)
+	{
+		ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SpdTrip = YES;
+		EmcOccureByString(0, "012237");
+	}
+	else
+		ReleaseEmsOccureByString(0, "012237");
+
+	if (ShmPrimaryMcuData->InputDet.bits.DoorOpen == ABNORMAL)
+	{
+		ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DoorOpen = YES;
+		EmcOccureByString(0, "012252");
+	}
+	else
+		ReleaseEmsOccureByString(0, "012252");
+
+	if (ShmPrimaryMcuData->InputDet.bits.Button1 == BTN_PRESS && !leftBtnPush)
+	{
+		if(!leftBtnPush)
+		{
+			printf("left btn down............................... \n");
+			ShmSysConfigAndInfo->SysInfo.CurGunSelected = 0;
+			switch(chargingInfo[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus)
+			{
+				case S_IDLE:
+				{
+					ShmSysConfigAndInfo->SysInfo.WaitForPlugit = 0x01;
+				}
+				break;
+				case S_CHARGING:
+				{
+					// 停止充電
+					printf("To Stop = %d --------- \n", ShmSysConfigAndInfo->SysInfo.CurGunSelected);
+					chargingInfo[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus = 9;
+					//ChargingTerminalProcess(ShmSysConfigAndInfo->SysInfo.CurGunSelected);
+				}
+					break;
+				case S_COMPLETE:
+				{
+					// 回 IDLE
+					printf("Back to IDLE = %d --------- \n", ShmSysConfigAndInfo->SysInfo.CurGunSelected);
+					chargingInfo[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus = 1;
+				}
+					break;
+			}
+		}
+
+		leftBtnPush = true;
+		// 左邊的選槍按鈕,只有在雙槍都在充電時候才有用 : 30KW 以下該按鈕無作用
+	}
+	else if (ShmPrimaryMcuData->InputDet.bits.Button1 == BTN_RELEASE)
+	{
+		if(leftBtnPush)
+			printf("left btn up............................... \n");
+		leftBtnPush = false;
+	}
+
+	if (ShmPrimaryMcuData->InputDet.bits.Button2 == BTN_PRESS && !rightBtnPush)
+	{
+		if(!rightBtnPush)
+		{
+			printf("right btn down............................... \n");
+			if (_gunCount > 1)
+			{
+				ShmSysConfigAndInfo->SysInfo.CurGunSelected = 1;
+				switch(chargingInfo[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus)
+				{
+					case S_IDLE:
+					{
+						ShmSysConfigAndInfo->SysInfo.WaitForPlugit = 0x01;
+					}
+					break;
+					case S_CHARGING:
+					{
+						// 停止充電
+						printf("To Stop = %d --------- \n", ShmSysConfigAndInfo->SysInfo.CurGunSelected);
+						chargingInfo[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus = 9;
+						//ChargingTerminalProcess(ShmSysConfigAndInfo->SysInfo.CurGunSelected);
+					}
+						break;
+					case S_COMPLETE:
+					{
+						// 回 IDLE
+						printf("Back to IDLE = %d --------- \n", ShmSysConfigAndInfo->SysInfo.CurGunSelected);
+						chargingInfo[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus = 1;
+					}
+						break;
+				}
+			}
+		}
+
+		rightBtnPush = true;
+		// 右邊的按鈕,只作用在當前頁面,當前頁面如果在可以回 Home 與 停止充電的狀態為可用
+//		switch(chargingInfo[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->SystemStatus)
+//		{
+//			case S_IDLE: {}break;
+//			case S_AUTHORIZING: {}break;
+//			case S_PREPARING_FOR_EV: {}break;
+//			case S_PREPARING_FOR_EVSE: {}break;
+//			case S_CCS_PRECHARGE_ST0: {}break;
+//			case S_CCS_PRECHARGE_ST1: {}break;
+//			case S_CHARGING:
+//			{
+//				// 停止充電
+//				printf("Stop --------------------------------------------------- \n");
+//				//ChargingTerminalProcess(ShmSysConfigAndInfo->SysInfo.CurGunSelected);
+//			}
+//				break;
+//			case S_COMPLETE:
+//			{
+//				//setChargerMode(ShmSysConfigAndInfo->SysInfo.CurGunSelected, MODE_IDLE);
+//			}
+//				break;
+//		}
+	}
+	else if (ShmPrimaryMcuData->InputDet.bits.Button2 == BTN_RELEASE)
+	{
+		if(rightBtnPush)
+			printf("right btn up............................... \n");
+		rightBtnPush = false;
+	}
+}
+
+//===============================================
+// 確認各小板偵測的錯誤狀況
+//===============================================
+void CheckErrorOccurStatus(byte index)
+{
+	// 小板
+	if (chargingInfo[index]->Type == _Type_Chademo)
+	{
+		if (ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoChargerGetEmergencyStop == YES)
+			EmcOccureByString(index, "023730");
+		else if (ShmStatusCodeData->FaultCode.FaultEvents.bits.ChademoOutputRelayDrivingFault == YES)
+			EmcOccureByString(index, "011012");
+		else if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.ChademoGfdTrip == YES)
+			EmcOccureByString(index, "012234");
+	}
+	else if (chargingInfo[index]->Type == _Type_CCS)
+	{
+		if (ShmStatusCodeData->FaultCode.FaultEvents.bits.CcsOutputRelayDrivingFault == YES)
+			EmcOccureByString(index, "011014");
+		else if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CcsGfdTrip == YES)
+			EmcOccureByString(index, "012235");
+	}
+}
+
+//===============================================
+// 確認 GPIO 狀態
+//===============================================
+int gpio_get_value(unsigned int gpio, unsigned int *value)
+{
+    int fd;
+    char buf[MAX_BUF];
+    char ch;
+
+    snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);
+
+    fd = open(buf, O_RDONLY);
+    if (fd < 0) {
+        perror("gpio/get-value");
+        return fd;
+    }
+
+    read(fd, &ch, 1);
+
+    if (ch != '0') {
+        *value = 1;
+    } else {
+        *value = 0;
+    }
+
+    close(fd);
+    return 0;
+}
+
+void 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;
+			}
+		}
+	}
+}
+
+void CheckGpioInStatus()
+{
+	int pinIn[2] = { 27, 47 };
+	unsigned int gpioValue = 0;
+
+	for (int i = 0; i < ARRAY_SIZE(pinIn); i++)
+	{
+		gpio_get_value(pinIn[i], &gpioValue);
+		if (gpioValue == 0x01)
+		{
+			switch(pinIn[i])
+			{
+				// 小板緊急停止
+				case 27:
+				{
+					for(int i = 0; i < _gunCount; i++)
+					{
+						if (chargingInfo[i]->slotsIndex == 1)
+						{
+							if (chargingInfo[i]->Type == _Type_Chademo)
+								EmcOccureByString(i, "023730");
+							else if (chargingInfo[i]->Type == _Type_CCS)
+								EmcOccureByString(i, "013627");
+							break;
+						}
+					}
+				}
+					break;
+				case 47:
+				{
+					for(int i = 0; i < _gunCount; i++)
+					{
+						if (chargingInfo[i]->slotsIndex == 3)
+						{
+							if (chargingInfo[i]->Type == _Type_Chademo)
+								EmcOccureByString(i, "023730");
+							else if (chargingInfo[i]->Type == _Type_CCS)
+								EmcOccureByString(i, "013627");
+							break;
+						}
+					}
+				}
+					break;
+			}
+		}
+		else
+		{
+			switch (pinIn[i])
+			{
+				// 小板解除緊急停止
+				case 27:
+				{
+					for(int i = 0; i < _gunCount; i++)
+					{
+						if (chargingInfo[i]->slotsIndex == 1)
+						{
+							if (chargingInfo[i]->Type == _Type_Chademo)
+								ReleaseEmsOccureByString(i, "023730");
+							else if (chargingInfo[i]->Type == _Type_CCS)
+								ReleaseEmsOccureByString(i, "013627");
+							break;
+						}
+					}
+				}
+					break;
+				case 47:
+				{
+					// 右槍
+					for (int i = 0; i < _gunCount; i++)
+					{
+						if (chargingInfo[i]->slotsIndex == 3)
+						{
+							if (chargingInfo[i]->Type == _Type_Chademo)
+								ReleaseEmsOccureByString(i, "023730");
+							else if (chargingInfo[i]->Type == _Type_CCS)
+								ReleaseEmsOccureByString(i, "013627");
+							break;
+						}
+					}
+				}
+				break;
+			}
+		}
+	}
+}
+
+//===============================================
+// Main process
+//===============================================
+// 檢查 Byte 中某個 Bit 的值
+// _byte : 欲改變的 byte
+// _bit : 該 byte 的第幾個 bit
+unsigned char DetectBitValue(unsigned char _byte, unsigned char _bit)
+{
+	return ( _byte & mask_table[_bit] ) != 0x00;
+}
+
+// 設定 Byte 中某個 Bit的值
+// _byte : 欲改變的 byte
+// _bit : 該 byte 的第幾個 bit
+// value : 修改的值為 0 or 1
+void SetBitValue(unsigned char *_byte, unsigned char _bit, unsigned char value)
+{
+	if(value == 1)
+		*_byte |= (1 << _bit);
+	else if (value == 0)
+		*_byte ^= (1 << _bit);
+}
+
+void UserScanFunction()
+{
+	bool idleReq = false;
+	unsigned char stopReq = 255;
+
+	// 當前非驗證的狀態
+	if(!IsAuthorizingMode())
+	{
+		// 先判斷現在是否可以提供刷卡
+		// 1. 如果當前沒有槍是閒置狀態,則無提供刷卡功能
+		// 2. 停止充電
+		for (byte i = 0; i < _gunCount; i++)
+		{
+			// 二擇一
+			if (chargingInfo[i]->SystemStatus == S_CHARGING)
+			{
+				stopReq = i;
+			}
+			else if (chargingInfo[i]->SystemStatus == S_IDLE)
+			{
+				idleReq = true;
+			}
+		}
+
+		//printf("idleReq = %x, stopReq = %d \n", idleReq, stopReq);
+		// 有閒置的槍號,即可接受刷卡
+		if (idleReq || stopReq < _gunCount)
+		{
+			// 取卡號,假設 : 刷卡過了
+			if (strlen((char *)ShmSysConfigAndInfo->SysConfig.UserId) > 0)
+			{
+				if (stopReq < _gunCount)
+				{
+					char value[32];
+
+					memcpy(value, (unsigned char *)chargingInfo[stopReq]->CardNumber, ARRAY_SIZE(chargingInfo[stopReq]->CardNumber));
+					if (strcmp((char *)ShmSysConfigAndInfo->SysConfig.UserId, value) == EQUAL)
+					{
+						ChargingTerminalProcess(stopReq);
+						strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+						return;
+					}
+				}
+
+				if (idleReq)
+				{
+					// LCM => Authorizing
+					ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_AUTHORIZING;
+					//ChangeLcmByIndex(_LCM_AUTHORIZING);
+					// 進入確認卡號狀態
+					AuthorizingStart();
+					// authorizing timer
+					StartSystemTimeoutDet(Timeout_Authorizing);
+					autoReturnTimeoutFlag = NO;
+				}
+			}
+		}
+	}
+	else
+	{
+		// 確認驗證卡號完成沒
+		if (isAuthorizedComplete() || true)
+		{
+			StopSystemTimeoutDet();
+			// 判斷後台回覆狀態
+			if(canStartCharging() || true)
+			{
+				// LCM => Authorize complete
+				ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_AUTHORIZ_COMP;
+				//ChangeLcmByIndex(_LCM_AUTHORIZ_COMP);
+				// 通過認證,開始確認當前要進入充電的槍號
+				DetectPluginStart();
+			}
+			else
+			{
+				// LCM => Authorize fail
+				ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_AUTHORIZ_FAIL;
+				//ChangeLcmByIndex(_LCM_AUTHORIZ_FAIL);
+			}
+			ClearAuthorizedFlag();
+		}
+	}
+}
+
+unsigned char isModeChange(unsigned char gun_index)
+{
+	unsigned char result = NO;
+
+	if(chargingInfo[gun_index]->SystemStatus != chargingInfo[gun_index]->PreviousSystemStatus)
+	{
+		result = YES;
+		chargingInfo[gun_index]->PreviousSystemStatus = chargingInfo[gun_index]->SystemStatus;
+	}
+
+	return result;
+}
+
+void ScannerCardProcess()
+{
+	if (!isDetectPlugin() && !isCardScan && ShmSysConfigAndInfo->SysStopChargingAlarmCode.Level == 0)
+	{
+		isCardScan = true;
+		// 處理刷卡及驗證卡號的動作
+		UserScanFunction();
+	}
+
+	if (ShmSysConfigAndInfo->SysInfo.PageIndex == _LCM_AUTHORIZ_FAIL)
+	{
+		StartSystemTimeoutDet(Timeout_VerifyFail);
+		isCardScan = false;
+	}
+	else if(ShmSysConfigAndInfo->SysInfo.PageIndex == _LCM_AUTHORIZ_COMP)
+	{
+		StartSystemTimeoutDet(Timeout_VerifyComp);
+	}
+	else if(ShmSysConfigAndInfo->SysInfo.PageIndex == _LCM_WAIT_FOR_PLUG)
+	{
+		StartSystemTimeoutDet(Timeout_WaitPlug);
+	}
+	else
+		isCardScan = false;
+}
+
+void AddGunInfoByConnector(byte typeValue, byte slots)
+{
+	switch (typeValue)
+	{
+		case '0': // none
+			break;
+		case '1': // IEC 62196-2 Type 1/SAE J1772 Plug
+			break;
+		case '2': // IEC 62196-2 Type 1/SAE J1772 Socket
+			break;
+		case '3': // IEC 62196-2 Type 2 Plug
+			break;
+		case '4': // IEC 62196-2 Type 2 Socket
+			break;
+		case '5': // GB/T AC Plug
+			break;
+		case '6': // GB/T AC Socket
+			break;
+		case 'J': // CHAdeMO
+		{
+			if (CHAdeMO_QUANTITY > _chademoIndex)
+			{
+				chargingInfo[_gunIndex] = &ShmSysConfigAndInfo->SysInfo.ChademoChargingData[_chademoIndex];
+
+				chargingInfo[_gunIndex]->Index = _gunIndex;
+				chargingInfo[_gunIndex]->slotsIndex = slots;
+				chargingInfo[_gunIndex]->SystemStatus = S_BOOTING;
+				chargingInfo[_gunIndex]->Type = _Type_Chademo;
+				chargingInfo[_gunIndex]->type_index = _chademoIndex;
+				_chademoIndex++;
+				_gunIndex++;
+			}
+		}
+			break;
+		case 'U': // CCS1 combo
+			break;
+		case 'E': // CCS2 combo
+		{
+			if (CCS_QUANTITY > _ccsIndex)
+			{
+				chargingInfo[_gunIndex] = &ShmSysConfigAndInfo->SysInfo.CcsChargingData[_ccsIndex];
+
+				chargingInfo[_gunIndex]->Index =	_gunIndex;
+				chargingInfo[_gunIndex]->slotsIndex = slots;
+				chargingInfo[_gunIndex]->SystemStatus = S_BOOTING;
+				chargingInfo[_gunIndex]->Type = _Type_CCS;
+				chargingInfo[_gunIndex]->type_index = _ccsIndex;
+				// 現階段預設為走 DIN70121
+				ShmCcsData->CommProtocol = 0x01;
+				_ccsIndex++;
+				_gunIndex++;
+			}
+		}
+			break;
+		case 'G': // GBT DC
+			break;
+		case 'D': // GBT DC x 2
+			break;
+	}
+}
+
+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);
+	if (strlen((char *) ShmSysConfigAndInfo->SysConfig.ModelName) >= 9)
+	{
+		byte slots = 1;
+		for (byte typeIndex = 7; typeIndex <= 9; typeIndex++)
+		{
+			AddGunInfoByConnector(ShmSysConfigAndInfo->SysConfig.ModelName[typeIndex], slots);
+			slots++;
+		}
+
+		_gunCount = _gunIndex;
+		printf("_gunCount = %d \n", _gunCount);
+		if (_gunCount == 0)
+			result = false;
+
+		// 偵測槍屬於哪個 slot : 可知道插在板上的Slot 0 或 1 是 Chademo 還是 CCS
+		for (byte gunIndex = 0; gunIndex < _gunCount; gunIndex++)
+		{
+			if (bd0_1_status == 0 && bd0_2_status == 1)
+			{
+				// 與硬體相同 type : Chademo
+				if (chargingInfo[gunIndex]->Type == _Type_Chademo)
+				{
+					chargingInfo[gunIndex]->Evboard_id = 0x01;
+				}
+			}
+			else if (bd0_1_status == 1 && bd0_2_status == 0)
+			{
+				// 與硬體相同 type : CCS
+				if (chargingInfo[gunIndex]->Type == _Type_CCS)
+				{
+					chargingInfo[gunIndex]->Evboard_id = 0x01;
+				}
+			}
+
+			if (bd1_1_status == 0 && bd1_2_status == 1)
+			{
+				// 與硬體相同 type : Chademo
+				if (chargingInfo[gunIndex]->Type == _Type_Chademo)
+				{
+					chargingInfo[gunIndex]->Evboard_id = 0x02;
+				}
+
+				if (_gunCount == 1)
+					chargingInfo[gunIndex]->Evboard_id = 0x01;
+			}
+			else if (bd1_1_status == 1 && bd1_2_status == 0)
+			{
+				// 與硬體相同 type : CCS
+				if (chargingInfo[gunIndex]->Type == _Type_CCS)
+				{
+					chargingInfo[gunIndex]->Evboard_id = 0x02;
+				}
+
+				if (_gunCount == 1)
+					chargingInfo[gunIndex]->Evboard_id = 0x01;
+			}
+
+			printf("index = %d, Type = %d, Evboard_id = %d \n", gunIndex, chargingInfo[gunIndex]->Type, chargingInfo[gunIndex]->Evboard_id);
+			if (chargingInfo[gunIndex]->Evboard_id == 0x00)
+				result = false;
+		}
+	}
+	else
+	{
+		// Module Name 不正確 - 告警
+		result = false;
+	}
+
+	return result;
+}
+
+void KillTask()
+{
+	ChangeLcmByIndex(_LCM_FIX);
+	system("killall Module_EventLogging");
+	system("killall Module_PrimaryComm");
+	system("killall Module_EvComm");
+	system("killall Module_LcmControl");
+	system("killall Module_InternalComm");
+	system("killall Module_PsuComm");
+}
+
+char CheckUpdateProcess()
+{
+	DIR *d;
+	struct dirent *dir;
+	d = opendir("/mnt/");
+
+	if (d)
+	{
+		long int MaxLen=48*1024*1024, ImageLen = 0;
+		while ((dir = readdir(d)) != NULL)
+		{
+			char *new_str;
+			new_str = malloc(strlen("/mnt/")+strlen(dir->d_name)+1);
+			new_str[0] = '\0';
+			strcat(new_str, "/mnt/");
+			strcat(new_str, dir->d_name);
+			int fd = open(new_str, O_RDONLY);
+			if (fd < 0)
+			{
+				return FAIL;
+			}
+
+			unsigned char *ptr = malloc(MaxLen); //-48 is take out the header
+			memset(ptr, 0xFF, MaxLen);  //-48 is take out the header
+			//get the image length
+			ImageLen = read(fd, ptr, MaxLen);
+
+			if (ImageLen > 20)
+			{
+				unsigned int Type = (((unsigned int)ptr[16])<<24 | ((unsigned int)ptr[17])<<16 | ((unsigned int)ptr[18])<<8 | ((unsigned int)ptr[19]));
+			    printf("Typed...%x \r\n", Type);
+
+			    switch (Type)
+			    {
+			    	case 0x10000001:
+			    	case 0x10000002:
+			    	case 0x10000003:
+			    	case 0x10000004:
+			    	case 0x10000005:
+			    	case 0x10000006:
+			    	{
+			    		// CSU_PRIMARY_CONTROLLER : 0x10000006
+			    		int fd = InitComPort(0x04);
+
+			    		if (Upgrade_UART(fd, Type, 0x04, new_str, ShmSysConfigAndInfo) == PASS)
+			    			return PASS;
+			    		else
+			    			return FAIL;
+
+			    		close(fd);
+			    	}
+			    	break;
+			    	case 0x1000000B:
+			    	{
+			    		// CHAdeMO_BOARD : 0x1000000B
+			    		for(byte index = 0; index < _gunCount; index++)
+			    		{
+			    			if (chargingInfo[index]->Type == _Type_Chademo)
+			    			{
+			    				int CanFd = InitCanBus();
+			    				if (CanFd > 0)
+			    				{
+			    					if (Upgrade_CAN(CanFd, Type, chargingInfo[index]->Evboard_id, new_str, ShmSysConfigAndInfo) == PASS)
+			    					{
+			    						printf("Upgrad OK. \n");
+			    						return PASS;
+			    					}
+			    					else
+			    					{
+			    						printf("Upgrad Fail. \n");
+			    						return FAIL;
+			    					}
+			    				}
+			    				else
+			    				{
+			    					printf("Upgrad FD fail. \n");
+			    					return FAIL;
+			    				}
+			    			}
+			    		}
+			    		break;
+			    	}
+			    }
+			}
+			free(new_str);
+			free(ptr);
+		}
+	}
+	free(dir);
+	closedir(d);
+	return FAIL;
+}
+
+void CreateRfidFork()
+{
+	pid_t rfidRecPid;
+\
+	rfidRecPid = fork();
+	if (rfidRecPid == 0)
+	{
+		while(true)
+		{
+			// 刷卡判斷
+			GetCardNumber();
+			usleep(100000);
+		}
+	}
+}
+
+void StartSystemTimeoutDet(unsigned char flag)
+{
+	if (ShmSysConfigAndInfo->SysInfo.SystemTimeoutFlag != flag)
+	{
+		gettimeofday(&ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer, NULL);
+	}
+	ShmSysConfigAndInfo->SysInfo.SystemTimeoutFlag = flag;
+}
+
+void StopSystemTimeoutDet()
+{
+	ShmSysConfigAndInfo->SysInfo.SystemTimeoutFlag = Timeout_None;
+}
+
+void StartGunInfoTimeoutDet(unsigned char gunIndex, unsigned char flag)
+{
+	if (gunIndex < _gunCount)
+	{
+		if (chargingInfo[gunIndex]->TimeoutFlag != flag)
+		{
+			gettimeofday(&chargingInfo[gunIndex]->TimeoutTimer, NULL);
+		}
+		chargingInfo[gunIndex]->TimeoutFlag = flag;
+	}
+}
+
+void StopGunInfoTimeoutDet(unsigned char gunIndex)
+{
+	if (gunIndex < _gunCount)
+	{
+		chargingInfo[gunIndex]->TimeoutFlag = Timeout_None;
+	}
+}
+
+void CreateTimeoutFork()
+{
+	pid_t timeoutPid;
+
+	timeoutPid = fork();
+	if (timeoutPid == 0)
+	{
+		while(true)
+		{
+			// 系統
+			switch(ShmSysConfigAndInfo->SysInfo.SystemTimeoutFlag)
+			{
+				case Timeout_SelftestChk:
+					if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) >= 60000000)
+					{
+						_SelfTestTimeout();
+						StopSystemTimeoutDet();
+					}
+					break;
+				case Timeout_Authorizing:
+					if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) >= 60000000)
+					{
+						_AuthorizedTimeout();
+						StopSystemTimeoutDet();
+					}
+					break;
+				case Timeout_VerifyFail:
+					if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) >= 3000000)
+					{
+						_AutoReturnTimeout();
+						StopSystemTimeoutDet();
+					}
+					break;
+				case Timeout_VerifyComp:
+					if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) >= 3000000)
+					{
+						_AutoReturnTimeout();
+						StopSystemTimeoutDet();
+					}
+					break;
+				case Timeout_WaitPlug:
+					if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) >= 40000000)
+					{
+						_DetectPlugInTimeout();
+						StopSystemTimeoutDet();
+					}
+					break;
+			}
+			// 各槍
+			for (byte gun_index = 0; gun_index < _gunCount; gun_index++)
+			{
+				switch(chargingInfo[gun_index]->TimeoutFlag)
+				{
+					case Timeout_Preparing:
+						if (GetTimeoutValue(chargingInfo[gun_index]->TimeoutTimer) >= 30000000)
+						{
+							_PrepareTimeout(gun_index);
+							StopGunInfoTimeoutDet(gun_index);
+						}
+						break;
+					case Timeout_EvChargingDet:
+						if (GetTimeoutValue(chargingInfo[gun_index]->TimeoutTimer) >= 120000000)
+						{
+							_DetectEvChargingEnableTimeout(gun_index);
+							StopGunInfoTimeoutDet(gun_index);
+						}
+						break;
+					case Timeout_EvseChargingDet:
+						if (GetTimeoutValue(chargingInfo[gun_index]->TimeoutTimer) >= 60000000)
+						{
+							_DetectEvseChargingEnableTimeout(gun_index);
+							StopGunInfoTimeoutDet(gun_index);
+						}
+						break;
+					case Timeout_WaitforCompleteDet:
+						if (GetTimeoutValue(chargingInfo[gun_index]->TimeoutTimer) >= 10000000)
+						{
+							_CompleteTimeout(gun_index);
+							StopGunInfoTimeoutDet(gun_index);
+						}
+						break;
+					case Timeout_ForCcsPrechargeDet:
+						if (GetTimeoutValue(chargingInfo[gun_index]->TimeoutTimer) >= 60000000)
+						{
+							_CcsPrechargeTimeout(gun_index);
+							StopGunInfoTimeoutDet(gun_index);
+						}
+						break;
+				}
+			}
+			usleep(100000);
+		}
+	}
+}
+
+int main(void)
+{
+	InitGPIO();
+	InitEthernet();
+	sleep(1);
+	system("/sbin/ifconfig eth0 192.168.1.10 netmask 255.255.255.0 down");
+	sleep(1);
+	system("/sbin/ifconfig eth0 192.168.1.10 netmask 255.255.255.0 up");
+
+	//echo 1 > /sys/class/gpio/gpio110/value
+	//return 0;
+
+	if(CreateShareMemory() == 0)
+	{
+		#ifdef SystemLogMessage
+		DEBUG_ERROR("CreatShareMemory NG \n");
+		#endif
+		if(ShmStatusCodeData!=NULL)
+		{
+			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FailToCreateShareMemory = 1;
+		}
+		return 0;
+		sleep(5);
+		system("reboot -f");
+		sleep(5);
+		system("reboot -f");
+	}
+
+	printf("\n");
+	printf("CheckGunTypeFromHw....... \n");
+	CheckGunTypeFromHw();
+	char *moduleName = "DSYE601E00T2PH";
+	memcpy(&ShmSysConfigAndInfo->SysConfig.ModelName, moduleName, strlen(moduleName));
+
+	if (!CheckConnectorTypeStatus())
+	{
+		// Module Name 與硬體對應不正確
+		printf("Module Name & HW info none match. \n");
+		DEBUG_ERROR("Module Name & HW info none match. \n");
+		sleep(5);
+		return 0;
+	}
+
+	printf("Module Name & HW info correct. Initialize.......\n");
+	Initialization();
+	printf("Spawn all Task. \n");
+	SpawnTask();
+
+	ChangeLcmByIndex(_LCM_INIT);
+	CreateTimeoutFork();
+	printf("Self test. \n");
+	SelfTestRun();
+	StopSystemTimeoutDet();
+
+	if (ShmSysConfigAndInfo->SysInfo.SelfTestSeq == _STEST_FAIL)
+	{
+		for (byte gun_index = 0; gun_index < _gunCount; gun_index++)
+		{
+			setChargerMode(gun_index, MODE_ALARM);
+		}
+		ChangeLcmByIndex(_LCM_FIX);
+		return FAIL;
+	}
+	else
+	{
+		for (byte gun_index = 0; gun_index < _gunCount; gun_index++)
+		{
+			setChargerMode(gun_index, MODE_IDLE);
+		}
+	}
+	ChangeLcmByIndex(_LCM_IDLE);
+	sleep(1);
+	//***** 須新增的偵測 *****//
+	// 1. Thernal - 控制風扇轉速
+	// 2. ouput fuse - 控制風扇轉速
+
+	CreateRfidFork();
+	// Main loop
+	printf("Main Loop. \n");
+	for (;;)
+	{
+		ChkPrimaryStatus();
+		if (ShmSysConfigAndInfo->SysInfo.PageIndex == _LCM_IDLE)
+		{
+			//printf("ShmSysConfigAndInfo->SysInfo.FirmwareUpdate = %d \n", ShmSysConfigAndInfo->SysInfo.FirmwareUpdate);
+			if (ShmSysConfigAndInfo->SysInfo.FirmwareUpdate == YES)
+			{
+				KillTask();
+				if (CheckUpdateProcess() == PASS)
+				{
+					printf("update complete. \n");
+				}
+				else
+				{
+					printf("update fail. \n");
+				}
+				ShmSysConfigAndInfo->SysInfo.FirmwareUpdate = NO;
+				sleep(5);
+				system("reboot -f");
+			}
+		}
+//		usleep(whileLoopTime * 100);
+//		continue;
+		// 讀卡邏輯
+		ScannerCardProcess();
+
+		for (byte gun_index = 0; gun_index < _gunCount; gun_index++)
+		{
+			CheckGpioInStatus();
+			CheckErrorOccurStatus(gun_index);
+
+			switch(chargingInfo[gun_index]->SystemStatus)
+			{
+				case S_IDLE:
+				{
+					if (isModeChange(gun_index))
+					{
+						printf("S_IDLE================================== %x \n", gun_index);
+						chargingInfo[gun_index]->RemainChargingDuration = 0;
+						chargingInfo[gun_index]->PresentChargedEnergy = 0;
+					}
+
+					if (ShmSysConfigAndInfo->SysStopChargingAlarmCode.Level == 2)
+					{
+						ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_FIX;
+						ClearDetectPluginFlag();
+					}
+					else
+					{
+						// 判斷是否有啟用檢查插槍
+						if(isDetectPlugin())
+						{
+							// 卡號驗證成功後,等待充電槍插入充電車
+							if (chargingInfo[gun_index]->ConnectorPlugIn == YES)
+							{
+								ShmSysConfigAndInfo->SysInfo.CurGunSelected = gun_index;
+								strcpy((char *)chargingInfo[gun_index]->CardNumber, (char *)ShmSysConfigAndInfo->SysConfig.UserId);
+								// 當前操作的槍號,進入 Preparing
+								setChargerMode(gun_index, MODE_REASSIGN_CHECK);
+								ClearDetectPluginFlag();
+								ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_NONE;
+							}
+							else if (!isCardScan)
+							{
+								// LCM => Waiting for plugging
+								ShmSysConfigAndInfo->SysInfo.SystemPage = _LCM_WAIT_FOR_PLUG;
+							}
+						}
+						else
+						{
+							if (ShmSysConfigAndInfo->SysInfo.CurGunSelected == gun_index)
+								ShmSysConfigAndInfo->SysInfo.ConnectorPage = _LCM_IDLE;
+						}
+					}
+				}
+					break;
+				case S_REASSIGN_CHECK:
+				{
+					if (isModeChange(gun_index))
+					{
+						printf("S_REASSIGN_CHECK================================== %x \n", gun_index);
+						StopSystemTimeoutDet();
+					}
+
+					bool isRessign = false;
+					if (_gunCount > 1)
+					{
+						for (byte index = 0; index < _gunCount; index++)
+						{
+							// 有其他槍已經分配好 psu 模塊
+							if (ShmSysConfigAndInfo->SysInfo.CurGunSelected != index &&
+									chargingInfo[index]->SystemStatus >= S_PREPARNING)
+							{
+								printf("=============Smart Charging============= Step 1 \n");
+								ShmSysConfigAndInfo->SysInfo.ReAssignedFlag = _REASSIGNED_PREPARE;
+								isRessign = true;
+								break;
+							}
+						}
+					}
+
+					if (isRessign)
+						setChargerMode(gun_index, MODE_REASSIGN);
+					else
+						setChargerMode(gun_index, MODE_PRECHARGE);
+				}
+					break;
+				case S_REASSIGN:
+				{
+					if (isModeChange(gun_index))
+					{
+						printf("S_REASSIGN================================== %x \n", gun_index);
+					}
+
+					// 重新分配,此階段主要是讓已經在充電或者準備進入充電前的緩衝
+					// 此狀態下~ 控制權在於 PSU 及 EV小板 Process
+					if (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag == _REASSIGNED_NONE ||
+							ShmSysConfigAndInfo->SysInfo.ReAssignedFlag == _REASSIGNED_MAIN)
+						setChargerMode(gun_index, MODE_PRECHARGE);
+					else if (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag == _REASSIGNED_RELAY &&
+						ShmSysConfigAndInfo->SysInfo.BridgeRelayStatus == NO)
+							ShmSysConfigAndInfo->SysInfo.ReAssignedFlag = _REASSIGNED_MAIN;
+				}
+					break;
+				case S_PREPARNING:
+				{
+					if (isModeChange(gun_index))
+					{
+						printf("S_PREPARNING================================== %x \n", gun_index);
+						StopGunInfoTimeoutDet(gun_index);
+						StartGunInfoTimeoutDet(gun_index, Timeout_Preparing);
+					}
+
+					if (ShmSysConfigAndInfo->SysInfo.ReAssignedFlag != _REASSIGNED_NONE)
+						ShmSysConfigAndInfo->SysInfo.ReAssignedFlag = _REASSIGNED_NONE;
+
+					// Precharge 三個流程 : 1 Precharge, 2 Preparing for ev, 3 Preparing for evse
+					// Precharge : AC Contactor <Relay board>, Relay k1 k2 <Relay board>, PSU AddressAssignment, PSU GroupAvailablePower
+					// Preparing for ev : 車端通訊流程
+					// Preparing for evse : PSU (output 500V, 2A), GFD Test <Relay board>
+					//ShmSysConfigAndInfo->SysInfo.AcContactorStatus == YES &&
+					if (((ShmPsuData->SystemPresentPsuQuantity > 0 &&
+							ShmPsuData->PsuGroup[gun_index].GroupPresentPsuQuantity > 0 &&
+							ShmPsuData->PsuGroup[gun_index].GroupAvailablePower > 10) &&
+							chargingInfo[gun_index]->AvailableChargingPower > 10))
+					{
+						setChargerMode(gun_index, MODE_PREPARE_FOR_EV);
+					}
+
+					if (ShmSysConfigAndInfo->SysInfo.CurGunSelected == gun_index)
+						ShmSysConfigAndInfo->SysInfo.ConnectorPage = _LCM_PRE_CHARGE;
+				}
+					break;
+				case S_PREPARING_FOR_EV: // 等待車端的通訊 (EV 小板),待車端回報後,開始樁端的測試
+				{
+					if (isModeChange(gun_index))
+					{
+						printf("S_PREPARING_FOR_EV================================== %x \n", gun_index);
+						strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+						StopGunInfoTimeoutDet(gun_index);
+						StartGunInfoTimeoutDet(gun_index, Timeout_EvChargingDet);
+					}
+
+					if (chargingInfo[gun_index]->Type == _Type_Chademo)
+					{
+						// 檢查車端的槍鎖是否為鎖上
+						if (isEvGunLocked_chademo(gun_index) == YES)
+						{
+							setChargerMode(gun_index, MODE_PREPARE_FOR_EVSE);
+						}
+					}
+					else if (chargingInfo[gun_index]->Type == _Type_CCS)
+					{
+						// 檢查車端的 charging enable 是否為 1
+						if (isEvGunLocked_ccs(gun_index) == YES)
+						{
+							setChargerMode(gun_index, MODE_PREPARE_FOR_EVSE);
+						}
+					}
+
+					if (isEvBoardStopChargeFlag(gun_index) == YES)
+					{
+						// 板端要求停止
+						ChargingTerminalProcess(gun_index);
+					}
+
+					// LCM => Pre-charging
+					if (ShmSysConfigAndInfo->SysInfo.CurGunSelected == gun_index)
+						ShmSysConfigAndInfo->SysInfo.ConnectorPage = _LCM_PRE_CHARGE;
+				}
+					break;
+				case S_PREPARING_FOR_EVSE: // 等待 RB 通訊及測試,並將狀態回報, CSU 確認 Pass 後,開始進入充電
+				{
+					if (isModeChange(gun_index))
+					{
+						printf("S_PREPARING_FOR_EVSE================================== %x \n", gun_index);
+						StopGunInfoTimeoutDet(gun_index);
+						StartGunInfoTimeoutDet(gun_index, Timeout_EvseChargingDet);
+					}
+
+					if (chargingInfo[gun_index]->Type == _Type_Chademo)
+					{
+						// 檢查樁端的 GFD 結果
+						if (isPrechargeStatus_chademo(gun_index) > 5 && isPrechargeStatus_chademo(gun_index) < 8)
+						{
+							// 當前操作的槍號,進入 Charging
+							setChargerMode(gun_index, MODE_CHARGING);
+						}
+					}
+					else if (chargingInfo[gun_index]->Type == _Type_CCS)
+					{
+						// 檢查樁端的 GFD 結果
+						if (chargingInfo[gun_index]->GroundFaultStatus == GFD_PASS)
+						{
+							setChargerMode(gun_index, MODE_CCS_PRECHARGE_STEP0);
+						}
+					}
+
+					if (isEvBoardStopChargeFlag(gun_index) == YES)
+					{
+						// 板端要求停止
+						ChargingTerminalProcess(gun_index);
+					}
+
+					// LCM => Pre-charging
+					if (ShmSysConfigAndInfo->SysInfo.CurGunSelected == gun_index)
+						ShmSysConfigAndInfo->SysInfo.ConnectorPage = _LCM_PRE_CHARGE;
+				}
+					break;
+				case S_CHARGING: // 剛進入充電狀態,等待 EV 小板要求的輸出電流後開始輸出
+				{
+					if (isModeChange(gun_index))
+					{
+						printf("S_CHARGING================================== %x \n", gun_index);
+						StopGunInfoTimeoutDet(gun_index);
+						ftime(&startChargingTime[gun_index]);
+					}
+
+					ftime(&endChargingTime[gun_index]);
+					chargingInfo[gun_index]->RemainChargingDuration = DiffTimeb(startChargingTime[gun_index], endChargingTime[gun_index]);
+
+					if (isEvBoardStopChargeFlag(gun_index) == YES)
+					{
+						// 板端要求停止
+						ChargingTerminalProcess(gun_index);
+					}
+
+					// LCM => Charging
+					if (ShmSysConfigAndInfo->SysInfo.CurGunSelected == gun_index)
+						ShmSysConfigAndInfo->SysInfo.ConnectorPage = _LCM_CHARGING;
+				}
+					break;
+				case S_TERMINATING:
+				{
+					if (isModeChange(gun_index))
+					{
+						printf ("terminating......................... %x \n", gun_index);
+						StopGunInfoTimeoutDet(gun_index);
+					}
+
+					if (chargingInfo[gun_index]->Type == _Type_Chademo)
+					{
+						// 非車端的停止 : 需等待小板送出停止指令,讓車端解除槍
+						if (isEvStopCharging_chademo(gun_index) == YES)
+						{
+							setChargerMode(gun_index, MODE_COMPLETE);
+						}
+					}
+					else if (chargingInfo[gun_index]->Type == _Type_CCS)
+					{
+						// 非車端的停止 : 需等待小板送出停止指令,讓車端解除槍
+						if (isEvStopCharging_ccs(gun_index) == YES)
+						{
+							setChargerMode(gun_index, MODE_COMPLETE);
+						}
+					}
+					if (ShmSysConfigAndInfo->SysInfo.CurGunSelected == gun_index)
+						ShmSysConfigAndInfo->SysInfo.ConnectorPage = _LCM_COMPLETE;
+					//ChangeLcmByIndex(gun_index, _LCM_COMPLETE);
+				}
+					break;
+				case S_COMPLETE:
+				{
+					if (isModeChange(gun_index))
+					{
+						printf ("complete......................... %x \n", gun_index);
+						ftime(&endChargingTime[gun_index]);
+						if (chargingInfo[gun_index]->RemainChargingDuration != 0)
+							chargingInfo[gun_index]->RemainChargingDuration = DiffTimeb(startChargingTime[gun_index], endChargingTime[gun_index]);
+
+						strcpy((char *)chargingInfo[gun_index]->CardNumber, "");
+						strcpy((char *)ShmSysConfigAndInfo->SysConfig.UserId, "");
+						StopGunInfoTimeoutDet(gun_index);
+						StartGunInfoTimeoutDet(gun_index, Timeout_WaitforCompleteDet);
+					}
+
+					if (ShmSysConfigAndInfo->SysInfo.CurGunSelected == gun_index)
+						ShmSysConfigAndInfo->SysInfo.ConnectorPage = _LCM_COMPLETE;
+				}
+					break;
+				case S_CCS_PRECHARGE_ST0:
+				{
+					if (isModeChange(gun_index))
+					{
+						printf("CCS Precharge Processing 1....................%x \n", gun_index);
+						StopGunInfoTimeoutDet(gun_index);
+						StartGunInfoTimeoutDet(gun_index, Timeout_ForCcsPrechargeDet);
+					}
+
+					if (isEvBoardStopChargeFlag(gun_index) == YES)
+					{
+						// 板端要求停止
+						ChargingTerminalProcess(gun_index);
+					}
+
+					// 等待 EV 小板 (CCS) 通知可以開始 Precharge
+					// 切換 D+ Relay to Precharge Relay
+					if (isPrechargeStatus_ccs(gun_index) == 39 || isPrechargeStatus_ccs(gun_index) == 40)
+					{
+						if (chargingInfo[gun_index]->RelayKPK2Status == YES && chargingInfo[gun_index]->PrechargeStatus != PRECHARGE_READY)
+						//if (chargingInfo[gun_index]->PrechargeStatus != PRECHARGE_PRERELAY_PASS)
+						{
+							printf("Send precharge ready 1..........%x, status = %d \n", gun_index, isPrechargeStatus_ccs(gun_index));
+							chargingInfo[gun_index]->PrechargeStatus = PRECHARGE_READY;
+						}
+					}
+					else if (isPrechargeStatus_ccs(gun_index) == 45 || isPrechargeStatus_ccs(gun_index) == 46)
+					{
+						setChargerMode(gun_index, MODE_CCS_PRECHARGE_STEP1);
+					}
+
+					break;
+				}
+				case S_CCS_PRECHARGE_ST1:
+				{
+					if (isModeChange(gun_index))
+					{
+						printf("CCS Precharge Processing 2....................%x \n", gun_index);
+					}
+
+					if (isEvBoardStopChargeFlag(gun_index) == YES)
+					{
+						// 板端要求停止
+						ChargingTerminalProcess(gun_index);
+					}
+
+					// 等待小板通知進入充電
+					// 切換 D+ Relay to Precharge Relay
+					if (chargingInfo[gun_index]->RelayK1K2Status == YES)
+					{
+						chargingInfo[gun_index]->PrechargeStatus = PRECHARGE_READY;
+						setChargerMode(gun_index, MODE_CHARGING);
+					}
+					break;
+				}
+			}
+		}
+
+		if (ShmSysConfigAndInfo->SysInfo.SystemPage != _LCM_NONE)
+			ChangeLcmByIndex(ShmSysConfigAndInfo->SysInfo.SystemPage);
+		else
+			ChangeLcmByIndex(ShmSysConfigAndInfo->SysInfo.ConnectorPage);
+
+		usleep(whileLoopTime);
+	}
+
+	return FAIL;
+}

BIN
EVSE/Projects/DM30/Apps/main.o


+ 5 - 0
EVSE/Projects/DM30/Apps/timeout.c

@@ -0,0 +1,5 @@
+#include "timeout.h"
+
+//===============================================
+// Initial Callback function
+//===============================================

+ 52 - 0
EVSE/Projects/DM30/Apps/timeout.h

@@ -0,0 +1,52 @@
+#ifndef TIMEOUT_H_
+#define TIMEOUT_H_
+
+#include 	<sys/time.h>
+#include 	<sys/timeb.h>
+#include    <sys/types.h>
+#include    <sys/stat.h>
+#include 	<sys/types.h>
+#include 	<sys/ioctl.h>
+#include 	<sys/socket.h>
+#include 	<sys/ipc.h>
+#include 	<sys/shm.h>
+#include 	<sys/shm.h>
+#include 	<sys/mman.h>
+#include 	<linux/wireless.h>
+#include 	<linux/can.h>
+#include 	<linux/can/raw.h>
+#include 	<arpa/inet.h>
+#include 	<netinet/in.h>
+
+#include 	<unistd.h>
+#include 	<stdarg.h>
+#include    <stdio.h>
+#include    <stdlib.h>
+#include    <unistd.h>
+#include    <fcntl.h>
+#include    <termios.h>
+#include    <errno.h>
+#include 	<errno.h>
+#include 	<string.h>
+#include	<time.h>
+#include	<ctype.h>
+#include 	<ifaddrs.h>
+
+enum Timeout_flag
+{
+	Timeout_None =					0,
+	Timeout_SelftestChk = 			1,
+	Timeout_Authorizing = 			2,
+	Timeout_VerifyFail = 			3,
+	Timeout_VerifyComp = 			4,
+	Timeout_WaitPlug = 				5,
+
+	Timeout_Preparing = 			6,
+	Timeout_EvChargingDet = 		7,
+	Timeout_EvseChargingDet = 		8,
+	Timeout_WaitforCompleteDet = 	9,
+
+	Timeout_ForCcsPrechargeDet = 	10,
+};
+
+#endif /* TIMEOUT_H_ */

BIN
EVSE/Projects/DM30/Apps/timeout.o


BIN
EVSE/Projects/DM30/Images/root/FactoryConfig


BIN
EVSE/Projects/DM30/Images/root/Module_EventLogging


BIN
EVSE/Projects/DM30/Images/root/Module_InternalComm


+ 3 - 0
EVSE/Projects/define.h

@@ -275,6 +275,8 @@ struct SysInfoData
 	unsigned char 		AcContactorStatus;				// 0: disconnected, 1: connected
 	unsigned char 	 	SystemTimeoutFlag;				// 0 : none, 1 : self test
 	struct timeval		SystemTimeoutTimer;
+	unsigned char   SystemPage;
+	unsigned char   ConnectorPage;
 };
 
 struct WARNING_CODE_INFO
@@ -888,6 +890,7 @@ struct CHAdeMOEvData
 	unsigned char  SOC;					//102.6				0~100(%) (unit:%)
 										//					Display Only
 	unsigned char  Communicating;			//					it is true if receive EV CAN message within every 1500ms
+unsigned char  PresentMsgFlowStatus;
 };
 
 struct CHAdeMOEvseData