/* * Module_SmartBox.c * * Created on: 2022�~5��3�� * Author: 7564 */ #include "Module_SmartBox.h" struct SysConfigAndInfo *ShmSysConfigAndInfo; struct StatusCodeData *ShmStatusCodeData; struct PsuData *ShmPsuData; struct DcCommonInformation *ShmDcCommonData; struct SmartBoxData *ShmSmartBoxData; struct ChargingInfoData *chargingInfo[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY]; byte ConnectorUsingSeq[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY][4] = {{0, 2, 3, 1}, {1, 3, 2, 0}}; struct timespec _log_time; #define DEBUG_INFO(format, args...) StoreLogMsg("[%s:%d][%s][Info] "format, __FILE__, __LINE__, __FUNCTION__, ##args) #define DEBUG_WARN(format, args...) StoreLogMsg("[%s:%d][%s][Warn] "format, __FILE__, __LINE__, __FUNCTION__, ##args) #define DEBUG_ERROR(format, args...) StoreLogMsg("[%s:%d][%s][Error] "format, __FILE__, __LINE__, __FUNCTION__, ##args) int StoreLogMsg(const char *fmt, ...) { char Buf[4096+256]; char buffer[4096]; va_list args; struct timeb SeqEndTime; struct tm *tm; va_start(args, fmt); int rc = vsnprintf(buffer, sizeof(buffer), fmt, args); va_end(args); memset(Buf,0,sizeof(Buf)); ftime(&SeqEndTime); SeqEndTime.time = time(NULL); tm=localtime(&SeqEndTime.time); if (ShmSysConfigAndInfo->SysConfig.SwitchDebugFlag == YES) { sprintf(Buf,"%02d:%02d:%02d:%03d - %s", tm->tm_hour,tm->tm_min,tm->tm_sec,SeqEndTime.millitm, buffer); printf("%s \n", Buf); } else { sprintf(Buf,"echo \"%04d-%02d-%02d %02d:%02d:%02d:%03d - %s\" >> /Storage/SystemLog/[%04d.%02d]SystemLog_%s_Log", tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec,SeqEndTime.millitm, buffer, tm->tm_year+1900,tm->tm_mon+1, ShmSysConfigAndInfo->SysConfig.SerialNumber); system(Buf); } return rc; } void PRINTF_FUNC(char *string, ...) { va_list args; char buffer[4096]; va_start(args, string); vsnprintf(buffer, sizeof(buffer), string, args); va_end(args); DEBUG_INFO("%s ", buffer); } //========================================== // Init all share memory //========================================== int InitShareMemory() { int result = PASS; int MeterSMId; //creat ShmSysConfigAndInfo if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo), 0777)) < 0) { #ifdef SystemLogMessage DEBUG_ERROR("shmget ShmSysConfigAndInfoKey NG %d \n"); #endif result = FAIL; } else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage DEBUG_ERROR("shmat ShmSysConfigAndInfo NG \n"); #endif result = FAIL; } //creat ShmStatusCodeData if ((MeterSMId = shmget(ShmStatusCodeKey, sizeof(struct StatusCodeData), 0777)) < 0) { #ifdef SystemLogMessage DEBUG_ERROR("shmget ShmStatusCodeKey NG \n"); #endif result = FAIL; } else if ((ShmStatusCodeData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage DEBUG_ERROR("shmat ShmStatusCodeData NG \n"); #endif result = FAIL; } //creat ShmPsuData if ((MeterSMId = shmget(ShmPsuKey, sizeof(struct PsuData), 0777)) < 0) { #ifdef SystemLogMessage DEBUG_ERROR("shmget ShmPsuKey NG \n"); #endif result = FAIL; } else if ((ShmPsuData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage DEBUG_ERROR("shmat ShmPsuData NG \n"); #endif result = FAIL; } if ((MeterSMId = shmget(ShmCommonKey, sizeof(struct DcCommonInformation), IPC_CREAT | 0777)) < 0) { #ifdef SystemLogMessage DEBUG_ERROR("shmget ShmCommonKey NG \n"); #endif result = FAIL; } else if ((ShmDcCommonData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage DEBUG_ERROR("shmat ShmDcCommonData NG \n"); #endif result = FAIL; } if ((MeterSMId = shmget ( ShmSmartBoxKey, sizeof(struct SmartBoxData), IPC_CREAT | 0777 )) < 0) { #ifdef SystemLogMessage DEBUG_ERROR("shmat ShmSmartBoxKey NG \n"); #endif return FAIL; } else if ((ShmSmartBoxData = shmat ( MeterSMId, NULL, 0 )) == (void *) - 1) { #ifdef SystemLogMessage DEBUG_ERROR("shmat ShmSmartBoxData NG \n"); #endif return FAIL; } return result; } //========================================== // Public Function //========================================== bool FindChargingInfoData(byte target, struct ChargingInfoData **chargingData) { for (byte index = 0; index < CHAdeMO_QUANTITY; index++) { if (ShmSysConfigAndInfo->SysInfo.ChademoChargingData[index].Index == target) { chargingData[target] = &ShmSysConfigAndInfo->SysInfo.ChademoChargingData[index]; return true; } } for (byte index = 0; index < CCS_QUANTITY; index++) { if (ShmSysConfigAndInfo->SysInfo.CcsChargingData[index].Index == target) { chargingData[target] = &ShmSysConfigAndInfo->SysInfo.CcsChargingData[index]; return true; } } for (byte index = 0; index < GB_QUANTITY; index++) { if (ShmSysConfigAndInfo->SysInfo.GbChargingData[index].Index == target) { chargingData[target] = &ShmSysConfigAndInfo->SysInfo.GbChargingData[index]; return true; } } return false; } void Initialization() { bool isPass = false; while(!isPass) { isPass = true; for (byte _index = 0; _index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _index++) { if (!FindChargingInfoData(_index, &chargingInfo[0])) { DEBUG_ERROR("SmartBox (main) : FindChargingInfoData false \n"); isPass = false; break; } } sleep(1); } for (byte _index = 0; _index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _index++) { ShmSmartBoxData->Dynamic4Fetch[_index].ShareGroup = NONE_GROUP_CAN_SELECTED; ShmSmartBoxData->Dynamic4Fetch[_index].TargetRelay = NONE_RELAY_SELECTED; ShmSmartBoxData->Dynamic4Fetch[_index].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_NONE; ShmSmartBoxData->Dynamic4Release[_index].ReleaseGroup = NONE_GROUP_CAN_SELECTED; ShmSmartBoxData->Dynamic4Release[_index].TargetRelay = NONE_RELAY_SELECTED; ShmSmartBoxData->Dynamic4Release[_index].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_NONE; ShmSmartBoxData->ConnectorUsingGroupCount[_index] = 0; } } void PrintfLog() { if (ShmPsuData->Work_Step != _WORK_CHARGING) { PRINTF_FUNC ( "****************************************************************** \n" ); PRINTF_FUNC ( "SystemPresentPsuQuantity = %d \n", ShmPsuData->SystemPresentPsuQuantity); PRINTF_FUNC ( "SystemAvailableCurrent = %d (A) \n", ShmPsuData->SystemAvailableCurrent / 10); PRINTF_FUNC ( "SystemAvailablePower = %d (kw) \n", ShmPsuData->SystemAvailablePower / 10); PRINTF_FUNC ( "GroupCount = %d \n", ShmPsuData->GroupCount ); for (int _count = 0; _count < ARRAY_SIZE(ConnectorUsingSeq[0]); _count ++) { PRINTF_FUNC ( "----------------------------------------------------------------- \n" ); PRINTF_FUNC ( "Group Index = %d, UsingTarget for Gun-%d \n", _count, ShmPsuData->PsuGroup[_count].UsingTarget); PRINTF_FUNC ( "GroupPresentPsuQuantity = %d \n", ShmPsuData->PsuGroup[_count].GroupPresentPsuQuantity ); PRINTF_FUNC ( "GroupTargetOutputVoltage = %d (V) \n", ShmPsuData->PsuGroup[_count].GroupTargetOutputVoltage / 10); PRINTF_FUNC ( "GroupTargetOutputCurrent = %d (A) \n", ShmPsuData->PsuGroup[_count].GroupTargetOutputCurrent / 10); PRINTF_FUNC ( "GroupAvailableCurrent = %d (A) \n", ShmPsuData->PsuGroup[_count].GroupAvailableCurrent / 10); PRINTF_FUNC ( "GroupAvailablePower = %d (kw) \n", ShmPsuData->PsuGroup[_count].GroupAvailablePower / 10); PRINTF_FUNC ( "GroupMaxVoltage = %d (V) \n", ShmPsuData->PsuGroup[_count].GroupMaxVoltage / 10); PRINTF_FUNC ( "GroupPresentOutputVoltage = %.1f (V) \n", (double)ShmPsuData->PsuGroup[_count].GroupPresentOutputVoltage / 10); PRINTF_FUNC ( "GroupPresentOutputCurrent = %.1f (A) \n", (double)ShmPsuData->PsuGroup[_count].GroupPresentOutputCurrent / 10); PRINTF_FUNC ( "GroupPresentOutputPower = %d \n", ShmPsuData->PsuGroup[_count].GroupPresentOutputPower ); PRINTF_FUNC ( "TotalRatingPower = %f \n", (double)ShmPsuData->PsuGroup[_count].TotalRatingPower); PRINTF_FUNC ( "TotalIAvailableCurrent = %f \n", (double)ShmPsuData->PsuGroup[_count].TotalIAvailableCurrent / 10); } } else { for (byte conn = 0; conn < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; conn++) { byte totalUsingGpCount = 0; byte totalQuantity = 0; unsigned short _targetVol = 0 , _targetCur = 0; unsigned short _avaCur = 0 , _avaPow = 0; unsigned short _outputVol = 0 , _outputCur = 0; unsigned short _ratingPow = 0; for (byte gp = 0; gp < ShmSmartBoxData->ConnectorUsingGroupCount[conn]; gp++) { if (ShmPsuData->PsuGroup[ConnectorUsingSeq[conn][gp]].UsingTarget == GUN_LEFT) { totalUsingGpCount++; byte tarGp = ConnectorUsingSeq[conn][gp]; totalQuantity += ShmPsuData->PsuGroup[tarGp].GroupPresentPsuQuantity; _targetVol = ShmPsuData->PsuGroup[tarGp].GroupTargetOutputVoltage / 10; _targetCur += ShmPsuData->PsuGroup[tarGp].GroupTargetOutputCurrent / 10; _avaCur += ShmPsuData->PsuGroup[tarGp].GroupAvailableCurrent / 10; _avaPow += ShmPsuData->PsuGroup[tarGp].GroupAvailablePower / 10; _outputVol = (double)ShmPsuData->PsuGroup[tarGp].GroupPresentOutputVoltage / 10; _outputCur = (double)ShmPsuData->PsuGroup[tarGp].GroupPresentOutputCurrent / 10; _ratingPow += ShmPsuData->PsuGroup[tarGp].TotalRatingPower; } } if (totalUsingGpCount > 0) { PRINTF_FUNC ( "----------------------------------------------------------------- \n" ); PRINTF_FUNC ( "Group Index = %d, totalUsingGpCount = %d \n", conn, totalUsingGpCount); PRINTF_FUNC ( "totalQuantity = %d \n", totalQuantity); PRINTF_FUNC ( "_targetVol = %d (V), _targetCur = %d (A) \n", _targetVol, _targetCur); PRINTF_FUNC ( "_avaCur = %d (A), _avaPow = %d (kw) \n", _avaCur, _avaPow); PRINTF_FUNC ( "_outputVol = %d (V), _outputCur = %d (A) \n", _outputVol, _outputCur); PRINTF_FUNC ( "_ratingPow = %d \n", _ratingPow); } for (byte gp = 0; gp < ShmSmartBoxData->ConnectorUsingGroupCount[conn]; gp++) { if (ShmPsuData->PsuGroup[ConnectorUsingSeq[conn][gp]].UsingTarget == GUN_RIGHT) { totalUsingGpCount++; byte tarGp = ConnectorUsingSeq[conn][gp]; totalQuantity += ShmPsuData->PsuGroup [tarGp].GroupPresentPsuQuantity; _targetVol = ShmPsuData->PsuGroup [tarGp].GroupTargetOutputVoltage / 10; _targetCur += ShmPsuData->PsuGroup [tarGp].GroupTargetOutputCurrent / 10; _avaCur += ShmPsuData->PsuGroup [tarGp].GroupAvailableCurrent / 10; _avaPow += ShmPsuData->PsuGroup [tarGp].GroupAvailablePower / 10; _outputVol = (double) ShmPsuData->PsuGroup [tarGp].GroupPresentOutputVoltage / 10; _outputCur = (double) ShmPsuData->PsuGroup [tarGp].GroupPresentOutputCurrent / 10; _ratingPow += ShmPsuData->PsuGroup [tarGp].TotalRatingPower; } } if (totalUsingGpCount > 0) { PRINTF_FUNC ( "----------------------------------------------------------------- \n" ); PRINTF_FUNC ( "Group Index = %d, totalUsingGpCount = %d \n", conn, totalUsingGpCount); PRINTF_FUNC ( "totalQuantity = %d \n", totalQuantity); PRINTF_FUNC ( "_targetVol = %d (V), _targetCur = %d (A) \n", _targetVol, _targetCur); PRINTF_FUNC ( "_avaCur = %d (A), _avaPow = %d (kw) \n", _avaCur, _avaPow); PRINTF_FUNC ( "_outputVol = %d (V), _outputCur = %d (A) \n", _outputVol, _outputCur); PRINTF_FUNC ( "_ratingPow = %d \n", _ratingPow); } } } } void GetSystemMaxVoltage() { if (ShmSysConfigAndInfo->SysInfo.BootingStatus == BOOTTING) { int _sysVol = 0; for (byte group = 0; group < ShmPsuData->GroupCount; group++) { if (ShmPsuData->PsuGroup[group].GroupMaxVoltage > _sysVol) _sysVol = ShmPsuData->PsuGroup[group].GroupMaxVoltage; } for (byte gun_index = 0; gun_index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; gun_index++) { if (chargingInfo[gun_index]->MaximumChargingVoltage != _sysVol) { chargingInfo[gun_index]->MaximumChargingVoltage = _sysVol; } } } } void GetTimespecFunc(struct timespec *time) { clock_gettime(CLOCK_MONOTONIC, time); } long int GetTimeoutValue(struct timespec *startTime) { struct timespec endTime; clock_gettime(CLOCK_MONOTONIC, &endTime); return 1000 * (endTime.tv_sec - startTime->tv_sec) + (endTime.tv_nsec - startTime->tv_nsec) / 1000000; } //========================================== // Relay Processing //========================================== void SmartRelayCheck() { /* --------------------------------------- G_0 -----------(R1)----------------> Gun - 0 | -> R3 G_2 --------| | -> R4 G_3 --------| | -> R5 G_1 -----------(R2)----------------> Gun - 1 --------------------------------------- R3 ON �ɾ� : G_2 �ݩ� Gun-0 ��X�BG_0�ݩ� Gun - 1 ��X R4 ON �ɾ� : G_3 �ݩ� Gun-0 ��X�BG_2�ݩ� Gun - 1 ��X R5 ON �ɾ� : G_3 �ݩ� Gun-1 ��X�BG_1�ݩ� Gun - 0 ��X ------------------------- ���yPSU�|�Ӹs�Ψ��X��ShareGroup�����ȦU�ݩ���ӿ�X */ byte _buff[3] = {0}; for (byte group = 0; group < ShmPsuData->GroupCount; group++) { switch(group) { case _PSU_GROUP_INDEX_0: { if (ShmPsuData->PsuGroup[group].UsingTarget == GUN_RIGHT) { // �p�G�O�зǫ~ if(ShmDcCommonData->systemType == _SYSTEM_TYPE_STANDARD) { _buff[_RELAY_SWITCH_NAME_R4] = 0x01; _buff[_RELAY_SWITCH_NAME_R5] = 0x01; } else { // R3 ON _buff[_RELAY_SWITCH_NAME_R3] = 0x01; } } } break; case _PSU_GROUP_INDEX_2: { if (ShmPsuData->PsuGroup[group].UsingTarget == GUN_LEFT) { // R3 ON _buff[_RELAY_SWITCH_NAME_R3] = 0x01; } if (ShmPsuData->PsuGroup[group].UsingTarget == GUN_RIGHT) { // R4 ON _buff[_RELAY_SWITCH_NAME_R4] = 0x01; } } break; case _PSU_GROUP_INDEX_3: { if (ShmPsuData->PsuGroup[group].UsingTarget == GUN_LEFT) { // R4 ON _buff[_RELAY_SWITCH_NAME_R4] = 0x01; } if (ShmPsuData->PsuGroup[group].UsingTarget == GUN_RIGHT) { // R5 ON _buff[_RELAY_SWITCH_NAME_R5] = 0x01; } } break; case _PSU_GROUP_INDEX_1: { if (ShmPsuData->PsuGroup[group].UsingTarget == GUN_LEFT) { // �p�G�O�зǫ~ if(ShmDcCommonData->systemType == _SYSTEM_TYPE_STANDARD) { _buff[_RELAY_SWITCH_NAME_R4] = 0x01; _buff[_RELAY_SWITCH_NAME_R5] = 0x01; } else { // R5 ON _buff[_RELAY_SWITCH_NAME_R5] = 0x01; } } } break; } } for (byte _Conn = 0; _Conn < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _Conn++) { if (ShmSmartBoxData->Dynamic4Fetch[_Conn].FetchLoopStep >= _PSU_DYNAMIC_FETCH_STEP_RELAY) { byte targetGroup = ShmSmartBoxData->Dynamic4Fetch[_Conn].ShareGroup; switch(targetGroup) { case _PSU_GROUP_INDEX_0: { if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_RIGHT) { // �p�G�O�зǫ~ if(ShmDcCommonData->systemType == _SYSTEM_TYPE_STANDARD) { _buff[_RELAY_SWITCH_NAME_R4] = 0x01; _buff[_RELAY_SWITCH_NAME_R5] = 0x01; ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4; } else { // R3 ON -- P _buff[_RELAY_SWITCH_NAME_R3] = 0x01; ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R3; } } } break; case _PSU_GROUP_INDEX_2: { if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_LEFT) { // R3 ON -- P _buff[_RELAY_SWITCH_NAME_R3] = 0x01; ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R3; } if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_RIGHT) { // R4 ON -- P _buff[_RELAY_SWITCH_NAME_R4] = 0x01; ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4; } } break; case _PSU_GROUP_INDEX_3: { if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_LEFT) { // R4 ON -- P _buff[_RELAY_SWITCH_NAME_R4] = 0x01; ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4; } if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_RIGHT) { // R5 ON -- P _buff[_RELAY_SWITCH_NAME_R5] = 0x01; ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R5; } } break; case _PSU_GROUP_INDEX_1: { if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_LEFT) { // �p�G�O�зǫ~ if(ShmDcCommonData->systemType == _SYSTEM_TYPE_STANDARD) { _buff[_RELAY_SWITCH_NAME_R4] = 0x01; _buff[_RELAY_SWITCH_NAME_R5] = 0x01; ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4; } else { // R5 ON -- P _buff[_RELAY_SWITCH_NAME_R5] = 0x01; ShmSmartBoxData->Dynamic4Fetch[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R5; } } } break; } } if (ShmSmartBoxData->Dynamic4Release[_Conn].ReleaseLoopStep >= _PSU_DYNAMIC_RELEASE_STEP_RELAYOFF) { byte targetGroup = ShmSmartBoxData->Dynamic4Release[_Conn].ReleaseGroup; switch(targetGroup) { case _PSU_GROUP_INDEX_0: { if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_RIGHT) { // R3 OFF _buff[_RELAY_SWITCH_NAME_R3] = 0x00; ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R3; // �p�G�O�зǫ~ if(ShmDcCommonData->systemType == _SYSTEM_TYPE_STANDARD) { _buff[_RELAY_SWITCH_NAME_R4] = 0x00; _buff[_RELAY_SWITCH_NAME_R5] = 0x00; ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4; } } } break; case _PSU_GROUP_INDEX_2: { if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_LEFT) { // R3 OFF _buff[_RELAY_SWITCH_NAME_R3] = 0x00; ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R3; } if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_RIGHT) { // R5 OFF _buff[_RELAY_SWITCH_NAME_R4] = 0x00; ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4; } } break; case _PSU_GROUP_INDEX_3: { if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_LEFT) { // R4 OFF _buff[_RELAY_SWITCH_NAME_R4] = 0x00; ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4; } if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_RIGHT) { // R5 OFF _buff[_RELAY_SWITCH_NAME_R5] = 0x00; ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R5; } } break; case _PSU_GROUP_INDEX_1: { if (ShmPsuData->PsuGroup[targetGroup].UsingTarget == GUN_LEFT) { // �p�G�O�зǫ~ if(ShmDcCommonData->systemType == _SYSTEM_TYPE_STANDARD) { _buff[_RELAY_SWITCH_NAME_R4] = 0x00; _buff[_RELAY_SWITCH_NAME_R5] = 0x00; ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R4; } else { // R4 OFF _buff[_RELAY_SWITCH_NAME_R5] = 0x00; ShmSmartBoxData->Dynamic4Release[_Conn].TargetRelay = _RELAY_SWITCH_NAME_R5; } } } break; } } } memcpy(ShmSmartBoxData->ParallelRelayStatus, _buff, sizeof(_buff)); } //========================================== // Sub Processing //========================================== void Assign2ConnectorProcessing(byte _targetConn) { // �ھڲ{�b�Ӻj���쪺�s�ƶq, �̶��h�]�w�s���ϥΥؼЬ��� /�k�j // �@���]�w�ӼҶ��ؼЬ��� /�k�j��AAssignedPwr2Connector function �|�N�ӼҶ�����T����������/�k�j for (byte aGp = 0; aGp < ShmSmartBoxData->ConnectorUsingGroupCount[_targetConn]; aGp++) { if (ShmPsuData->PsuGroup[ConnectorUsingSeq[_targetConn][aGp]].IsUsing == YES) { ShmPsuData->PsuGroup[ConnectorUsingSeq[_targetConn][aGp]].UsingTarget = _targetConn; } } } // �N_group�Ӹs���Ҷ��t��_targetConn�j�� void AddGroup2Connector(byte _targetConn, byte _group) { ShmPsuData->PsuGroup[_group].IsUsing = YES; if ((ShmSysConfigAndInfo->SysInfo.IsAlternatvieConf == YES && _targetConn == GUN_RIGHT) || (ShmDcCommonData->systemType == _SYSTEM_TYPE_STANDARD && ShmSmartBoxData->ConnectorUsingGroupCount[_targetConn] > 0)) ShmSmartBoxData->ConnectorUsingGroupCount[_targetConn] = 4; else ShmSmartBoxData->ConnectorUsingGroupCount[_targetConn]++; // ������۹�s Assign2ConnectorProcessing(_targetConn); } // �NtargetGp�Ӹs���Ҷ��q_targetConn�j������ bool ReleaseConnectorProcessing(byte _targetConn, byte targetGp) { bool result = false; if (ShmPsuData->PsuGroup[targetGp].PwSwitchStatus == _PSU_POWER_STATUS_OFF) { result = true; ShmPsuData->PsuGroup[targetGp].UsingTarget = GUN_CHECK; ShmPsuData->PsuGroup[targetGp].IsUsing = NO; ShmSmartBoxData->ConnectorUsingGroupCount[_targetConn]--; } return result; } //========================================== // Fetch fork //========================================== void InitializeDynamicFetch(byte _targetConn) { ShmSmartBoxData->Dynamic4Fetch[_targetConn].ShareGroup = NONE_GROUP_CAN_SELECTED; ShmSmartBoxData->Dynamic4Fetch[_targetConn].TargetRelay = NONE_RELAY_SELECTED; ShmSmartBoxData->Dynamic4Fetch[_targetConn].ShareTargetCurrent = 0; ShmSmartBoxData->SmartChk[_targetConn].IsFetchStart = NO; } void FetchLoopProcessing(byte _targetConn) { byte targetGroup = ShmSmartBoxData->Dynamic4Fetch[_targetConn].ShareGroup; if (targetGroup == NONE_GROUP_CAN_SELECTED && ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep >= _PSU_DYNAMIC_FETCH_STEP_TG_VOL) { ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_FINISH; } // �� target vol ����n�٬O�η��e���u�q�� ? �i�H�ոլ�~ float EvVoltage = chargingInfo[_targetConn]->EvBatterytargetVoltage * 10; switch(ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep) { case _PSU_DYNAMIC_FETCH_STEP_NONE: case _PSU_DYNAMIC_FETCH_STEP_WAIT:{ } break; case _PSU_DYNAMIC_FETCH_STEP_TG_VOL: { // �Ӹs���� if (ShmPsuData->PsuGroup[targetGroup].GroupPresentOutputVoltage != 0) { PRINTF_FUNC("EV_ReqVoltage = %f, targetGroup = %d, Group_CurVoltage = %d \n", EvVoltage, targetGroup, ShmPsuData->PsuGroup[targetGroup].GroupPresentOutputVoltage); } if (EvVoltage <= PSU_MIN_VOL) { PRINTF_FUNC("***** FETCH_STEP_ABORT ***** (Gun - %d) \n", _targetConn); ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_ABORT; } else if (ShmPsuData->PsuGroup[targetGroup].GroupPresentOutputVoltage >= EvVoltage - PSU_TG_VOL_GAP) { PRINTF_FUNC("***** FETCH_STEP_RELAY ***** (Gun - %d) \n", _targetConn); ShmPsuData->PsuGroup[targetGroup].UsingTarget = _targetConn; ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_RELAY; } } break; case _PSU_DYNAMIC_FETCH_STEP_RELAY: { // �f�W������ Relay if (ShmSmartBoxData->Dynamic4Fetch[_targetConn].TargetRelay < ARRAY_SIZE(ShmSmartBoxData->ParallelRelayStatus)) { if (ShmSmartBoxData->ParallelRelayStatus[ShmSmartBoxData->Dynamic4Fetch[_targetConn].TargetRelay] == YES) { if (ShmSmartBoxData->RcbParallelStatus[ShmSmartBoxData->Dynamic4Fetch[_targetConn].TargetRelay] == YES) { PRINTF_FUNC("***** FETCH_STEP_CUR_SHARE ***** (Gun - %d) \n", _targetConn); ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_CUR_SHARE; } } } } break; case _PSU_DYNAMIC_FETCH_STEP_CUR_SHARE: { // ���y : �ؼйq�y = ���e�q�y / (�쥻��X�s�Ӽ� + share group �Ӽ�) PRINTF_FUNC("GroupPresent = %d (0.1A), ShareTarget = %d (0.1A), CurrentPresent = %.1f \n", ShmPsuData->PsuGroup[targetGroup].GroupPresentOutputCurrent, ShmSmartBoxData->Dynamic4Fetch[_targetConn].ShareTargetCurrent, chargingInfo[_targetConn]->PresentChargingCurrent); if ((ShmPsuData->PsuGroup[targetGroup].GroupPresentOutputCurrent >= ShmSmartBoxData->Dynamic4Fetch[_targetConn].ShareTargetCurrent - PSU_TG_CUR_GAP && ShmPsuData->PsuGroup[targetGroup].GroupPresentOutputCurrent <= ShmSmartBoxData->Dynamic4Fetch[_targetConn].ShareTargetCurrent + PSU_TG_CUR_GAP) || chargingInfo[_targetConn]->PresentChargingCurrent <= PSU_MIN_CUR) { PRINTF_FUNC("***** FETCH_STEP_WATI_FINISH ***** (Gun - %d) \n", _targetConn); ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_WATI_FINISH; } } break; case _PSU_DYNAMIC_FETCH_STEP_WATI_FINISH: { AddGroup2Connector(_targetConn, targetGroup); GetTimespecFunc(&ShmSmartBoxData->SmartChk[_targetConn].FetchLoopTime); PRINTF_FUNC("***** FETCH_STEP_FINISH ***** (Gun - %d) \n", _targetConn); ShmSmartBoxData->Dynamic4Fetch[_targetConn].ShareGroup = NONE_GROUP_CAN_SELECTED; ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_FINISH; } break; case _PSU_DYNAMIC_FETCH_STEP_FINISH: { // ���� int _t = GetTimeoutValue(&ShmSmartBoxData->SmartChk[_targetConn].FetchLoopTime); if (_t >= FETCH_FINISH_WAIT_TIME) { InitializeDynamicFetch(_targetConn); PRINTF_FUNC("***** FETCH_STEP_NONE ***** (Gun - %d) \n", _targetConn); ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_NONE; } } break; case _PSU_DYNAMIC_FETCH_STEP_ABORT: { // ���_ if (ShmPsuData->PsuGroup[targetGroup].IsUsing) { ShmPsuData->PsuGroup[targetGroup].IsUsing = NO; ShmPsuData->PsuGroup[targetGroup].UsingTarget = GUN_CHECK; } GetTimespecFunc(&ShmSmartBoxData->SmartChk[_targetConn].FetchLoopTime); ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_FINISH; } break; } } byte CheckRemainPwrByConIndex(byte _targetConn) { byte result = NONE_GROUP_CAN_SELECTED; // �Ӻj�w�g�ϥΪ��s�ƶq byte usingCount = ShmSmartBoxData->ConnectorUsingGroupCount[_targetConn]; for (byte Gp = usingCount; Gp < ARRAY_SIZE(ConnectorUsingSeq[_targetConn]); Gp++) { // �P�_�O�_���Ӻj�U�@�ӥi�θs�����A if (ShmPsuData->PsuGroup[ConnectorUsingSeq[_targetConn][Gp]].IsUsing == NO && ShmPsuData->PsuGroup[ConnectorUsingSeq[_targetConn][Gp]].GroupPresentPsuQuantity > 0) { result = ConnectorUsingSeq[_targetConn][Gp]; break; } } return result; } void Chk2StopFetchStep(byte _targetConn) { // �}�l�y�{��,�N���y�{�����a~ if (ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep > _PSU_DYNAMIC_FETCH_STEP_NONE && ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep < _PSU_DYNAMIC_FETCH_STEP_TG_VOL) { PRINTF_FUNC("***** FETCH_STEP_ABORT ***** (Gun - %d) \n", _targetConn); ShmSmartBoxData->Dynamic4Fetch[_targetConn].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_ABORT; } } bool GetCanFetchResult(byte gun_index) { // �p�G���e��X�����ڥi���Ѫ���q (�Z�� <= CAP_GAP_FETCH <3KW>) // ���� EvBatterytargetVoltage ��]�O�p�O�|�N�ӭȰ����P���B�z�覡 float needPower = chargingInfo[gun_index]->PresentChargingVoltage * chargingInfo[gun_index]->EvBatterytargetCurrent / 100; ShmSmartBoxData->ConnectorStatus[gun_index].NeedToFetch = (needPower > 0 && needPower >= chargingInfo[gun_index]->RealRatingPower - CAP_GAP_FETCH) ? true : false; if (!ShmSmartBoxData->ConnectorStatus[gun_index].NeedToFetch) { // �Ҽ{�C���Ҷ��̤j��X�q�y�� 100A ShmSmartBoxData->ConnectorStatus[gun_index].NeedToFetch = (chargingInfo[gun_index]->EvBatterytargetCurrent >= chargingInfo[gun_index]->AvailableChargingCurrent - LIMIT_PWR_MODULE_GAP) ? true : false; } return ShmSmartBoxData->ConnectorStatus[gun_index].NeedToFetch; } void FetchFork() { pid_t fetchPid; fetchPid = fork(); if(fetchPid > 0) { bool isPass = false; struct ChargingInfoData *_chargingData[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY]; while(!isPass) { isPass = true; for (byte _index = 0; _index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _index++) { if (!FindChargingInfoData(_index, &_chargingData[0])) { DEBUG_ERROR("Smartbox (FetchFork) : FindChargingInfoData false \n"); isPass = false; break; } } sleep(1); } while(1) { for (byte gun_index = 0; gun_index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; gun_index++) { if (chargingInfo[gun_index]->SystemStatus == SYS_MODE_IDLE || chargingInfo[gun_index]->SystemStatus == SYS_MODE_RESERVATION || chargingInfo[gun_index]->SystemStatus == SYS_MODE_MAINTAIN || chargingInfo[gun_index]->SystemStatus == SYS_MODE_FAULT) { ShmSmartBoxData->ConnectorStatus[gun_index].NeedToFetch = NO; if (ShmSmartBoxData->ConnectorStatus[gun_index].ConnectorStaus != _CONNECTOR_STATUS_NONE) ShmSmartBoxData->ConnectorStatus[gun_index].ConnectorStaus = _CONNECTOR_STATUS_NONE; } // ��R�q��ӻ�,�R�q�j�u���ݨD else if (chargingInfo[gun_index]->SystemStatus >= SYS_MODE_MODE_REASSIGN_CHECK && chargingInfo[gun_index]->SystemStatus <= SYS_MODE_REASSIGN) { // �P�_�Ӹs�O�_�Q�ϥΤ� if (ShmPsuData->PsuGroup[gun_index].IsUsing) { // �p�G�ϥΤ� : ���ݧ�o���Ҷ����X ShmSmartBoxData->ConnectorStatus[gun_index].ConnectorStaus = _CONNECTOR_STATUS_WAIT; } else { // �����P�N�Ӹs���X InitializeDynamicFetch(gun_index); ShmSmartBoxData->ConnectorStatus[gun_index].ConnectorStaus = _CONNECTOR_STATUS_USING; } } else if (chargingInfo[gun_index]->SystemStatus == SYS_MODE_PREPARING) { // �o�Ӷ��q�u�|�����ݩ�Ӻj���Ҷ��s if (ShmDcCommonData->systemType == _SYSTEM_TYPE_SIMPLE) { // ���� : �j��ϥβĹs�s AddGroup2Connector(gun_index, _PSU_GROUP_INDEX_0); } else { if (!ShmPsuData->PsuGroup[gun_index].IsUsing) { // �Ĥ@�� : Gun index // �ĤG�� : Psu Group index AddGroup2Connector(gun_index, gun_index); } } } else if (chargingInfo[gun_index]->SystemStatus == SYS_MODE_CHARGING) { // �P�_�O�_�i�H�λݭn���Ѧh�l�s��X byte chkRemainGp = NONE_GROUP_CAN_SELECTED; if (ShmSmartBoxData->Dynamic4Fetch[gun_index].ShareGroup == NONE_GROUP_CAN_SELECTED) chkRemainGp = CheckRemainPwrByConIndex(gun_index); else chkRemainGp = ShmSmartBoxData->Dynamic4Fetch[gun_index].ShareGroup; ShmSmartBoxData->ConnectorStatus[gun_index].NeedToFetch = GetCanFetchResult(gun_index); if (ShmDcCommonData->systemType != _SYSTEM_TYPE_SIMPLE && ShmSmartBoxData->Dynamic4Release[gun_index].ReleaseLoopStep == _PSU_DYNAMIC_RELEASE_STEP_NONE && ((ShmSmartBoxData->ConnectorStatus[gun_index].NeedToFetch && chkRemainGp != NONE_GROUP_CAN_SELECTED && ShmSmartBoxData->Dynamic4Fetch[gun_index].FetchLoopStep <= _PSU_DYNAMIC_FETCH_STEP_WAIT) || ShmDcCommonData->smartFetchRun[gun_index]) ) { if (!ShmSmartBoxData->SmartChk[gun_index].IsFetchStart) { // �P�_�O�_�i�H�λݭn���Ѧh�l�s��X PRINTF_FUNC("Fetch Target = %d, Target Group = %d \n", gun_index, chkRemainGp); // ��w�ؼиs,�ʺA���t�}�l // �Ӹs�Ҷ��Y�Q��w, �w���t�~�@�s�]�i�J�ۦP��,�w���m�P�@�Ӹs������ ShmPsuData->PsuGroup[chkRemainGp].IsUsing = YES; ShmSmartBoxData->Dynamic4Fetch[gun_index].ShareGroup = chkRemainGp; PRINTF_FUNC("***** FETCH_STEP_WAIT ***** (Gun - %d) \n", gun_index); ShmSmartBoxData->Dynamic4Fetch[gun_index].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_WAIT; // �˼ƶi�J�ʺA���t�� - Fetch loop ShmSmartBoxData->SmartChk [gun_index].IsFetchStart = YES; // ����, �˼� FETCH_SMART_CHK_TIME <5s> GetTimespecFunc(&ShmSmartBoxData->SmartChk[gun_index].FetchLoopTime); } else { if (ShmSmartBoxData->Dynamic4Fetch[gun_index].FetchLoopStep == _PSU_DYNAMIC_FETCH_STEP_WAIT) { int _t = GetTimeoutValue(&ShmSmartBoxData->SmartChk[gun_index].FetchLoopTime); if (_t >= FETCH_SMART_CHK_TIME) { PRINTF_FUNC("***** FETCH_STEP_TG_VOL ***** (Gun - %d) \n", gun_index); ShmSmartBoxData->Dynamic4Fetch[gun_index].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_TG_VOL; ShmDcCommonData->smartFetchRun[gun_index] = NO; } } } } else { // �ʺA���t�����_ Chk2StopFetchStep(gun_index); } } FetchLoopProcessing(gun_index); } usleep(50000); } } } //========================================== // Release fork //========================================== void InitializeDynamicRelease(byte _targetConn) { ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseGroup = NONE_GROUP_CAN_SELECTED; ShmSmartBoxData->Dynamic4Release[_targetConn].TargetRelay = NONE_RELAY_SELECTED; ShmSmartBoxData->Dynamic4Release[_targetConn].LimitCurCap = 0; ShmSmartBoxData->Dynamic4Release[_targetConn].LimitPwrCap = 0; ShmSmartBoxData->Dynamic4Release[_targetConn].LimitCur = 0; ShmSmartBoxData->Dynamic4Release[_targetConn].LimitPwr = 0; ShmSmartBoxData->Dynamic4Release[_targetConn].AutoRelease = NO; ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep = _PSU_DYNAMIC_FETCH_STEP_FINISH; } byte CheckReleasePwrByConIndex(byte _targetConn) { byte result = NONE_GROUP_CAN_SELECTED; // �Ӻj�w�g�ϥΪ��s�ƶq byte usingCount = ShmSmartBoxData->ConnectorUsingGroupCount[_targetConn]; // ���i��̫�@�Ӥ]�������� if (usingCount - 1 > 0) result = ConnectorUsingSeq[_targetConn][usingCount - 1]; return result; } void ReleaseLoopProcessing(byte _targetConn) { byte targetGroup = ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseGroup; switch(ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep) { case _PSU_DYNAMIC_RELEASE_STEP_NONE: case _PSU_DYNAMIC_RELEASE_STEP_WAIT: {} break; case _PSU_DYNAMIC_RELEASE_STEP_LIMIT: { // ���ӭn�q���i��X����q�P�q�y // if the current and power limits are below their capacity // if (ShmSmartBoxData->Dynamic4Release[_targetConn].LimitPwr <= ShmSmartBoxData->Dynamic4Release[_targetConn].LimitPwrCap || // chargingInfo[_targetConn]->PresentChargingCurrent * 10 <= PSU_LIMIT_CUR) if (ShmSmartBoxData->Dynamic4Release[_targetConn].LimitPwr <= ShmSmartBoxData->Dynamic4Release[_targetConn].LimitPwrCap) { PRINTF_FUNC("***** RELEASE_STEP_CUR_SHARE ***** (Gun - %d) \n", _targetConn); ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_CUR_SHARE; } } break; case _PSU_DYNAMIC_RELEASE_STEP_CUR_SHARE: { PRINTF_FUNC("targetGroup = %d, GroupPresentOutputCurrent = %.1f \n", targetGroup, ShmPsuData->PsuGroup[targetGroup].GroupPresentOutputCurrent); // if the output current is below their capacity for 5s int _t = GetTimeoutValue(&ShmSmartBoxData->SmartChk[_targetConn].ReleaseLoopTime); if (ShmPsuData->PsuGroup[targetGroup].GroupPresentOutputCurrent <= RELEASE_STEP_CUR_SHARE && _t >= WAIT_FOR_LIMIT_STABLE) { PRINTF_FUNC("***** RELEASE_STEP_RELAYOFF ***** (Gun - %d) \n", _targetConn); ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_RELAYOFF; } } break; case _PSU_DYNAMIC_RELEASE_STEP_RELAYOFF: { // ��������� Relay PRINTF_FUNC("TargetRelay (%d), targetGroup = %d, ParallelRelayStatus = (%d), RcbParallelStatus = (%d) \n", ShmSmartBoxData->Dynamic4Release[_targetConn].TargetRelay, targetGroup, ShmSmartBoxData->ParallelRelayStatus[ShmSmartBoxData->Dynamic4Release[_targetConn].TargetRelay], ShmSmartBoxData->RcbParallelStatus[ShmSmartBoxData->Dynamic4Release[_targetConn].TargetRelay]); if (ShmSmartBoxData->Dynamic4Release[_targetConn].TargetRelay < ARRAY_SIZE(ShmSmartBoxData->ParallelRelayStatus)) { if (ShmSmartBoxData->ParallelRelayStatus[ShmSmartBoxData->Dynamic4Release[_targetConn].TargetRelay] == NO) { if (ShmSmartBoxData->RcbParallelStatus[ShmSmartBoxData->Dynamic4Release[_targetConn].TargetRelay] == NO) { PRINTF_FUNC("***** RELEASE_STEP_WATI_FINISH ***** (Gun - %d) \n", _targetConn); ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_WAIT_FINISH; } } } } break; case _PSU_DYNAMIC_RELEASE_STEP_WAIT_FINISH: { if(ReleaseConnectorProcessing(_targetConn, targetGroup)) { GetTimespecFunc ( & ShmSmartBoxData->SmartChk [_targetConn].ReleaseLoopTime ); PRINTF_FUNC("***** RELEASE_STEP_FINISH ***** (Gun - %d) \n", _targetConn); InitializeDynamicRelease(_targetConn); ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_FINISH; } } break; case _PSU_DYNAMIC_RELEASE_STEP_FINISH: { // ���� int _t = GetTimeoutValue(&ShmSmartBoxData->SmartChk[_targetConn].ReleaseLoopTime); if (_t >= RELEASE_FINISH_WAIT_TIME) { PRINTF_FUNC("***** RELEASE_STEP_NONE ***** (Gun - %d) \n", _targetConn); ShmSmartBoxData->SmartChk[_targetConn].IsReleaseStart = NO; ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_NONE; } } break; case _PSU_DYNAMIC_RELEASE_STEP_ABORT: { GetTimespecFunc(& ShmSmartBoxData->SmartChk [_targetConn].ReleaseLoopTime); PRINTF_FUNC("***** RELEASE_STEP_FINISH ***** (Gun - %d) \n", _targetConn); InitializeDynamicRelease(_targetConn); ShmSmartBoxData->Dynamic4Release[_targetConn].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_FINISH; } break; } } void Chk2StopReleaseStep(byte _targetConn) { // �}�l�y�{��,�N���y�{�����a~ if (ShmSmartBoxData->Dynamic4Release [_targetConn].ReleaseGroup > _PSU_DYNAMIC_RELEASE_STEP_NONE && ShmSmartBoxData->Dynamic4Release [_targetConn].ReleaseGroup < _PSU_DYNAMIC_RELEASE_STEP_LIMIT) { PRINTF_FUNC ( "***** RELEASE_STEP_ABORT ***** (Gun - %d) \n", _targetConn ); //ShmSmartBoxData->Dynamic4Release [_targetConn].ReleaseGroup = _PSU_DYNAMIC_RELEASE_STEP_ABORT; } else ShmSmartBoxData->SmartChk[_targetConn].IsReleaseStart = NO; } bool GetCanReleaseResult(byte gun_index, byte releaseGp) { bool result = false; unsigned short releasePwr = ShmPsuData->PsuGroup[releaseGp].TotalRatingPower * 10; float needPower = chargingInfo[gun_index]->PresentChargingVoltage * chargingInfo[gun_index]->EvBatterytargetCurrent / 100; result = (chargingInfo[gun_index]->RealRatingPower > 0 && releasePwr > 0 && needPower < chargingInfo[gun_index]->RealRatingPower - releasePwr - CAP_GAP_RELEASE) ? true : false; if (result) { // afterReleaseMdCur �C�ӼҶ��̤j 100A : 1A float afterReleaseMdCur = chargingInfo[gun_index]->AvailableChargingCurrent - ShmPsuData->PsuGroup[releaseGp].GroupAvailableCurrent; result = (chargingInfo[gun_index]->EvBatterytargetCurrent >= afterReleaseMdCur - LIMIT_PWR_MODULE_GAP) ? false : true; } return result; } void ReleaseFork() { pid_t releasePid; releasePid = fork(); if(releasePid > 0) { bool isPass = false; struct ChargingInfoData *_chargingData[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY]; while(!isPass) { isPass = true; for (byte _index = 0; _index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _index++) { if (!FindChargingInfoData(_index, &_chargingData[0])) { DEBUG_ERROR("Smartbox (ReleaseFork) : FindChargingInfoData false \n"); isPass = false; break; } } sleep(1); } while(1) { for (byte gun_index = 0; gun_index < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; gun_index++) { if (chargingInfo[gun_index]->SystemStatus == SYS_MODE_CHARGING) { // ���X�h�l�s : �n�P�_�ҭn���X�s�үണ�Ѫ��̤j��q RealRatingPower // �����O�_���U�@�ӭn���X���s byte releaseGp = CheckReleasePwrByConIndex(gun_index); if (releaseGp != NONE_GROUP_CAN_SELECTED) { bool canRelease = GetCanReleaseResult(gun_index, releaseGp); if (chargingInfo[gun_index]->Type != _Type_Test && ShmSmartBoxData->Dynamic4Fetch[gun_index].FetchLoopStep == _PSU_DYNAMIC_FETCH_STEP_NONE && (ShmSmartBoxData->AnotherConnectorStatus[gun_index].ConnectorStaus == _CONNECTOR_STATUS_WAIT || (ShmSmartBoxData->AnotherConnectorStatus[gun_index].NeedToFetch && SMART_MODE && chargingInfo[gun_index]->_TakePsuGpCount > ShmDcCommonData->halfGroupCount) || canRelease || ShmDcCommonData->smartReleaseRun[gun_index]) ) { //PRINTF_FUNC("RealRatingPower = %d \n", chargingInfo[gun_index]->RealRatingPower); //PRINTF_FUNC("releasePwr = %d, needPower = %f \n", releasePwr, needPower); if (ShmSmartBoxData->Dynamic4Release[gun_index].ReleaseLoopStep == _PSU_DYNAMIC_RELEASE_STEP_NONE) { if (!ShmSmartBoxData->SmartChk[gun_index].IsReleaseStart) { PRINTF_FUNC("***** Entry release chk (Gun_%d).. ***** \n", gun_index); ShmSmartBoxData->SmartChk[gun_index].IsReleaseStart = YES; ShmSmartBoxData->Dynamic4Release[gun_index].CheckOutPwrIsStable = chargingInfo[gun_index]->PresentChargingPower; GetTimespecFunc(&ShmSmartBoxData->SmartChk[gun_index].ReleaseLoopTime); } else { int _delayt = GetTimeoutValue(&ShmSmartBoxData->SmartChk[gun_index].ReleaseLoopTime); // �C�����ݤ@����X��q�O�_í�w, í�w�h�i�J���t if (_delayt >= RELEASE_STABLE_CHK_TIME) { if (chargingInfo[gun_index]->PresentChargingPower > ShmSmartBoxData->Dynamic4Release[gun_index].CheckOutPwrIsStable + STABLE_CAP_GAP) { ShmSmartBoxData->Dynamic4Release[gun_index].CheckOutPwrIsStable = chargingInfo[gun_index]->PresentChargingPower; GetTimespecFunc(&ShmSmartBoxData->SmartChk[gun_index].ReleaseLoopTime); } else { // �i�Jí�w PRINTF_FUNC("***** RELEASE_STEP_WAIT ***** \n"); ShmSmartBoxData->Dynamic4Release[gun_index].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_WAIT; GetTimespecFunc(&ShmSmartBoxData->SmartChk[gun_index].ReleaseLoopTime); } } } } else if (ShmSmartBoxData->Dynamic4Release[gun_index].ReleaseLoopStep == _PSU_DYNAMIC_RELEASE_STEP_WAIT) { int _delayt = GetTimeoutValue(&ShmSmartBoxData->SmartChk[gun_index].ReleaseLoopTime); // �C�����ݤ@����X��q�O�_í�w, í�w�h�i�J���t if (_delayt >= RELEASE_SMART_CHK_TIME) { PRINTF_FUNC("***** RELEASE_STEP_LIMIT ***** \n"); ShmSmartBoxData->Dynamic4Release[gun_index].ReleaseGroup = releaseGp; ShmSmartBoxData->Dynamic4Release[gun_index].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_LIMIT; ShmDcCommonData->smartReleaseRun[gun_index] = NO; } } } else { // �ʺA���t�����_ Chk2StopReleaseStep(gun_index); } } } else if (chargingInfo[gun_index]->SystemStatus == SYS_MODE_IDLE || chargingInfo[gun_index]->SystemStatus == SYS_MODE_FAULT || chargingInfo[gun_index]->SystemStatus == SYS_MODE_RESERVATION || (chargingInfo[gun_index]->SystemStatus >= SYS_MODE_TERMINATING && chargingInfo[gun_index]->SystemStatus <= SYS_MODE_ALARM)) { if (ShmSmartBoxData->ConnectorStatus[gun_index].ConnectorStaus == _CONNECTOR_STATUS_NONE) { byte totoalUsingGpCount = ShmSmartBoxData->ConnectorUsingGroupCount[gun_index]; for (byte _gp = 0; _gp < totoalUsingGpCount; _gp++) { PRINTF_FUNC("ConnectorUsingSeq[%d][%d] = %d \n", gun_index, _gp, ConnectorUsingSeq[gun_index][_gp]); ReleaseConnectorProcessing(gun_index, ConnectorUsingSeq[gun_index][_gp]); } if (ShmSmartBoxData->Dynamic4Fetch[gun_index].ShareGroup != NONE_GROUP_CAN_SELECTED && ShmSmartBoxData->Dynamic4Fetch[gun_index].FetchLoopStep < _PSU_DYNAMIC_FETCH_STEP_FINISH) ShmSmartBoxData->Dynamic4Fetch[gun_index].FetchLoopStep = _PSU_DYNAMIC_FETCH_STEP_ABORT; ShmSmartBoxData->Dynamic4Release[gun_index].ReleaseLoopStep = _PSU_DYNAMIC_RELEASE_STEP_NONE; } if (ShmSmartBoxData->ConnectorStatus[gun_index].NeedToFetch) ShmSmartBoxData->ConnectorStatus[gun_index].NeedToFetch = NO; } ReleaseLoopProcessing(gun_index); } usleep(50000); } } } //========================================== // Main Function //========================================== void TakeAnotherGunStatus(byte target) { byte another = 0; if (target == 0) another = 1; ShmSmartBoxData->AnotherConnectorStatus[another].ConnectorStaus = ShmSmartBoxData->ConnectorStatus[target].ConnectorStaus; ShmSmartBoxData->AnotherConnectorStatus[another].NeedToFetch = ShmSmartBoxData->ConnectorStatus[target].NeedToFetch; } void AssignedPwr2Connector() { for(byte _gun = 0; _gun < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; _gun++) { byte usingGroupCount = 0; float availablePwr = 0, availableCur = 0, iAvailableCur = 0, totalPsuCount = 0, kwAvailablePwr = 0; float outputVol = 0, outputCur = 0; float limitCur = 0, limitPwr = 0, remainCur = 0; for (byte group = 0; group < ShmPsuData->GroupCount; group++) { if (ShmPsuData->PsuGroup[group].UsingTarget == _gun) { usingGroupCount++; if (group != ShmSmartBoxData->Dynamic4Fetch[_gun].ShareGroup && (group != ShmSmartBoxData->Dynamic4Release[_gun].ReleaseGroup || ShmSmartBoxData->Dynamic4Release[_gun].ReleaseLoopStep <= _PSU_DYNAMIC_RELEASE_STEP_WAIT_FINISH)) { availablePwr += ShmPsuData->PsuGroup[group].GroupAvailablePower; availableCur += ShmPsuData->PsuGroup[group].GroupAvailableCurrent; iAvailableCur += ShmPsuData->PsuGroup[group].TotalIAvailableCurrent; totalPsuCount += ShmPsuData->PsuGroup[group].GroupPresentPsuQuantity; if (ShmPsuData->PsuGroup[group].TotalRatingPower <= 15 || ShmPsuData->PsuGroup[group].TotalRatingPower > 30) kwAvailablePwr += (ShmPsuData->PsuGroup[group].GroupAvailablePower) / 10; else kwAvailablePwr += ShmPsuData->PsuGroup[group].TotalRatingPower; } // Release Loop �� : ��ڤW~ �q�y�|�� .... // �o�q, �u���٭n�d�����Ҷ���X�q�y�P��q�N�n if (group != ShmSmartBoxData->Dynamic4Release[_gun].ReleaseGroup && ShmSmartBoxData->Dynamic4Release[_gun].ReleaseLoopStep == _PSU_DYNAMIC_RELEASE_STEP_LIMIT) { limitCur += ShmPsuData->PsuGroup[group].GroupTargetOutputCurrent; remainCur += ShmPsuData->PsuGroup[group].TotalIAvailableCurrent; limitPwr += ShmPsuData->PsuGroup[group].TotalRatingPower; } outputCur += ShmPsuData->PsuGroup[group].GroupPresentOutputCurrent; if (outputVol < ShmPsuData->PsuGroup[group].GroupPresentOutputVoltage || outputVol == 0) outputVol = ShmPsuData->PsuGroup[group].GroupPresentOutputVoltage; } } chargingInfo[_gun]->AvailableChargingPower = availablePwr; chargingInfo[_gun]->AvailableChargingCurrent = availableCur; chargingInfo[_gun]->DeratingChargingCurrent = iAvailableCur; chargingInfo[_gun]->_TotalPsuCount = totalPsuCount; chargingInfo[_gun]->PresentChargingVoltage = outputVol / 10; // �b�C��̤j 1KW ��X��~ ���ڭ̰����@�U~ if (chargingInfo[_gun]->SystemStatus == SYS_MODE_CHARGING) { if (chargingInfo[_gun]->RealMaxPower <= 10 && outputCur < (chargingInfo[_gun]->RealMaxCurrent * 0.9)) outputCur = (chargingInfo[_gun]->RealMaxCurrent * 0.9); } chargingInfo[_gun]->PresentChargingCurrent = outputCur / 10; chargingInfo[_gun]->RealRatingPower = kwAvailablePwr * 10; chargingInfo[_gun]->_TakePsuGpCount = usingGroupCount; // ���j�ݭn�O�o�t�~�@��j�����A if (ShmSysConfigAndInfo->SysConfig.TotalConnectorCount > 1) TakeAnotherGunStatus(_gun); // �� Release group ���̤j�q�y if (ShmSmartBoxData->Dynamic4Release[_gun].ReleaseLoopStep == _PSU_DYNAMIC_RELEASE_STEP_LIMIT && ShmSmartBoxData->Dynamic4Release[_gun].LimitPwrCap == 0) { // limitCur : �U���Ѿl�s���ݨD�q�y //ShmSmartBoxData->Dynamic4Release[_gun].LimitCurCap = limitCur; // Release ���y�Q�k(�`��) : �p�G�O����������۵M����~ ���ӳ��|�]���y�覡 // ���p�@ : �s1 : 30A�A�s2 : 30A �@ 60A ��X�A�B��ڤW�s1 �i���Ѫ��q�y�� 75A (400V ��X) // ���p�G : �s1 : 75A�A�s2 : 75A �@ 150A ��X�A�B��ڤW�s1 �i���Ѫ��q�y�� 75A (400V ��X) // ���p�T : �s1 : 70A�A�s2 : 70A �@ 140A ��X�A�B��ڤW�s1 �i���Ѫ��q�y�� 75A (400V ��X) // --------------------------------------------- // ���p�@ : 60A <= �s1�i���Ѫ� 75A : ���y // ���p�@ : 150A > �s1�i���Ѫ� 75A : �������_ // ���p�@ : 140A > �s1�i���Ѫ� 75A : �������_ if (chargingInfo[_gun]->PresentChargingCurrent <= remainCur) { PRINTF_FUNC("PresentChargingCurrent = %f, remainCur = %f \n", chargingInfo[_gun]->PresentChargingCurrent, remainCur / 10); limitCur = chargingInfo[_gun]->PresentChargingCurrent * 10; ShmSmartBoxData->Dynamic4Release[_gun].AutoRelease = YES; } else PRINTF_FUNC("limitCur = %f \n", limitCur); ShmSmartBoxData->Dynamic4Release[_gun].LimitCurCap = limitCur; ShmSmartBoxData->Dynamic4Release[_gun].LimitPwrCap = limitPwr * 10; } } } void CollectGroupInformation(byte group) { int _groupPower = 0 , _groupCurrent = 0 , _groupMaxVoltage = 0; int Iavail = 0, Pavail = 0; unsigned short _outputVolBuf = 0, _outputCurBuf = 0; for (byte index = 0; index < ShmPsuData->PsuGroup[group].GroupPresentPsuQuantity; index ++) { // Cap _groupCurrent += ShmPsuData->PsuGroup[group].PsuModule[index].AvailableCurrent; _groupPower += ShmPsuData->PsuGroup[group].PsuModule[index].AvailablePower; if (ShmPsuData->PsuGroup[group].PsuModule[index].PresentMaxOutputVoltage > _groupMaxVoltage) _groupMaxVoltage = ShmPsuData->PsuGroup[group].PsuModule[index].PresentMaxOutputVoltage; // Iavailable Iavail += ShmPsuData->PsuGroup[group].PsuModule[index].IAvailableCurrent; Pavail += ShmPsuData->PsuGroup[group].PsuModule[index].KwAvailablePower; // output _outputCurBuf += ShmPsuData->PsuGroup[group].PsuModule[index].PresentOutputCurrent; if (_outputVolBuf == 0 || (ShmPsuData->PsuGroup[group].PsuModule[index].PresentOutputVoltage > PSU_MIN_VOL && _outputVolBuf < ShmPsuData->PsuGroup[group].PsuModule[index].PresentOutputVoltage)) { _outputVolBuf = ShmPsuData->PsuGroup[group].PsuModule[index].PresentOutputVoltage; } } ShmPsuData->PsuGroup[group].GroupMaxVoltage = _groupMaxVoltage; ShmPsuData->PsuGroup[group].GroupAvailableCurrent = _groupCurrent; ShmPsuData->PsuGroup[group].GroupAvailablePower = _groupPower; ShmPsuData->PsuGroup[group].TotalIAvailableCurrent = Iavail; ShmPsuData->PsuGroup[group].TotalRatingPower = Pavail; ShmPsuData->PsuGroup[group].GroupPresentOutputVoltage = _outputVolBuf; ShmPsuData->PsuGroup[group].GroupPresentOutputCurrent = _outputCurBuf; } void CollectPsuInformation() { int _sysPwr = 0, _sysCur = 0, _sysVol = 0; for (byte group = 0; group < ShmPsuData->GroupCount; group++) { // ���s��T CollectGroupInformation(group); // ��z�t�θ�T _sysPwr += ShmPsuData->PsuGroup[group].GroupAvailablePower; _sysCur += ShmPsuData->PsuGroup[group].GroupAvailableCurrent; if (ShmPsuData->PsuGroup[group].GroupMaxVoltage > _sysVol) _sysVol = ShmPsuData->PsuGroup[group].GroupMaxVoltage; } // �t��,�q��,�q�y,��q ShmPsuData->SystemAvailableCurrent = _sysCur; ShmPsuData->SystemAvailablePower = _sysPwr; GetSystemMaxVoltage(); } //========================================== // Main Loop //========================================== int main(void) { if(InitShareMemory() == FAIL) { #ifdef SystemLogMessage DEBUG_ERROR("InitShareMemory NG\n"); #endif if(ShmStatusCodeData != NULL) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FailToCreateShareMemory = 1; } sleep(5); return 0; } Initialization(); // ��R�q�j�ާ@ : �N�Ҷ����X�ӻP�ɤW�Ѿl���Ҷ��\�v FetchFork(); ReleaseFork(); GetTimespecFunc(&_log_time); while(1) { if (ShmPsuData->Work_Step >= GET_SYS_CAP) { // �����Ӧ� PSU ����T CollectPsuInformation(); // �N�s��T���t��������ϥΤ��R�q�j AssignedPwr2Connector(); int time = GetTimeoutValue(&_log_time); if (time < 0) GetTimespecFunc(&_log_time); // �C Priority �����O if (time > 5000) { //PrintfLog(); GetTimespecFunc(&_log_time); } } if (ShmDcCommonData->systemType != _SYSTEM_TYPE_SIMPLE && ShmPsuData->Work_Step == _WORK_CHARGING) { // �������� SmartRelayCheck(); } usleep(50000); } return -1; }