#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*標準輸入輸出定義*/ #include /*標準函數庫定義*/ #include /*Unix 標準函數定義*/ #include /*檔控制定義*/ #include /*PPSIX 終端控制定義*/ #include /*錯誤號定義*/ #include #include #include #include #include #include #include "Config.h" #include #include "../../define.h" #include #include "Module_Upgrade.h" #include "timeout.h" #define Debug #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; //================================================ // 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; } //================================= // 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); } 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 CreatShareMemory() { int MeterSMId; //creat ShmSysConfigAndInfo if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo), IPC_CREAT | 0777)) < 0) { #ifdef SystemLogMessage StoreLogMsg("[main]CreatShareMemory:shmget ShmSysConfigAndInfo NG \n"); #endif return 0; } else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage StoreLogMsg("[main]CreatShareMemory:shmat ShmSysConfigAndInfo NG \n"); #endif return 0; } memset(ShmSysConfigAndInfo, 0, sizeof(struct SysConfigAndInfo)); //creat ShmStatusCodeData 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)); //creat ShmCHAdeMOData 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 0 > /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 1 > /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(); // 初始化卡號驗證的 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; 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 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') { printf("ccs pass \n"); ShmCcsData->V2GMessage_DIN70121[chargingInfo[index]->type_index].SelfTest_Comp = YES; } else 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; } } } } 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/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; } //=============================================== // 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(); } 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(_LCM_PRE_CHARGE); } break; case S_CHARGING: { ChangeLcmByIndex(_LCM_CHARGING); } break; case S_TERMINATING: { ChangeLcmByIndex(_LCM_COMPLETE); } break; } return; } } if (!IsAuthorizingMode()) ChangeLcmByIndex(_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"); ChangeLcmByIndex(_LCM_AUTHORIZ_FAIL); ClearAuthorizedFlag(); } } void _DetectPlugInTimeout() { if(isDetectPlugin()) { printf("_DetectPlugInTimeout \n"); ClearDetectPluginFlag(); } } 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 _PrechargeTimeout(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) { leftBtnPush = true; // 左邊的選槍按鈕,只有在雙槍都在充電時候才有用 : 30KW 以下該按鈕無作用 } else if (ShmPrimaryMcuData->InputDet.bits.Button1 == BTN_RELEASE) { leftBtnPush = false; } if (ShmPrimaryMcuData->InputDet.bits.Button2 == BTN_PRESS && !rightBtnPush) { 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) { 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: bd0_1_status = gpioValue; break; case 23: bd0_2_status = gpioValue; break; case 44: bd1_1_status = gpioValue; break; case 45: bd1_2_status = gpioValue; break; } } } } void CheckGpioInStatus() { int pinIn[2] = { 26, 46 }; 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 26: { // 左槍 if (_gunCount > 0) { if (chargingInfo[0]->Type == _Type_Chademo) EmcOccureByString(0, InfoStatusCode[30]); else if (chargingInfo[0]->Type == _Type_CCS) EmcOccureByString(0, InfoStatusCode[30]); } } break; case 46: { // 右槍 if (_gunCount > 1) { if (chargingInfo[1]->Type == _Type_Chademo) EmcOccureByString(1, InfoStatusCode[30]); else if (chargingInfo[1]->Type == _Type_CCS) EmcOccureByString(1, InfoStatusCode[30]); } } break; } } else { switch (pinIn[i]) { // 小板緊急停止 case 26: { // 左槍 if (_gunCount > 0) { ReleaseEmsOccureByString(0, "023730"); } } break; case 46: { // 右槍 } 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 ChangeLcmByIndex(_LCM_AUTHORIZING); // 進入確認卡號狀態 AuthorizingStart(); // authorizing timer StartSystemTimeoutDet(Timeout_Authorizing); autoReturnTimeoutFlag = NO; } } } } else { // 確認驗證卡號完成沒 if (isAuthorizedComplete() || true) { StopSystemTimeoutDet(); // 判斷後台回覆狀態 if(canStartCharging() || true) { // LCM => Authorize complete ChangeLcmByIndex(_LCM_AUTHORIZ_COMP); // 通過認證,開始確認當前要進入充電的槍號 DetectPluginStart(); } else { // LCM => Authorize 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]->PreSystemStatus) { result = YES; chargingInfo[gun_index]->PreSystemStatus = chargingInfo[gun_index]->SystemStatus; } return result; } void ScannerCardProcess() { if (!isDetectPlugin() && !isCardScan) { 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 0x30: // none break; case 0x31: // IEC 62196-2 Type 1/SAE J1772 Plug break; case 0x32: // IEC 62196-2 Type 1/SAE J1772 Socket break; case 0x33: // IEC 62196-2 Type 2 Plug break; case 0x34: // IEC 62196-2 Type 2 Socket break; case 0x35: // GB/T AC Plug break; case 0x36: // GB/T AC Socket break; case 0x4A: // CHAdeMO { if (CHAdeMO_QUANTITY > _chademoIndex) { ShmSysConfigAndInfo->SysInfo.ChademoChargingData[_chademoIndex].Index = _gunIndex; ShmSysConfigAndInfo->SysInfo.ChademoChargingData[_chademoIndex].slotsIndex = slots; chargingInfo[_gunIndex] = &ShmSysConfigAndInfo->SysInfo.ChademoChargingData[_chademoIndex]; chargingInfo[_gunIndex]->SystemStatus = S_BOOTING; chargingInfo[_gunIndex]->Type = _Type_Chademo; chargingInfo[_gunIndex]->type_index = _chademoIndex; _chademoIndex++; _gunIndex++; } } break; case 0x55: // CCS1 combo break; case 0x45: // CCS2 combo { if (CCS_QUANTITY > _ccsIndex) { ShmSysConfigAndInfo->SysInfo.CcsChargingData[_ccsIndex].Index = _gunIndex; ShmSysConfigAndInfo->SysInfo.CcsChargingData[_ccsIndex].slotsIndex = slots; chargingInfo[_gunIndex] = &ShmSysConfigAndInfo->SysInfo.CcsChargingData[_ccsIndex]; chargingInfo[_gunIndex]->SystemStatus = S_BOOTING; chargingInfo[_gunIndex]->Type = _Type_CCS; chargingInfo[_gunIndex]->type_index = _ccsIndex; // 現階段預設為走 DIN70121 ShmCcsData->CommProtocol = 0x01; _ccsIndex++; _gunIndex++; } } break; case 0x47: // GBT DC printf("G \n"); break; case 0x44: // GBT DC x 2 printf("D \n"); 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; if (_gunCount == 0) result = false; chargingInfo[0]->Evboard_id = 0x01; return true; // 偵測槍屬於哪個 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]->slotsIndex == 0x01) { 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]->slotsIndex == 0x01) { chargingInfo[gunIndex]->Evboard_id = 0x01; } } if (bd1_1_status == 0 && bd1_2_status == 1) { // 與硬體相同 type : Chademo if (chargingInfo[gunIndex]->Type == _Type_Chademo && chargingInfo[gunIndex]->slotsIndex == 0x03) { chargingInfo[gunIndex]->Evboard_id = 0x02; } } //else if (bd1_1_status == 0 || bd1_2_status == 1) else if (bd1_1_status == 1 && bd1_2_status == 0) { // 與硬體相同 type : CCS if (chargingInfo[gunIndex]->Type == _Type_CCS && chargingInfo[gunIndex]->slotsIndex == 0x03) { chargingInfo[gunIndex]->Evboard_id = 0x02; } } printf("Evboard_id = %d \n", 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 EventLogging"); system("killall Module_PrimaryComm"); system("killall Module_EvComm"); system("killall Module_LcmControl"); system("killall Module_InternalComm"); } 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); if (Type == 0x1000000B) { // Chademo 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; } } } } // int fd = InitComPort(); // // if (Upgrade_UART(fd, Type , 0x04, new_str, ShmSysConfigAndInfo) == PASS) // { // return PASS; // } // else // return FAIL; // } // close(fd); // } } 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(); break; case Timeout_Authorizing: if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) >= 60000000) _AuthorizedTimeout(); break; case Timeout_VerifyFail: if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) >= 3000000) _AutoReturnTimeout(); break; case Timeout_VerifyComp: if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) >= 3000000) _AutoReturnTimeout(); break; case Timeout_WaitPlug: if (GetTimeoutValue(ShmSysConfigAndInfo->SysInfo.SystemTimeoutTimer) >= 40000000) _DetectPlugInTimeout(); 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) _PrechargeTimeout(gun_index); break; case Timeout_EvChargingDet: if (GetTimeoutValue(chargingInfo[gun_index]->TimeoutTimer) >= 120000000) _DetectEvChargingEnableTimeout(gun_index); break; case Timeout_EvseChargingDet: if (GetTimeoutValue(chargingInfo[gun_index]->TimeoutTimer) >= 60000000) _DetectEvseChargingEnableTimeout(gun_index); break; case Timeout_WaitforCompleteDet: if (GetTimeoutValue(chargingInfo[gun_index]->TimeoutTimer) >= 10000000) _CompleteTimeout(gun_index); break; case Timeout_ForCcsPrechargeDet: if (GetTimeoutValue(chargingInfo[gun_index]->TimeoutTimer) >= 60000000) _CcsPrechargeTimeout(gun_index); break; } } usleep(100000); } } } int main(void) { //Create all share memory if(CreatShareMemory()==0) { #ifdef SystemLogMessage DEBUG_ERROR("CreatShareMemory NG \n"); #endif if(ShmStatusCodeData!=NULL) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FailToCreateShareMemory=1; } return 0; sleep(5); system("reboot -f"); sleep(5); system("reboot -f"); } printf("\n"); printf("Initializing. \n"); // InitGPIO(); // //LoadSysConfigAndInfo(&ShmSysConfigAndInfo->SysConfig); // InitEthernet(); // // return 0; printf("Check GPIO Status. \n"); CheckGunTypeFromHw(); char *moduleName = "DSYZ301E0001P0"; 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. \n"); Initialization(); printf("Spawn all Task. \n"); SpawnTask(); ChangeLcmByIndex(_LCM_INIT); printf("_gunCount = %d \n", _gunCount); 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) { if (ShmSysConfigAndInfo->SysInfo.FirmwareUpdate == YES) { KillTask(); if (CheckUpdateProcess() == PASS) { printf("update complete. \n"); } else { printf("update fail. \n"); } ShmSysConfigAndInfo->SysInfo.FirmwareUpdate = NO; // sleep(3); // system("reboot -f"); } } // 讀卡邏輯 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) { ChangeLcmByIndex(_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_PRECHARGE); ClearDetectPluginFlag(); } else if (!isCardScan) { // LCM => Waiting for plugging ChangeLcmByIndex(_LCM_WAIT_FOR_PLUG); } } else { //printf("ChangeLcmByIndex(_LCM_IDLE) \n"); ChangeLcmByIndex(_LCM_IDLE); } } } break; case S_REASSIGN_CHECK:{;} break; case S_REASSIGN:{;} break; case S_PREPARNING: { if (chargingInfo[gun_index]->ConnectorPlugIn == YES) { if (isModeChange(gun_index)) { printf("S_PREPARNING================================== %x \n", gun_index); StopGunInfoTimeoutDet(gun_index); StartGunInfoTimeoutDet(gun_index, Timeout_Preparing); } // Precharge 三個流程 : 1 Precharge, 2 Preparing for ev, 3 Preparing for evse // Precharge : AC Contactor , Relay k1 k2 , PSU AddressAssignment, PSU GroupAvailablePower // Preparing for ev : 車端通訊流程 // Preparing for evse : PSU (output 500V, 2A), GFD Test //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); } } ChangeLcmByIndex(_LCM_PRE_CHARGE); } break; case S_PREPARING_FOR_EV: // 等待車端的通訊 (EV 小板),待車端回報後,開始樁端的測試 { if (isModeChange(gun_index)) { printf("S_PREPARING_FOR_EV================================== \n"); 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) { if (chargingInfo[gun_index]->FuseChargingVoltage < 600) { setChargerMode(gun_index, MODE_PREPARE_FOR_EVSE); } } } else if (chargingInfo[gun_index]->Type == _Type_CCS) { // 檢查車端的 charging enable 是否為 1 if (isEvGunLocked_ccs(gun_index) == YES) { if (chargingInfo[gun_index]->FuseChargingVoltage < 600) { setChargerMode(gun_index, MODE_PREPARE_FOR_EVSE); } else printf("over 60 V in bus. \n"); } } if (isEvBoardStopChargeFlag(gun_index) == YES) { // 板端要求停止 ChargingTerminalProcess(gun_index); } // LCM => Pre-charging ChangeLcmByIndex(_LCM_PRE_CHARGE); } break; case S_PREPARING_FOR_EVSE: // 等待 RB 通訊及測試,並將狀態回報, CSU 確認 Pass 後,開始進入充電 { if (isModeChange(gun_index)) { printf("S_PREPARING_FOR_EVSE================================== \n"); StopGunInfoTimeoutDet(gun_index); StartGunInfoTimeoutDet(gun_index, Timeout_EvseChargingDet); } if (chargingInfo[gun_index]->Type == _Type_Chademo) { // 檢查樁端的 GFD 結果 if (chargingInfo[gun_index]->GroundFaultStatus == GFD_PASS) { // 當前操作的槍號,進入 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 ChangeLcmByIndex(_LCM_PRE_CHARGE); } break; case S_CHARGING: // 剛進入充電狀態,等待 EV 小板要求的輸出電流後開始輸出 { if (isModeChange(gun_index)) { printf("S_CHARGING================================== \n"); 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 ChangeLcmByIndex(_LCM_CHARGING); } break; case S_TERMINATING: { if (isModeChange(gun_index)) { printf ("terminating......................... \n"); StopGunInfoTimeoutDet(gun_index); } if (chargingInfo[gun_index]->Type == _Type_Chademo) { // 非車端的停止 : 需等待小板送出停止指令,讓車端解除槍 if (isEvStopCharging_chademo(gun_index) == YES) { if (chargingInfo[gun_index]->RelayK1K2Status == NO) { setChargerMode(gun_index, MODE_COMPLETE); } } } else if (chargingInfo[gun_index]->Type == _Type_CCS) { // 非車端的停止 : 需等待小板送出停止指令,讓車端解除槍 if (isEvStopCharging_ccs(gun_index) == YES) { setChargerMode(gun_index, MODE_COMPLETE); } } ChangeLcmByIndex(_LCM_COMPLETE); } break; case S_COMPLETE: { if (isModeChange(gun_index)) { printf ("complete......................... \n"); ftime(&endChargingTime[gun_index]); 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 (chargingInfo[gun_index]->RelayK1K2Status == NO) { // LCM => Charging ChangeLcmByIndex(_LCM_COMPLETE); } } break; case S_CCS_PRECHARGE_ST0: { if (isModeChange(gun_index)) { printf("CCS Precharge Processing 1....................\n"); 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..........\n"); 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....................\n"); } 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; } } } usleep(whileLoopTime); } return FAIL; }