#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../Config.h" #include "../Log/log.h" #include "../Define/define.h" #include "../ShareMemory/shmMem.h" #include "../SelectGun/SelectGun.h" #include "Ev_Comm.h" #include "Module_EvComm.h" #include "../CSU/main.h" //------------------------------------------------------------------------------ static struct SysConfigData *pSysConfig = NULL; static struct SysInfoData *pSysInfo = NULL; static struct FaultCodeData *pFaultCode = NULL; static struct AlarmCodeData *pAlarmCode = NULL; static struct CHAdeMOData *ShmCHAdeMOData = NULL; static struct GBTData *ShmGBTData = NULL; static struct CcsData *ShmCcsData = NULL; static DcCommonInfo *ShmDcCommonData = NULL; static SelectGunInfo *ShmSelectGunInfo = NULL; struct MeterInformation *ShmCsuMeterData = NULL; // 限制最大充電電壓,因應不同 type 槍線來限制 // Chademo : 500V, 125A, // GB : 750, 120A // CCS : 950V, 120A //DS60-120 add //static double chademoVol = 5000; //static double ccsVol = 9500; //static double gbVol = 7500; static float maxChargingVol[2] = {0, 0}; // 限制最大充電電壓,如依照模塊則填上 0 // 限制最大充電電流與能量透過 Web static float maxChargingCur[2] = {0, 0}; // 限制最大充電電流,如依照模塊則填上 0 static float maxChargingPow = 0; // 限制最大充電能量,如依照模塊則填上 0 int chargingTime[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY]; static float LogInfo[2][10]; //DS60-120 add static int CanFd = -1; bool psuOutputReady[2] = {0, 0}; uint8_t deratingIndex[2]; bool ischillerHighTemp[2]; //------------------------------------------------------------------------------ extern void CANReceiver(int fd); extern void ClearAbnormalStatus_Chademo(uint8_t gun_index); extern void ClearAbnormalStatus_GB(uint8_t gun_index); extern void ClearAbnormalStatus_CCS(uint8_t gun_index); //------------------------------------------------------------------------------ int GetCanFd(void) { return CanFd; } void GetClockTime(struct timespec *_now_time, void *null) { clock_gettime(CLOCK_MONOTONIC, _now_time); } unsigned long GetClockTimeoutValue(struct timespec _start_time) { struct timespec ts_end; unsigned long ret = 0; clock_gettime(CLOCK_MONOTONIC, &ts_end); ret = ((unsigned long)(ts_end.tv_sec - _start_time.tv_sec) * 1000000) + ((unsigned long)((ts_end.tv_nsec / 1000) - (_start_time.tv_nsec/ 1000))); return ret; } uint32_t 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 InitCanBus(void) { int s0, nbytes; struct timeval tv; struct ifreq ifr0; struct sockaddr_can addr0; struct can_filter rxfilter[3]; 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) { log_error("Set SO_RCVTIMEO NG"); } nbytes = 40960; if (setsockopt(s0, SOL_SOCKET, SO_RCVBUF, &nbytes, sizeof(int)) < 0) { log_error("Set SO_RCVBUF NG"); } nbytes = 40960; if (setsockopt(s0, SOL_SOCKET, SO_SNDBUF, &nbytes, sizeof(int)) < 0) { log_error("Set SO_SNDBUF NG"); } rxfilter[0].can_id = 0x01; rxfilter[0].can_mask = 0x000000FF; rxfilter[1].can_id = 0x02; rxfilter[1].can_mask = 0x000000FF; rxfilter[2].can_id = 0x01FF; rxfilter[2].can_mask = 0x00000FFF; if (setsockopt(s0, SOL_CAN_RAW, CAN_RAW_FILTER, &rxfilter, sizeof(struct can_filter) * 3) < 0) { log_error("RX setsockopt CAN_RAW_FILTER failed"); } 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; } float GetMaxChargingVol(uint8_t index) { return maxChargingVol[index]; } float GetMaxCharginigCur(uint8_t index) { return maxChargingCur[index]; } static void SendCommunicationOnly(uint8_t index) { struct ChargingInfoData *pDcCharginigInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index); uint8_t targetID = pDcCharginigInfo->Evboard_id; /* if (pSysConfig->TotalConnectorCount == 1 && pDcCharginigInfo->Type == _Type_CCS_2 && ShmDcCommonData->CcsVersion == _CCS_VERSION_CHECK_TAG_V015S0) { targetID += 1; } */ SetChargingPermission(index, COMMUNICATION, pDcCharginigInfo->AvailableChargingPower, 0, 0, targetID); } static void SendStopOnly(uint8_t index) { struct ChargingInfoData *pDcCharginigInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index); uint8_t targetID = pDcCharginigInfo->Evboard_id; /* if (pSysConfig->TotalConnectorCount == 1 && pDcCharginigInfo->Type == _Type_CCS_2 && ShmDcCommonData->CcsVersion == _CCS_VERSION_CHECK_TAG_V015S0) { targetID += 1; } */ SetChargingPermission(index, STOP, pDcCharginigInfo->AvailableChargingPower, 0, 0, targetID); } static uint8_t GetStopChargingReasonByEvse(uint8_t gunIndex, uint8_t *reason) { uint8_t result = NO; struct ChargingInfoData *pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex); if (pAlarmCode->AlarmEvents.bits.EmergencyStopTrip == 0x01) { // 012251 *(reason + 5) = 0; *(reason + 4) = 1; *(reason + 3) = 2; *(reason + 2) = 2; *(reason + 1) = 5; *(reason + 0) = 1; result = YES; } if (pDcChargingInfo->Type == _Type_Chademo) { if (pFaultCode->FaultEvents.bits.ChademoOutputRelayDrivingFault == YES) { // 011012 *(reason + 5) = 0; *(reason + 4) = 1; *(reason + 3) = 1; *(reason + 2) = 0; *(reason + 1) = 1; *(reason + 0) = 2; result = YES; } else if (pAlarmCode->AlarmEvents.bits.ChademoOutputUVPFail == YES) { // 012289 *(reason + 5) = 0; *(reason + 4) = 1; *(reason + 3) = 2; *(reason + 2) = 2; *(reason + 1) = 8; *(reason + 0) = 9; result = YES; } else if (pAlarmCode->AlarmEvents.bits.ChademoGfdTrip == YES) { // 012234 *(reason + 5) = 0; *(reason + 4) = 1; *(reason + 3) = 2; *(reason + 2) = 2; *(reason + 1) = 3; *(reason + 0) = 4; result = YES; } } else if (pDcChargingInfo->Type == _Type_GB) { if (pFaultCode->FaultEvents.bits.ChademoOutputRelayDrivingFault == YES) { // 012290 *(reason + 5) = 0; *(reason + 4) = 1; *(reason + 3) = 2; *(reason + 2) = 2; *(reason + 1) = 9; *(reason + 0) = 0; result = YES; } else if (pAlarmCode->AlarmEvents.bits.GbGfdTrip == YES) { // 012236 *(reason + 5) = 0; *(reason + 4) = 1; *(reason + 3) = 2; *(reason + 2) = 2; *(reason + 1) = 3; *(reason + 0) = 6; result = YES; } } else if (pDcChargingInfo->Type == _Type_CCS_2) { if (pFaultCode->FaultEvents.bits.CcsOutputRelayDrivingFault == YES) { // 011014 *(reason + 5) = 0; *(reason + 4) = 1; *(reason + 3) = 1; *(reason + 2) = 0; *(reason + 1) = 1; *(reason + 0) = 4; result = YES; } else if (pAlarmCode->AlarmEvents.bits.CcsOutputUVPFail == YES) { // 012288 *(reason + 5) = 0; *(reason + 4) = 1; *(reason + 3) = 2; *(reason + 2) = 2; *(reason + 1) = 8; *(reason + 0) = 8; result = YES; } else if (pAlarmCode->AlarmEvents.bits.CcsGfdTrip == YES) { // 012235 *(reason + 5) = 0; *(reason + 4) = 1; *(reason + 3) = 2; *(reason + 2) = 2; *(reason + 1) = 3; *(reason + 0) = 5; result = YES; } } return result; } static void setCurrentOutput(void) { struct ChargingInfoData *chargingData_1 = NULL; struct ChargingInfoData *chargingData_2 = NULL; if (pSysConfig->TotalConnectorCount == 1) { chargingData_1 = (struct ChargingInfoData *)GetDcChargingInfoData(0); //chargingData_2 = (struct ChargingInfoData *)GetDcChargingInfoData(0); if (chargingData_1->FireChargingVoltage <= 500) { //DS60-120 add chargingData_1->PresentChargingCurrent = 0; } } else if (pSysConfig->TotalConnectorCount == 2) { chargingData_1 = (struct ChargingInfoData *)GetDcChargingInfoData(0); chargingData_2 = (struct ChargingInfoData *)GetDcChargingInfoData(1); if (chargingData_1->FireChargingVoltage <= 500) { //DS60-120 add chargingData_1->PresentChargingCurrent = 0; } if (chargingData_2->FireChargingVoltage <= 500) { chargingData_2->PresentChargingCurrent = 0; } } } void GetOtpPwrOrCurMethod(struct ChargingInfoData* chargingData, float* pow, float* cur) { if (((chargingData->ConnectorTemp >= STAGE1_GUN_DERATING_TEMP && chargingData->ConnectorTemp < STAGE2_GUN_DERATING_TEMP) || (chargingData->ChillerTemp >= STAGE1_GUN_DERATING_TEMP && chargingData->ChillerTemp < STAGE2_GUN_DERATING_TEMP)) && chargingData->deratingByConnOtp.deratingIndex < 1) { chargingData->deratingByConnOtp.deratingIndex = 1; } else if ((chargingData->ConnectorTemp >= STAGE2_GUN_DERATING_TEMP || chargingData->ChillerTemp >= STAGE2_GUN_DERATING_TEMP) && chargingData->ConnectorTemp != UNDEFINED_TEMP && chargingData->ChillerTemp != UNDEFINED_TEMP && chargingData->deratingByConnOtp.deratingIndex < 2) { chargingData->deratingByConnOtp.deratingIndex = 2; } if (chargingData->deratingByConnOtp.deratingTargetRate[chargingData->deratingByConnOtp.deratingIndex] != 0) { *pow *= chargingData->deratingByConnOtp.deratingTargetRate[chargingData->deratingByConnOtp.deratingIndex]; } else if (chargingData->deratingByConnOtp.deratingTargetCurrent[chargingData->deratingByConnOtp.deratingIndex] != 0) { if (*cur > chargingData->deratingByConnOtp.deratingTargetCurrent[chargingData->deratingByConnOtp.deratingIndex]) *cur = chargingData->deratingByConnOtp.deratingTargetCurrent[chargingData->deratingByConnOtp.deratingIndex]; } } static void SetPresentChargingOutputCap(void) { float pow1 = 0, cur1 = 0; float pow2 = 0, cur2 = 0; struct ChargingInfoData *chargingData_1 = NULL; struct ChargingInfoData *chargingData_2 = NULL; struct PrimaryMcuData* ShmPrimaryMcuData = (struct PrimaryMcuData*)GetShmPrimaryMcuData(); if (pSysConfig->TotalConnectorCount == 1) { chargingData_1 = (struct ChargingInfoData *)GetDcChargingInfoData(0); chargingData_2 = (struct ChargingInfoData *)GetDcChargingInfoData(0); } else if (pSysConfig->TotalConnectorCount == 2) { chargingData_1 = (struct ChargingInfoData *)GetDcChargingInfoData(0); chargingData_2 = (struct ChargingInfoData *)GetDcChargingInfoData(1); } #if !defined DD360 && !defined DD360Audi && !defined DD360ComBox float vol = 0; #endif //!defined DD360 && !defined DD360Audi pow1 = chargingData_1->AvailableChargingPower; cur1 = chargingData_1->AvailableChargingCurrent; #if !defined DD360 && !defined DD360Audi && !defined DD360ComBox vol = chargingData_1->MaximumChargingVoltage; GetMaxVolAndCurMethod(chargingData_1->Index, &vol, &cur1); GetMaxPowerMethod(chargingData_1->Index, &pow1); #endif //!defined DD360 && !defined DD360Audi //DS60-120 add if (pow1 <= 0) { cur1 = 0; } else { if (chargingData_1->SystemStatus == S_CHARGING && chargingData_1->FireChargingVoltage > 1500) { float maxCur = 0; maxCur = (pow1 * 1000) / chargingData_1->FireChargingVoltage; if (maxCur * 10 <= cur1) { //log_info("Gun1 -> MaxCharging Current = %f, Cap Current = %f ", (maxCur * 10), cur1); cur1 = maxCur * 10; } } } if (chargingData_1->deratingByConnOtp.isNeedDerating) { GetOtpPwrOrCurMethod(chargingData_1, &pow1, &cur1); if (deratingIndex[0] != chargingData_1->deratingByConnOtp.deratingIndex) { log_info("Gun0 Derating Index Set %d", chargingData_1->deratingByConnOtp.deratingIndex); deratingIndex[0] = chargingData_1->deratingByConnOtp.deratingIndex; } } pow2 = chargingData_2->AvailableChargingPower; cur2 = chargingData_2->AvailableChargingCurrent; #if !defined DD360 && !defined DD360Audi && !defined DD360ComBox vol = chargingData_2->MaximumChargingVoltage; GetMaxVolAndCurMethod(chargingData_2->Index, &vol, &cur2); GetMaxPowerMethod(chargingData_2->Index, &pow2); #endif //!defined DD360 && !defined DD360Audi //DS60-120 add if (pow2 <= 0) { cur2 = 0; } else { if (chargingData_2->SystemStatus == S_CHARGING && chargingData_2->FireChargingVoltage > 1500) { float maxCur = 0; maxCur = (pow2 * 1000) / chargingData_2->FireChargingVoltage; if (maxCur * 10 <= cur2) { //log_info("Gun2 -> MaxCharging Current = %f, Cap Current = %f ", (maxCur * 10), cur2); cur2 = maxCur * 10; } } } if (chargingData_2->deratingByConnOtp.isNeedDerating) { GetOtpPwrOrCurMethod(chargingData_2, &pow2, &cur2); if (deratingIndex[1] != chargingData_2->deratingByConnOtp.deratingIndex) { log_info("Gun1 Derating Index Set %d", chargingData_2->deratingByConnOtp.deratingIndex); deratingIndex[1] = chargingData_2->deratingByConnOtp.deratingIndex; } } // Chiller 錯誤或溫度降載 if (chargingData_1->ChillerTemp <= 70 && ShmDcCommonData->pGunInfo[0].withChiller && !ischillerHighTemp[0]) { ischillerHighTemp[0] = TRUE; if (cur1 > 2500) { log_info("Gun0 chiller temperature(%d) too high set current less than 250A", chargingData_1->ChillerTemp); cur1 = 2500; } } else if (chargingData_1->ChillerTemp > 75 && ischillerHighTemp[0]) { cur1 = 2500; } if (chargingData_2->ChillerTemp <= 70 && ShmDcCommonData->pGunInfo[1].withChiller && !ischillerHighTemp[1]) { ischillerHighTemp[1] = TRUE; if (cur2 > 2500) { log_info("Gun1 chiller temperature(%d) too high set current less than 250A", chargingData_2->ChillerTemp); cur2 = 2500; } } else if (chargingData_2->ChillerTemp > 75 && ischillerHighTemp[1]) { cur1 = 2500; } if (ShmPrimaryMcuData->InputDet.bits.Ac_Drop == ABNORMAL) { if (cur1 > 2500) { log_info("Gun0 chiller alarm set current less than 250A"); cur1 = 2500; } if (cur2 > 2500) { log_info("Gun1 chiller alarm set current less than 250A"); cur2 = 2500; } } //DS60-120 add if ((LogInfo[0][EV_LOG_OUTPUT_CAP_POW] <= pow1 - 5 || LogInfo[0][EV_LOG_OUTPUT_CAP_POW] >= pow1 + 5) || (LogInfo[0][EV_LOG_OUTPUT_CAP_CUR] <= cur1 - 5 || LogInfo[0][EV_LOG_OUTPUT_CAP_CUR] >= cur1 + 5) || (LogInfo[1][EV_LOG_OUTPUT_CAP_POW] <= pow2 - 5 || LogInfo[1][EV_LOG_OUTPUT_CAP_POW] >= pow2 + 5) || (LogInfo[1][EV_LOG_OUTPUT_CAP_CUR] <= cur2 - 5 || LogInfo[1][EV_LOG_OUTPUT_CAP_CUR] >= cur2 + 5) ) { //log_info("----------------------------------------------------- "); log_info("To EV (Real) Power_1 = %.1f, Cur_1 = %.1f, Power_2 = %.1f, Cur_2 = %.1f", pow1 / 10, cur1 / 10, pow2 / 10, cur2 / 10); //log_info("----------------------------------------------------- "); LogInfo[0][EV_LOG_OUTPUT_CAP_POW] = pow1; LogInfo[0][EV_LOG_OUTPUT_CAP_CUR] = cur1; LogInfo[1][EV_LOG_OUTPUT_CAP_POW] = pow2; LogInfo[1][EV_LOG_OUTPUT_CAP_CUR] = cur2; chargingData_1->RealMaxCurrent = cur1; chargingData_1->RealMaxPower = pow1; if (pSysConfig->TotalConnectorCount == 2) { chargingData_2->RealMaxCurrent = cur2; chargingData_2->RealMaxPower = pow2; } } SetPresentOutputCapacity(pow1, cur1, pow2, cur2); } static void GetMaxVolAndCurMethod(uint8_t index, float *vol, float *cur) { struct ChargingInfoData *pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(index); if (maxChargingVol[index] != 0 && maxChargingVol[index] <= *vol) { *vol = maxChargingVol[index]; } if (maxChargingCur[index] != 0 && maxChargingCur[index] <= *cur) { *cur = maxChargingCur[index]; } if (((pDcChargingInfo->SystemStatus >= S_PREPARING_FOR_EVSE && pDcChargingInfo->SystemStatus <= S_CHARGING) || (pDcChargingInfo->SystemStatus >= S_CCS_PRECHARGE_ST0 && pDcChargingInfo->SystemStatus <= S_CCS_PRECHARGE_ST1)) && pDcChargingInfo->ChargingProfileCurrent >= 0 && pDcChargingInfo->ChargingProfileCurrent <= *cur ) { *cur = pDcChargingInfo->ChargingProfileCurrent; } } static uint8_t waitPsuVolwithRealyVol(uint8_t gunIndex) { PcPsuOutput *pPcPsuOutput = (PcPsuOutput *)&ShmDcCommonData->PcPsuOutput[gunIndex]; struct ChargingInfoData *pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex); int vol = 0; vol = abs(pPcPsuOutput->Voltage - pDcChargingInfo->FireChargingVoltage); if (vol <= 10) { return YES; } return NO; } /** * [SetPresentChargingOutputFromPcPsu 充電狀態讀取電源櫃PSU輸出電壓電流,縮小誤差值] * @Author Jerry * @DateTime 2021-07-05 */ static void SetPresentChargingOutputFromPcPsu(uint8_t gunCount) { float vol1 = 0, cur1 = 0; float vol2 = 0, cur2 = 0; PcPsuOutput *pPcPsuOutput0 = NULL; PcPsuOutput *pPcPsuOutput1 = NULL; struct ChargingInfoData *chargingData0 = NULL; struct ChargingInfoData *chargingData1 = NULL; switch (gunCount) { case 1: pPcPsuOutput0 = (PcPsuOutput *)&ShmDcCommonData->PcPsuOutput[0]; pPcPsuOutput1 = (PcPsuOutput *)&ShmDcCommonData->PcPsuOutput[0]; chargingData0 = (struct ChargingInfoData *)GetDcChargingInfoData(0); chargingData1 = (struct ChargingInfoData *)GetDcChargingInfoData(0); break; case 2: pPcPsuOutput0 = (PcPsuOutput *)&ShmDcCommonData->PcPsuOutput[0]; pPcPsuOutput1 = (PcPsuOutput *)&ShmDcCommonData->PcPsuOutput[1]; chargingData0 = (struct ChargingInfoData *)GetDcChargingInfoData(0); chargingData1 = (struct ChargingInfoData *)GetDcChargingInfoData(1); break; } vol1 = pPcPsuOutput0->Voltage == 0 ? chargingData0->FireChargingVoltage : (((float)pPcPsuOutput0->Voltage)); cur1 = (chargingData0->PresentChargingCurrent * 10);//(((float)pPcPsuOutput0->Current) * 0.1); vol2 = pPcPsuOutput1->Voltage == 0 ? chargingData1->FireChargingVoltage : (((float)pPcPsuOutput1->Voltage)); cur2 = (chargingData1->PresentChargingCurrent * 10);//(((float)pPcPsuOutput1->Current) * 0.1); if ( (LogInfo[0][EV_LOG_NOW_OUTPUT_VOL] >= vol1 + CHK_VOL_RANGE) || (LogInfo[0][EV_LOG_NOW_OUTPUT_VOL] <= vol1 - CHK_VOL_RANGE) || (LogInfo[0][EV_LOG_NOW_OUTPUT_CUR] >= cur1 + CHK_CUR_RANGE) || (LogInfo[0][EV_LOG_NOW_OUTPUT_CUR] <= cur1 - CHK_CUR_RANGE) || (LogInfo[1][EV_LOG_NOW_OUTPUT_VOL] >= vol2 + CHK_VOL_RANGE) || (LogInfo[1][EV_LOG_NOW_OUTPUT_VOL] <= vol2 - CHK_VOL_RANGE) || (LogInfo[1][EV_LOG_NOW_OUTPUT_CUR] >= cur2 + CHK_CUR_RANGE) || (LogInfo[1][EV_LOG_NOW_OUTPUT_CUR] <= cur2 - CHK_CUR_RANGE) ) { log_info("G1->Out Vol=%.1f,Out Cur=%.1f - G2->Out Vol=%.1f,Out Cur=%.1f", vol1, cur1 / 10, vol2, cur2 / 10); LogInfo[0][EV_LOG_NOW_OUTPUT_VOL] = vol1; LogInfo[0][EV_LOG_NOW_OUTPUT_CUR] = cur1; LogInfo[1][EV_LOG_NOW_OUTPUT_VOL] = vol2; LogInfo[1][EV_LOG_NOW_OUTPUT_CUR] = cur2; } SetPresentOutputPower(vol1, cur1, vol2, cur2); } static void SetPresentChargingOutputPower(void) { float vol1 = 0, cur1 = 0; float vol2 = 0, cur2 = 0; PcPsuOutput *pPcPsuOutput1 = NULL; PcPsuOutput *pPcPsuOutput2 = NULL; struct ChargingInfoData *chargingData_1 = NULL; struct ChargingInfoData *chargingData_2 = NULL; bool isPsuVol1 = false, isPsuVol2 = false, isPsuCur1 = false, isPsuCur2 = false; if (pSysConfig->TotalConnectorCount == 1) { pPcPsuOutput1 = (PcPsuOutput *)&ShmDcCommonData->PcPsuOutput[0]; pPcPsuOutput2 = (PcPsuOutput *)&ShmDcCommonData->PcPsuOutput[0]; chargingData_1 = (struct ChargingInfoData *)GetDcChargingInfoData(0); chargingData_2 = (struct ChargingInfoData *)GetDcChargingInfoData(0); } else if (pSysConfig->TotalConnectorCount == 2) { pPcPsuOutput1 = (PcPsuOutput *)&ShmDcCommonData->PcPsuOutput[0]; pPcPsuOutput2 = (PcPsuOutput *)&ShmDcCommonData->PcPsuOutput[1]; chargingData_1 = (struct ChargingInfoData *)GetDcChargingInfoData(0); chargingData_2 = (struct ChargingInfoData *)GetDcChargingInfoData(1); } psuOutputReady[0] = chargingData_1->SystemStatus != S_CHARGING ? false : psuOutputReady[0]; psuOutputReady[1] = chargingData_2->SystemStatus != S_CHARGING ? false : psuOutputReady[1]; isPsuVol1 = chargingData_1->PantographFlag ? true : (pPcPsuOutput1->Voltage != 0 && psuOutputReady[0] == true); isPsuVol2 = chargingData_2->PantographFlag ? true : (pPcPsuOutput2->Voltage != 0 && psuOutputReady[1] == true); isPsuCur1 = chargingData_1->PantographFlag ? true : false; isPsuCur2 = chargingData_2->PantographFlag ? true : false; //vol1 = chargingData_1->FireChargingVoltage; vol1 = isPsuVol1 == false ? chargingData_1->FireChargingVoltage : (((float)pPcPsuOutput1->Voltage)); cur1 = isPsuCur1 == false ? (chargingData_1->PresentChargingCurrent * 10) : pPcPsuOutput1->Current; //vol2 = chargingData_2->FireChargingVoltage; vol2 = isPsuVol2 == false ? chargingData_2->FireChargingVoltage : (((float)pPcPsuOutput2->Voltage)); cur2 = isPsuCur2 == false ? (chargingData_2->PresentChargingCurrent * 10) : pPcPsuOutput2->Current; //DS60-120 add if ((LogInfo[0][EV_LOG_NOW_OUTPUT_VOL] >= vol1 + CHK_VOL_RANGE) || (LogInfo[0][EV_LOG_NOW_OUTPUT_VOL] <= vol1 - CHK_VOL_RANGE) || (LogInfo[0][EV_LOG_NOW_OUTPUT_CUR] >= cur1 + CHK_CUR_RANGE) || (LogInfo[0][EV_LOG_NOW_OUTPUT_CUR] <= cur1 - CHK_CUR_RANGE) || (LogInfo[1][EV_LOG_NOW_OUTPUT_VOL] >= vol2 + CHK_VOL_RANGE) || (LogInfo[1][EV_LOG_NOW_OUTPUT_VOL] <= vol2 - CHK_VOL_RANGE) || (LogInfo[1][EV_LOG_NOW_OUTPUT_CUR] >= cur2 + CHK_CUR_RANGE) || (LogInfo[1][EV_LOG_NOW_OUTPUT_CUR] <= cur2 - CHK_CUR_RANGE) ) { log_info("G1-> Vol=%.1f, Cur=%.1f - G2-> Vol = %.1f, Cur = %.1f", vol1 / 10, cur1 / 10, vol2 / 10, cur2 / 10); LogInfo[0][EV_LOG_NOW_OUTPUT_VOL] = vol1; LogInfo[0][EV_LOG_NOW_OUTPUT_CUR] = cur1; LogInfo[1][EV_LOG_NOW_OUTPUT_VOL] = vol2; LogInfo[1][EV_LOG_NOW_OUTPUT_CUR] = cur2; } //if (_outVol_1 != vol1 || // _outCur_1 != cur1 || // _outVol_2 != vol2 || // _outCur_2 != cur2) { /*log_info("G1 -> Output Vol = %f, Output Cur = %f -- G2 -> Output Vol = %f, Output Cur = %f ", vol1, cur1, vol2, cur2); */ // _outVol_1 = vol1; _outCur_1 = cur1; _outVol_2 = vol2; _outCur_2 = cur2; //} SetPresentOutputPower(vol1, cur1, vol2, cur2); } static void checkConnectorOVPState(uint8_t gunIndex) { struct ChargingInfoData *pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex); // 避免槍溫偵測誤判 static uint8_t gunTempAllowCount[2] = {0}; bool isOTP = false; switch (pDcChargingInfo->Type) { case _Type_Chademo: if (ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaConnectOTP) { isOTP = true; } break; case _Type_CCS_2: if (ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSConnectOTP) { isOTP = true; } break; case _Type_GB: if (ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTConnectOTP) { isOTP = true; } break; } if (ShmDcCommonData->ChillerTempErr[gunIndex].StatusBit.ChillerOTP == YES) { isOTP = true; } if (isOTP) { if (gunTempAllowCount[gunIndex] >= 2) { pDcChargingInfo->StopChargeFlag = YES; } else { gunTempAllowCount[gunIndex] += 1; } } else { gunTempAllowCount[gunIndex] = 0; } } static time_t GetRtcInfoForEpoch(void) { struct timeb csuTime; struct tm *tmCSU; struct tm t; time_t result; ftime(&csuTime); tmCSU = localtime(&csuTime.time); t.tm_year = tmCSU->tm_year; t.tm_mon = tmCSU->tm_mon; t.tm_mday = tmCSU->tm_mday; t.tm_hour = tmCSU->tm_hour; t.tm_min = tmCSU->tm_min; t.tm_sec = tmCSU->tm_sec; t.tm_isdst = -1; result = mktime(&t); return result; } static void FormatVoltageAndCurrent(void) { uint8_t gunIndex = 0; ParsingRatedCur parsingRatedCur = {0}; RateCurInfo *pRatedCurInfo = NULL; if (RatedCurrentParsing((char *)pSysConfig->ModelName, &parsingRatedCur) != PASS) { log_error("Parsing rated current failed"); return; } maxChargingPow = parsingRatedCur.Power; for (gunIndex = 0; gunIndex < pSysConfig->TotalConnectorCount; gunIndex++) { pRatedCurInfo = (RateCurInfo *)&parsingRatedCur.ParsingInfo[gunIndex]; maxChargingVol[gunIndex] = pRatedCurInfo->Voltage; maxChargingCur[gunIndex] = pRatedCurInfo->Current; log_info("Conn %d GunType = %d, MaxVol = %f, MaxCur = %f ", gunIndex, pRatedCurInfo->GunType, maxChargingVol[gunIndex], maxChargingCur[gunIndex]); } } static 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; } void CalOutputPowerAndEnergy(int _index) { struct ChargingInfoData *pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(_index); ShmCsuMeterData = (struct MeterInformation *)GetShmCsuMeterData(); if (pSysConfig->ModelName[3] == 'P') { // DC Meter if (ShmDcCommonData->pGunInfo[_index].curMeterValue == 0) { ShmDcCommonData->pGunInfo[_index].curMeterValue = pSysInfo->DcMeterInfo[_index].totlizeImportEnergy; } else { if (pSysInfo->DcMeterInfo[_index].totlizeImportEnergy >= ShmDcCommonData->pGunInfo[_index].curMeterValue) { ShmDcCommonData->pGunInfo[_index]._curTotalCharging += (pSysInfo->DcMeterInfo[_index].totlizeImportEnergy - ShmDcCommonData->pGunInfo[_index].curMeterValue); float totalChargingValue = (float)ShmDcCommonData->pGunInfo[_index]._curTotalCharging; ShmDcCommonData->pGunInfo[_index].curMeterValue = pSysInfo->DcMeterInfo[_index].totlizeImportEnergy; if (totalChargingValue > pDcChargingInfo->PresentChargedEnergy) { ShmDcCommonData->energy_time_period[_index][ShmDcCommonData->_hour_index] += totalChargingValue - pDcChargingInfo->PresentChargedEnergy; pDcChargingInfo->presentChargedEnergyPeriod[ShmDcCommonData->_hour_index] += totalChargingValue - pDcChargingInfo->PresentChargedEnergy; } if (pDcChargingInfo->SystemStatus == S_CHARGING) { pDcChargingInfo->PresentChargedEnergy = totalChargingValue; ShmDcCommonData->pGunInfo[_index].PowerConsumption += totalChargingValue; } else { pDcChargingInfo->PresentChargedEnergy = (float ) pSysInfo->DcMeterTransactionResult[_index].energyImport; if (pSysInfo->DcMeterTransactionAction[_index].OcmfInfoReady) { ShmDcCommonData->pGunInfo[_index].PowerConsumption = (float ) pSysInfo->DcMeterTransactionResult[_index].energyImportTotalStop; ShmDcCommonData->pGunInfo[_index].isMeterStop = TRUE; } } //pDcChargingInfo->PresentChargedEnergy = totalChargingValue; if (pSysConfig->BillingData.isBilling) { if(strcmp((char *)pSysConfig->OcppServerURL, "") == EQUAL || strcmp((char *)pSysConfig->ChargeBoxId, "") == EQUAL) pDcChargingInfo->ChargingFee = totalChargingValue * pSysConfig->BillingData.Cur_fee; } } } } else { if (chargingTime[_index] == 0 || chargingTime[_index] > pDcChargingInfo->PresentChargedDuration) { chargingTime[_index] = pDcChargingInfo->PresentChargedDuration; } else { int passTime = pDcChargingInfo->PresentChargedDuration - chargingTime[_index]; if (passTime > 0) { float changingPow = (pDcChargingInfo->PresentChargingPower) * passTime / 3600; if (pSysConfig->BillingData.isBilling) { ShmDcCommonData->energy_time_period[_index][ShmDcCommonData->_hour_index] += changingPow; pDcChargingInfo->presentChargedEnergyPeriod[ShmDcCommonData->_hour_index] += changingPow; if(strcmp((char *)pSysConfig->OcppServerURL, "") == EQUAL || strcmp((char *)pSysConfig->ChargeBoxId, "") == EQUAL) pDcChargingInfo->ChargingFee += changingPow * pSysConfig->BillingData.Cur_fee; } pDcChargingInfo->PowerConsumption += changingPow; ShmDcCommonData->pGunInfo[_index].PowerConsumption += changingPow; pDcChargingInfo->PresentChargedEnergy += changingPow; chargingTime[_index] = pDcChargingInfo->PresentChargedDuration; } } } } int main(int argc, char *argv[]) { bool chkChademoPermission[2] = {false}; int isContinue = 1; uint8_t gunIndex = 0; uint8_t typeIndex = 0; uint8_t priorityLow = 1; uint8_t SendErrorCount[2] = {0, 0}; uint8_t gfgResult = 0; uint32_t _timeBuf = 0; uint32_t chargingTime[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY] = {0}; float maxVol, maxCur; struct timespec _chk_ratingPower_timeout[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY]; struct timespec _chk_chademo_permission_timeout[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY]; time_t rtc = {0}; struct ChargingInfoData *pDcChargingInfo = NULL; struct timeb waitChargingTime; struct timeb nowTime; uint8_t Comcont = 0; uint8_t evstatus; if (CreateAllCsuShareMemory() == FAIL) { log_error("create share memory error"); return FAIL; } MappingGunChargingInfo("EvComm Task"); pSysConfig = (struct SysConfigData *)GetShmSysConfigData(); pSysInfo = (struct SysInfoData *)GetShmSysInfoData(); pAlarmCode = (struct AlarmCodeData *)GetShmAlarmCodeData(); pFaultCode = (struct FaultCodeData *)GetShmFaultCodeData(); ShmDcCommonData = (DcCommonInfo *)GetShmDcCommonData(); ShmCHAdeMOData = (struct CHAdeMOData *)GetShmCHAdeMOData(); ShmGBTData = (struct GBTData *)GetShmGBTData(); ShmCcsData = (struct CcsData *)GetShmCcsData(); ShmSelectGunInfo = (SelectGunInfo *)GetShmSelectGunInfo(); ShmCsuMeterData = (struct MeterInformation *)GetShmCsuMeterData(); CanFd = InitCanBus(); FormatVoltageAndCurrent(); signal(SIGCHLD,SIG_IGN); CANReceiver(CanFd); rtc = GetRtcInfoForEpoch(); while (isContinue) { for (gunIndex = 0; gunIndex < pSysConfig->TotalConnectorCount; gunIndex++) { pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gunIndex); typeIndex = pDcChargingInfo->type_index; if (priorityLow == 1) { // 優先權較低 - 只要有回應即不會再詢問 if (pDcChargingInfo->Type == _Type_Chademo && ShmCHAdeMOData->evse[typeIndex].SelfTest_Comp != PASS) { SyncRtcInfo(gunIndex, pDcChargingInfo->Evboard_id, (int)rtc); GetFirmwareVersion(gunIndex, pDcChargingInfo->Evboard_id); } else if (pDcChargingInfo->Type == _Type_GB && ShmGBTData->evse[typeIndex].SelfTest_Comp != PASS) { SyncRtcInfo(gunIndex, pDcChargingInfo->Evboard_id, (int)rtc); GetFirmwareVersion(gunIndex, pDcChargingInfo->Evboard_id); } else if (pDcChargingInfo->Type == _Type_CCS_2) { if (ShmCcsData->CommProtocol == _CCS_COMM_V2GMessage_DIN70121 && ShmCcsData->V2GMessage_DIN70121[typeIndex].SelfTest_Comp != PASS) { SyncRtcInfo(gunIndex, pDcChargingInfo->Evboard_id, (int)rtc); GetFirmwareVersion(gunIndex, pDcChargingInfo->Evboard_id); } } /* if (pDcChargingInfo->Type == _Type_Chademo) { pAlarmCode->AlarmEvents.bits.ChademoboardStestFail = (ShmCHAdeMOData->evse[typeIndex].SelfTest_Comp != PASS) ? true : false; pAlarmCode->AlarmEvents.bits.ChademoModuleCommFail = ( CanFd < 0 ) ? true : false; } else if (pDcChargingInfo->Type == _Type_GB) { pAlarmCode->AlarmEvents.bits.GbtboardStestFail = (ShmGBTData->evse[typeIndex].SelfTest_Comp != PASS) ? true : false; pAlarmCode->AlarmEvents.bits.mFail = ( CanFd < 0 ) ? true : false; } else if (pDcChargingInfo->Type == _Type_CCS_2) { pAlarmCode->AlarmEvents.bits.CCSboardStestFail = (ShmCcsData->V2GMessage_DIN70121[typeIndex].SelfTest_Comp != PASS) ? true : false; pAlarmCode->AlarmEvents.bits.ChademoModuleCommFail = ( CanFd < 0 ) ? true : false; }*/ //固定要取得的資訊 : 1.槍鎖狀態, 2."Connector 1" 溫度, 3."Connector 2" 溫度, 4.Pilot Voltage //log_info("GetMiscellaneousInfo. index = %d, Eid = %d ", // gunIndex, // pDcChargingInfo->Evboard_id); GetMiscellaneousInfo(gunIndex, pDcChargingInfo->RelayK1K2Status, pDcChargingInfo->PresentChargedEnergy, (pDcChargingInfo->PresentChargingVoltage * 10), pDcChargingInfo->Evboard_id); //checkConnectorOVPState(gunIndex); } switch (pDcChargingInfo->SystemStatus) { case S_IDLE: case S_RESERVATION: if (pDcChargingInfo->Type == _Type_Chademo) { ClearAbnormalStatus_Chademo(gunIndex); if (pSysInfo->PageIndex == _LCM_WAIT_FOR_PLUG) { if (!chkChademoPermission[gunIndex]) { chkChademoPermission[gunIndex] = true; GetClockTime(&_chk_chademo_permission_timeout[gunIndex], NULL); SendCommunicationOnly(gunIndex); log_info("Send Communication command"); } else { _timeBuf = GetClockTimeoutValue(_chk_chademo_permission_timeout[gunIndex]); if (_timeBuf < 0) { GetClockTime(&_chk_chademo_permission_timeout[gunIndex], NULL); } else { if (_timeBuf / 1000 > 10000) { SendCommunicationOnly(gunIndex); log_info("Send Communication command"); GetClockTime(&_chk_chademo_permission_timeout[gunIndex], NULL); } } } } else if (chkChademoPermission[gunIndex]) { chkChademoPermission[gunIndex] = false; SendStopOnly(gunIndex); } if (ShmDcCommonData->ConnectErrList[gunIndex].GunBits.ChaConnectOTP == NO) { pDcChargingInfo->StopChargeFlag = NO; } } else if (pDcChargingInfo->Type == _Type_GB) { ClearAbnormalStatus_GB(gunIndex); if (ShmDcCommonData->ConnectErrList[gunIndex].GunBits.GBTConnectOTP == NO) { pDcChargingInfo->StopChargeFlag = NO; } } else if (pDcChargingInfo->Type == _Type_CCS_2) { ClearAbnormalStatus_CCS(gunIndex); if (ShmDcCommonData->ConnectErrList[gunIndex].GunBits.CCSConnectOTP == NO) { pDcChargingInfo->StopChargeFlag = NO; } } // Set Ev board in communication mode // Get EVCCID for authorize when gun plug-in only for CCS if ( pDcChargingInfo->ConnectorPlugIn && pSysConfig->isAuthrizeByEVCCID && ShmCcsData->CommProtocol == _CCS_COMM_V2GMessage_DIN70121) { if (Comcont == 1 && evstatus < 15) { GetEVCCIDReq(gunIndex,pDcChargingInfo->Evboard_id); SendCommunicationOnly(gunIndex); } } if (ShmCcsData->CommProtocol == _CCS_COMM_V2GMessage_DIN70121 && priorityLow == 1) { GetOutputReq(gunIndex,pDcChargingInfo->Evboard_id); if (evstatus != ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].PresentMsgFlowStatus) { evstatus = ShmCcsData->V2GMessage_DIN70121[pDcChargingInfo->type_index].PresentMsgFlowStatus; } if ( evstatus > 19 && evstatus < 255 ) GetEVCCIDReq(gunIndex,pDcChargingInfo->Evboard_id); } if (priorityLow == 1) { pDcChargingInfo->PresentChargedEnergy = 0; pDcChargingInfo->PresentChargingPower = 0; pDcChargingInfo->GroundFaultStatus = GFD_WAIT; pDcChargingInfo->RealRatingPower = 0; pDcChargingInfo->StopChargeFlag = NO; pDcChargingInfo->NormalStopChargeFlag = NO;//DS60-120 add pDcChargingInfo->ChargingFee = 0.0; pDcChargingInfo->EvBatterySoc = 0; pDcChargingInfo->EvBatteryStartSoc = 0; //DS60-120 add pDcChargingInfo->EvBatteryMaxVoltage = 0; //DS60-120 add pDcChargingInfo->ChargingProfilePower = -1; //DS60-120 add pDcChargingInfo->ChargingProfileCurrent = -1; //DS60-120 add if (pSysInfo->MainChargingMode == _MAIN_CHARGING_MODE_MAX) { //DS60-120 add pDcChargingInfo->PresentChargingVoltage = 0; pDcChargingInfo->PresentChargingCurrent = 0; pDcChargingInfo->EvBatteryMaxVoltage = 0; } chargingTime[gunIndex] = 0; //maxChargingCur[gunIndex] = pSysConfig->MaxChargingCurrent * 10; //maxChargingPow = (pSysConfig->MaxChargingPower * 10); //DS60-120 add SendErrorCount[gunIndex] = 0; if (pSysConfig->ModelName[3] == 'P') { ShmCsuMeterData->_meter[gunIndex].curMeterValue = 0; ShmCsuMeterData->_meter[gunIndex]._chargingValue = 0; ShmCsuMeterData->_meter[gunIndex]._curTotalCharging = 0; } //maxChargingPow = pSysConfig->MaxChargingPower * 10; // ShmPsuData->SystemAvailablePower 已是 * 10 //maxChargingPow = ShmPsuData->SystemAvailablePower; if (pSysConfig->MaxChargingPower * 10 != 0 && pSysConfig->MaxChargingPower * 10 < maxChargingPow) { maxChargingPow = pSysConfig->MaxChargingPower * 10; } LogInfo[gunIndex][EV_LOG_EVSE_MAX_VOL] = 0; LogInfo[gunIndex][EV_LOG_EVSE_MAX_CUR] = 0; LogInfo[gunIndex][EV_LOG_MAX_BATT_VOL] = 0; LogInfo[gunIndex][EV_LOG_SOC] = 0; SetPresentChargingOutputPower(); } break; case S_PREPARNING: chkChademoPermission[gunIndex] = false; //DS60-120 add // 設定當前輸出 SetPresentChargingOutputPower(); pDcChargingInfo->PowerConsumption = 0; break; case S_PREPARING_FOR_EV: // 開始確認車端是否同意開始充電 : 1.SOC, 2.Target Vol, 3.Target Cur, 4.Charging remaining time GetOutputReq(gunIndex, pDcChargingInfo->Evboard_id); //log_info("PresentChargingVoltage = %f ", pDcChargingInfo->PresentChargingVoltage); //log_info("PresentChargingCurrent = %f ", pDcChargingInfo->PresentChargingCurrent); //log_info("AvailableChargingPower = %f ", pDcChargingInfo->AvailableChargingPower); //log_info("AvailableChargingCurrent = %f ", pDcChargingInfo->AvailableChargingCurrent); //log_info("MaximumChargingVoltage = %f ", pDcChargingInfo->MaximumChargingVoltage); // 設定當前輸出 SetPresentChargingOutputPower(); if (ShmSelectGunInfo->WaitDoCommPermission[gunIndex] == YES) { ShmSelectGunInfo->WaitDoCommPermission[gunIndex] = NO; //if (priorityLow == 1) { // 樁端輸出能力 maxVol = pDcChargingInfo->MaximumChargingVoltage; maxCur = pDcChargingInfo->AvailableChargingCurrent; GetMaxVolAndCurMethod(gunIndex, &maxVol, &maxCur); //DS60-120 add if (LogInfo[gunIndex][EV_LOG_EVSE_MAX_VOL] != maxVol || LogInfo[gunIndex][EV_LOG_EVSE_MAX_CUR] != maxCur) { LogInfo[gunIndex][EV_LOG_EVSE_MAX_VOL] = maxVol; LogInfo[gunIndex][EV_LOG_EVSE_MAX_CUR] = maxCur; log_info("To EV_%d Max_Vol = %.1f, Cap_Cur = %.1f, Cap_Pow = %.1f", gunIndex, maxVol / 10, maxCur / 10, pDcChargingInfo->AvailableChargingPower / 10); } pDcChargingInfo->RealMaxVoltage = maxVol; SetChargingPermission(gunIndex, START, pDcChargingInfo->AvailableChargingPower, maxCur, maxVol, pDcChargingInfo->Evboard_id); // 取得車端電池資訊 : 1.AC or DC ? 2.Total battery cap, 3.Max battery vol, 4.Max battery cur GetEvBatteryInfo(gunIndex, pDcChargingInfo->Evboard_id); } GetClockTime(&_chk_ratingPower_timeout[gunIndex], NULL); break; case S_PREPARING_FOR_EVSE: case S_CCS_PRECHARGE_ST0: case S_CCS_PRECHARGE_ST1: // 開始確認車端是否同意開始充電 GetOutputReq(gunIndex, pDcChargingInfo->Evboard_id); // 設定當前輸出 SetPresentChargingOutputPower(); if (priorityLow % 5 == 1) { // 取得車端電池資訊 : 1.AC or DC ? 2.Total battery cap, 3.Max battery vol, 4.Max battery cur GetEvBatteryInfo(gunIndex, pDcChargingInfo->Evboard_id); //DS60-120 add // 樁端輸出能力改變 SetPresentChargingOutputCap(); } //DS60-120 add if (LogInfo[gunIndex][EV_LOG_MAX_BATT_VOL] != pDcChargingInfo->EvBatteryMaxVoltage) { LogInfo[gunIndex][EV_LOG_MAX_BATT_VOL] = pDcChargingInfo->EvBatteryMaxVoltage; log_info("index = %d, Ev Maximum Battery Voltage = %f ", gunIndex, pDcChargingInfo->EvBatteryMaxVoltage); } if (LogInfo[gunIndex][EV_LOG_SOC] != pDcChargingInfo->EvBatterySoc) { LogInfo[gunIndex][EV_LOG_SOC] = pDcChargingInfo->EvBatterySoc; log_info("index = %d, SOC = %d ", gunIndex, pDcChargingInfo->EvBatterySoc); } // 持續通知 Isolation 測試狀態 if (priorityLow == 1) { // 拉 500 V 如果在一秒鐘內 GFD 都符合則 PASS // if (_chargingData[_index]->FireChargingVoltage >= 3500) // pDcChargingInfo->GroundFaultStatus = GFD_PASS; //log_info("To EV_%d GFD = %d ", _index,pDcChargingInfo->GroundFaultStatus); //if(_chargingData[_index]->GroundFaultStatus != GFD_WAIT) { //if ((GetClockTimeoutValue(_derating_time) / 1000) > 1000) gfgResult = pDcChargingInfo->GroundFaultStatus; // GB & Chademo ~ Warning 也先算 Pass,因為 CCS 認證會驗 Warning 故不可更動 if (pDcChargingInfo->Type == _Type_Chademo || pDcChargingInfo->Type == _Type_GB) { if (gfgResult == GFD_WARNING) { gfgResult = GFD_PASS; } } if (gfgResult == GFD_WARNING || gfgResult == GFD_PASS) { if (((GetClockTimeoutValue(_chk_ratingPower_timeout[gunIndex]) / 1000) > 12000 && pDcChargingInfo->RealRatingPower > 0) || (GetClockTimeoutValue(_chk_ratingPower_timeout[gunIndex]) / 1000) > 14000) { //log_info("**********EvComm : gunIndex= %d, RealRatingPower = %d ", // gunIndex,pDcChargingInfo->RealRatingPower); //gfgResult = GFD_PASS; //DS60-120 add if (LogInfo[gunIndex][EV_LOG_REAL_CAP_POW] != pDcChargingInfo->RealRatingPower) { LogInfo[gunIndex][EV_LOG_REAL_CAP_POW] = pDcChargingInfo->RealRatingPower; log_info("Conn %d, RealRatingPower = %d ", gunIndex, pDcChargingInfo->RealRatingPower); } } else { gfgResult = GFD_WAIT; } } SetIsolationStatus(gunIndex, gfgResult, pDcChargingInfo->Evboard_id); } if (pDcChargingInfo->SystemStatus == S_CCS_PRECHARGE_ST0 && pDcChargingInfo->PrechargeStatus == PRECHARGE_READY ) { SetEvsePrechargeInfo(gunIndex, PRECHARGE_PRERELAY_PASS, pDcChargingInfo->Evboard_id); } } ftime(&waitChargingTime); break; case S_CHARGING: //if (waitPsuVolwithRealyVol(gunIndex) == NO) { // continue; //} GetEvBatteryInfo(gunIndex, pDcChargingInfo->Evboard_id); //DS60-120 add // 計算 Power pDcChargingInfo->PresentChargingPower = ((float)((pDcChargingInfo->PresentChargingVoltage) * (pDcChargingInfo->PresentChargingCurrent)) / 1000); CalOutputPowerAndEnergy(gunIndex); /* //DS60-120 remove if (chargingTime[gunIndex] == 0 || chargingTime[gunIndex] > pDcChargingInfo->PresentChargedDuration) { chargingTime[gunIndex] = pDcChargingInfo->PresentChargedDuration; } else { int passTime = pDcChargingInfo->PresentChargedDuration - chargingTime[gunIndex]; if (passTime > 0) { float changingPow = (pDcChargingInfo->PresentChargingPower) * passTime / 3600; if (pSysConfig->BillingData.isBilling) { pDcChargingInfo->ChargingFee += changingPow * pSysConfig->BillingData.Cur_fee; } pDcChargingInfo->PresentChargedEnergy += changingPow; ShmDcCommonData->pGunInfo[gunIndex].PowerConsumption += changingPow; pDcChargingInfo->PowerConsumption += changingPow; chargingTime[gunIndex] = pDcChargingInfo->PresentChargedDuration; } } */ // 開始確認車端是否同意開始充電 GetOutputReq(gunIndex, pDcChargingInfo->Evboard_id); // 設定當前輸出 ftime(&nowTime); if (!(DiffTimeb(waitChargingTime, nowTime) < 5000 || DiffTimeb(waitChargingTime, nowTime) < 0)) { psuOutputReady[gunIndex] = true; } SetPresentChargingOutputPower(); // for test end if (priorityLow % 5 == 0) { // 樁端輸出能力改變 SetPresentChargingOutputCap(); } if ((pDcChargingInfo->GroundFaultStatus == GFD_FAIL) || (pDcChargingInfo->Type == _Type_CCS_2)) { SetIsolationStatus(gunIndex, pDcChargingInfo->GroundFaultStatus, pDcChargingInfo->Evboard_id); } /* else if (pDcChargingInfo->Type == _Type_CCS_2) { SetIsolationStatus(gunIndex, pDcChargingInfo->GroundFaultStatus, pDcChargingInfo->Evboard_id); }*/ // GFD 失敗再通知 if (priorityLow == 1) { if (pDcChargingInfo->Type == _Type_CCS_2 && pDcChargingInfo->PrechargeStatus == PRECHARGE_READY) { SetEvsePrechargeInfo(gunIndex, PRECHARGE_CHARELAY_PASS, pDcChargingInfo->Evboard_id); } } break; case S_ALARM: case S_TERMINATING: CalOutputPowerAndEnergy(gunIndex); // 設定當前輸出 setCurrentOutput(); SetPresentChargingOutputPower(); // 槍鎖還在,則代表是樁端要求的停止 if (pDcChargingInfo->GunLocked == START || pDcChargingInfo->Type == _Type_CCS_2) { uint8_t normalStop = 0x01; uint8_t stopReason[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; if (GetStopChargingReasonByEvse(gunIndex, stopReason)) { normalStop = 0x02; } EvseStopChargingEvent(normalStop, stopReason, pDcChargingInfo->Evboard_id); SendErrorCount[gunIndex] += 1; //DS60-120 add } if (pDcChargingInfo->Type == _Type_CCS_2) { SetIsolationStatus(gunIndex, pDcChargingInfo->GroundFaultStatus, pDcChargingInfo->Evboard_id); } GetOutputReq(gunIndex, pDcChargingInfo->Evboard_id); //DS60-120 add if (pDcChargingInfo->SystemStatus == S_ALARM) { if (priorityLow == 1) { // 樁端輸出能力 maxVol = pDcChargingInfo->MaximumChargingVoltage; maxCur = pDcChargingInfo->AvailableChargingCurrent; GetMaxVolAndCurMethod(gunIndex, &maxVol, &maxCur); SetChargingPermission(gunIndex, STOP, pDcChargingInfo->AvailableChargingPower, maxCur, maxVol, pDcChargingInfo->Evboard_id); } } break; case S_COMPLETE: // 設定當前輸出 SetPresentChargingOutputPower(); CalOutputPowerAndEnergy(gunIndex); if (priorityLow == 1) { // 樁端輸出能力 maxVol = pDcChargingInfo->MaximumChargingVoltage; maxCur = pDcChargingInfo->AvailableChargingCurrent; GetMaxVolAndCurMethod(gunIndex, &maxVol, &maxCur); SetChargingPermission(gunIndex, STOP, pDcChargingInfo->AvailableChargingPower, maxCur, maxVol, pDcChargingInfo->Evboard_id); //DS60-120 add //if (pDcChargingInfo->EvBatterySoc >= 100) { // //滿電,則直接清掉錯誤 // if (pDcChargingInfo->Type == _Type_Chademo) { // ClearAbnormalStatus_Chademo(gunIndex); // } else if (pDcChargingInfo->Type == _Type_GB) { // ClearAbnormalStatus_GB(gunIndex); // } else if (pDcChargingInfo->Type == _Type_CCS_2) { // ClearAbnormalStatus_CCS(gunIndex); // } //} } break; }//switch }//for Comcont >= 200 ? Comcont = 1: Comcont++; priorityLow >= 20 ? priorityLow = 1 : priorityLow++; usleep(50000); }//while return 0; }