#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //for pow #include #include #include #include #include "define.h" //#define Debug //Protocol format : Dir #define SendDirection 0x08000000 #define RecvDirection 0x00000000 //Protocol format : Message ID #define MsgAddressRequest 0x00000100 #define MsgAddressAssign 0x00000200 #define MsgStatusNotification 0x00000300 #define MsgGetFwVersion 0x00000400 #define MsgGetHwVersion 0x00000500 #define MsgChargingPermission 0x00000600 #define MsgPresentOutputPower 0x00000700 #define MsgPresentOutputCapacity 0x00000800 #define MsgGetOutputRequirement 0x00000900 #define MsgGetEvBatteryInfo 0x00000A00 #define MsgEvStopEvent 0x00000B00 #define MsgEvseStopEvent 0x00000C00 #define MsgGetMiscInfo 0x00000D00 #define MsgDownloadRequest 0x00000E00 #define MsgStartBlockTransfer 0x00000F00 #define MsgDataTransfer 0x00001000 #define MsgDownloadFinish 0x00001100 struct SysConfigAndInfo *ShmSysConfigAndInfo; struct StatusCodeData *ShmStatusCodeData; struct CcsData *ShmCcsData; struct InternalComm *ShmInternalComm; pid_t CANReceiverPid; int CanFd; #ifdef SystemLogMessage int StoreLogMsg(unsigned char *DataString) { unsigned char Buf[256]; time_t CurrentTime; struct tm *tm; memset(Buf,0,sizeof(Buf)); CurrentTime = time(NULL); tm=localtime(&CurrentTime); sprintf(Buf,"echo \"%04d.%02d.%02d %02d:%02d:%02d - %s\" >> /Storage/SystemLog/[%04d.%02d]SystemLog", tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec, DataString, tm->tm_year+1900,tm->tm_mon+1); system(Buf); #ifdef Debug printf("%s \n",DataString); #endif } #endif 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; } /**************************************************************************************/ /**************************Init all share memory *********************************/ /**************************************************************************************/ int InitShareMemory() { int MeterSMId; //creat ShmSysConfigAndInfo if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo), 0777)) < 0) { #ifdef SystemLogMessage StoreLogMsg("[CsuComm]InitShareMemory:shmget ShmSysConfigAndInfo NG"); #endif return 0; } else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage StoreLogMsg("[CsuComm]InitShareMemory:shmat ShmSysConfigAndInfo NG"); #endif return 0; } //creat ShmStatusCodeData if ((MeterSMId = shmget(ShmStatusCodeKey, sizeof(struct StatusCodeData), 0777)) < 0) { #ifdef SystemLogMessage StoreLogMsg("[CsuComm]InitShareMemory:shmget ShmStatusCodeData NG"); #endif return 0; } else if ((ShmStatusCodeData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage StoreLogMsg("[CsuComm]InitShareMemory:shmat ShmStatusCodeData NG"); #endif return 0; } //creat ShmCcsData if ((MeterSMId = shmget(ShmCcsCommKey, sizeof(struct CcsData), 0777)) < 0) { #ifdef SystemLogMessage StoreLogMsg("[CsuComm]InitShareMemory:shmget ShmCcsData NG"); #endif return 0; } else if ((ShmCcsData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage StoreLogMsg("[CsuComm]InitShareMemory:shmat ShmCcsData NG"); #endif return 0; } //creat ShmInternalComm if ((MeterSMId = shmget(ShmInternalCommKey, sizeof(struct InternalComm), IPC_CREAT | 0777)) < 0) { #ifdef SystemLogMessage StoreLogMsg("[CsuComm]InitShareMemory:shmget ShmInternalComm NG"); #endif return 0; } else if ((ShmInternalComm = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage StoreLogMsg("[CsuComm]InitShareMemory:shmat ShmInternalComm NG"); #endif return 0; } memset(ShmInternalComm,0,sizeof(struct InternalComm)); return 1; } int InitCanBus() { int s0,nbytes; struct timeval tv; struct ifreq ifr0; struct sockaddr_can addr0; 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 StoreLogMsg("[CsuComm]InitCanBus:Set SO_RCVTIMEO NG"); #endif } nbytes=40960; if (setsockopt(s0, SOL_SOCKET, SO_RCVBUF, &nbytes, sizeof(int)) < 0) { #ifdef SystemLogMessage StoreLogMsg("[CsuComm]InitCanBus:Set SO_RCVBUF NG"); #endif } nbytes=40960; if (setsockopt(s0, SOL_SOCKET, SO_SNDBUF, &nbytes, sizeof(int)) < 0) { #ifdef SystemLogMessage StoreLogMsg("[CsuComm]InitCanBus:Set SO_SNDBUF NG"); #endif } strcpy(ifr0.ifr_name, "can0" ); ioctl(s0, SIOCGIFINDEX, &ifr0); /* ifr.ifr_ifindex gets filled with that device's index */ addr0.can_family = AF_CAN; addr0.can_ifindex = ifr0.ifr_ifindex; bind(s0, (struct sockaddr *)&addr0, sizeof(addr0)); return s0; } int SendMsg(int Fd, unsigned int MsgId, unsigned char SlaveAddress, unsigned char DataLength, unsigned char *SendData) { struct can_frame frame; struct timeb StartTime,EndTime; unsigned int tmp=0; int nbytes; memset(&frame,0,sizeof(struct can_frame)); frame.can_id = 0x80000000|SendDirection|MsgId|SlaveAddress; frame.can_dlc = DataLength; memcpy(frame.data,SendData,DataLength); nbytes = write(Fd, &frame, sizeof(struct can_frame)); #ifdef Debug printf("[CsuComm]SendMsg => Send to ID=0x%x, nbytes=0x%x, DataLength=0x%x, Data=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x\n", frame.can_id,nbytes,frame.can_dlc, frame.data[0],frame.data[1],frame.data[2],frame.data[3],frame.data[4],frame.data[5],frame.data[6],frame.data[7]); #endif return nbytes; } int SendFwVersion(int Fd) { int nbytes; unsigned char Buffer[4]; memset(Buffer,0,sizeof(Buffer)); nbytes=FirmwareVersion; memcpy(Buffer,&nbytes,sizeof(int)); nbytes=SendMsg(Fd, MsgGetFwVersion, ShmInternalComm->SlaveAddress, sizeof(int), Buffer); return nbytes; } int SendHwVersion(int Fd) { int nbytes; unsigned char Buffer[4]; memset(Buffer,0,sizeof(Buffer)); nbytes=FirmwareVersion; memcpy(Buffer,&nbytes,sizeof(int)); nbytes=SendMsg(Fd, MsgGetFwVersion, ShmInternalComm->SlaveAddress, sizeof(int), Buffer); return nbytes; } int SendStatusNotification(int Fd) { int nbytes; unsigned char Buffer[8]; memset(Buffer,0,sizeof(Buffer)); Buffer[0]=ShmSysConfigAndInfo->SysInfo.CcsChargingData[0].ConnectorPlugIn; Buffer[1]=ShmSysConfigAndInfo->SysInfo.CcsChargingData[0].PilotState; if(strlen(ShmStatusCodeData->PresentStatusCode[0])>0) { memcpy(Buffer+2,ShmStatusCodeData->PresentStatusCode[0],6); } nbytes=SendMsg(Fd, MsgStatusNotification, ShmInternalComm->SlaveAddress, 8, Buffer); return nbytes; } float DIN70121PhyValDecode(struct PhysicalValueType_DIN70121 PhysicalData) { short DataValue; int DataMultiplier; float Rtn; DataValue=PhysicalData.Value; DataMultiplier=PhysicalData.Multiplier; switch(PhysicalData.Unit) { case h_DIN70121: Rtn=(DataValue*(10^DataMultiplier)*60*60); return Rtn; case m_DIN70121: Rtn=(DataValue*(10^DataMultiplier)*60); return Rtn; case s_DIN70121: case A_DIN70121: case V_DIN70121: Rtn=(DataValue*(10^DataMultiplier)); return Rtn; case Ah_DIN70121: Rtn=(DataValue*(10^DataMultiplier)); return Rtn; case VA_DIN70121: case W_DIN70121: Rtn=(DataValue*(10^DataMultiplier)/1000); return Rtn;//kW case Wh_DIN70121: Rtn=(DataValue*(10^DataMultiplier)/1000); return Rtn;//kWh } } float ISO151182014PhyValDecode(struct PhysicalValueType_ISO15118_2014 PhysicalData) { short DataValue; int DataMultiplier; float Rtn; DataValue=PhysicalData.Value; DataMultiplier=PhysicalData.Multiplier; switch(PhysicalData.Unit) { case h_ISO15118_2014: Rtn=(DataValue*(10^DataMultiplier)*60*60); return Rtn; case m_ISO15118_2014: Rtn=(DataValue*(10^DataMultiplier)*60); return Rtn; case s_ISO15118_2014: case A_ISO15118_2014: case V_ISO15118_2014: Rtn=(DataValue*(10^DataMultiplier)); return Rtn; case W_ISO15118_2014: Rtn=(DataValue*(10^DataMultiplier)/1000); return Rtn;//kW case Wh_ISO15118_2014: Rtn=(DataValue*(10^DataMultiplier)/1000); return Rtn;//kWh } } int SendOutputReq(int Fd) { int nbytes; unsigned char Buffer[8]; unsigned short TmpValue; memset(Buffer,0,sizeof(Buffer)); if(ShmCcsData->CommProtocol==1) { //DIN70121 Buffer[0]=ShmCcsData->V2GMessage_DIN70121.PresentMsgFlowStatus; Buffer[1]=ShmCcsData->V2GMessage_DIN70121.CurrentDemandRequest.DC_EVStatus.EVRESSSOC; TmpValue=DIN70121PhyValDecode(ShmCcsData->V2GMessage_DIN70121.CurrentDemandRequest.EVTargetVoltage)*10; memcpy(Buffer+2,&TmpValue,2); TmpValue=DIN70121PhyValDecode(ShmCcsData->V2GMessage_DIN70121.CurrentDemandRequest.EVTargetCurrent)*10; memcpy(Buffer+4,&TmpValue,2); TmpValue=DIN70121PhyValDecode(ShmCcsData->V2GMessage_DIN70121.CurrentDemandRequest.RemainingTimeToFullSoC); memcpy(Buffer+6,&TmpValue,2); } else if(ShmCcsData->CommProtocol==2) { //ISO15118_2014 Buffer[0]=ShmCcsData->V2GMessage_ISO15118_2014.PresentMsgFlowStatus; Buffer[1]=ShmCcsData->V2GMessage_ISO15118_2014.CurrentDemandRequest.DC_EVStatus.EVRESSSOC; TmpValue=ISO151182014PhyValDecode(ShmCcsData->V2GMessage_ISO15118_2014.CurrentDemandRequest.EVTargetVoltage)*10; memcpy(Buffer+2,&TmpValue,2); TmpValue=ISO151182014PhyValDecode(ShmCcsData->V2GMessage_ISO15118_2014.CurrentDemandRequest.EVTargetCurrent)*10; memcpy(Buffer+4,&TmpValue,2); TmpValue=ISO151182014PhyValDecode(ShmCcsData->V2GMessage_ISO15118_2014.CurrentDemandRequest.RemainingTimeToFullSoC); memcpy(Buffer+6,&TmpValue,2); } nbytes=SendMsg(Fd, MsgStatusNotification, ShmInternalComm->SlaveAddress, 8, Buffer); return nbytes; } int SendBatteryInfo(int Fd) { int nbytes; unsigned char Buffer[8]; unsigned short TmpValue; memset(Buffer,0,sizeof(Buffer)); if((ShmCcsData->CommProtocol==2)&&(ShmCcsData->V2GMessage_ISO15118_2014.ChargeParameterDiscoveryRequest.RequestedEnergyTransferMode<=1)) Buffer[0]=1;//AC else Buffer[0]=0;//DC if(ShmCcsData->CommProtocol==1) { //DIN70121 TmpValue=DIN70121PhyValDecode(ShmCcsData->V2GMessage_DIN70121.ChargeParameterDiscoveryRequest.DC_EVChargeParameter.EVEnergyCapacity)*10; memcpy(Buffer+1,&TmpValue,2); TmpValue=DIN70121PhyValDecode(ShmCcsData->V2GMessage_DIN70121.ChargeParameterDiscoveryRequest.DC_EVChargeParameter.EVMaximumVoltageLimit)*10; memcpy(Buffer+3,&TmpValue,2); TmpValue=DIN70121PhyValDecode(ShmCcsData->V2GMessage_DIN70121.ChargeParameterDiscoveryRequest.DC_EVChargeParameter.EVMaximumCurrentLimit)*10; memcpy(Buffer+5,&TmpValue,2); } else if(ShmCcsData->CommProtocol==2) { //ISO15118_2014 if(Buffer[0]==0) { //DC TmpValue=ISO151182014PhyValDecode(ShmCcsData->V2GMessage_ISO15118_2014.ChargeParameterDiscoveryRequest.DC_EVChargeParameter.EVEnergyCapacity)*10; memcpy(Buffer+1,&TmpValue,2); TmpValue=ISO151182014PhyValDecode(ShmCcsData->V2GMessage_ISO15118_2014.ChargeParameterDiscoveryRequest.DC_EVChargeParameter.EVMaximumVoltageLimit)*10; memcpy(Buffer+3,&TmpValue,2); TmpValue=ISO151182014PhyValDecode(ShmCcsData->V2GMessage_ISO15118_2014.ChargeParameterDiscoveryRequest.DC_EVChargeParameter.EVMaximumCurrentLimit)*10; memcpy(Buffer+5,&TmpValue,2); } else { //AC TmpValue=ISO151182014PhyValDecode(ShmCcsData->V2GMessage_ISO15118_2014.ChargeParameterDiscoveryRequest.AC_EVChargeParameter.EAmount)*10; memcpy(Buffer+1,&TmpValue,2); TmpValue=ISO151182014PhyValDecode(ShmCcsData->V2GMessage_ISO15118_2014.ChargeParameterDiscoveryRequest.AC_EVChargeParameter.EVMaxVoltage)*10; memcpy(Buffer+3,&TmpValue,2); TmpValue=ISO151182014PhyValDecode(ShmCcsData->V2GMessage_ISO15118_2014.ChargeParameterDiscoveryRequest.AC_EVChargeParameter.EVMaxCurrent)*10; memcpy(Buffer+5,&TmpValue,2); } } nbytes=SendMsg(Fd, MsgStatusNotification, ShmInternalComm->SlaveAddress, 7, Buffer); return nbytes; } int SendStopEvent(int Fd) { int nbytes; unsigned char Buffer[8]; memset(Buffer,0,sizeof(Buffer)); Buffer[0]=0x01; if(strlen(ShmStatusCodeData->PresentStatusCode[0])>0) { memcpy(Buffer+2,ShmStatusCodeData->PresentStatusCode[0],6); } nbytes=SendMsg(Fd, MsgStatusNotification, ShmInternalComm->SlaveAddress, 7, Buffer); return nbytes; } int SendMiscInfo(int Fd) { int nbytes; unsigned char Buffer[8]; unsigned short TmpValue; memset(Buffer,0,sizeof(Buffer)); Buffer[0]=ShmSysConfigAndInfo->SysInfo.CcsChargingData[0].ConnectorPlugIn; TmpValue=ShmSysConfigAndInfo->SysInfo.CcsConnectorTemp; memcpy(Buffer+1,&TmpValue,2); Buffer[3]=(unsigned char)(ShmSysConfigAndInfo->SysInfo.CcsChargingData[0].PilotVoltage*10); Buffer[4]=ShmSysConfigAndInfo->SysInfo.CcsChargingData[0].PilotState; nbytes=SendMsg(Fd, MsgStatusNotification, ShmInternalComm->SlaveAddress, 7, Buffer); return nbytes; } /**************************************************************/ /************** Receiving Task*******************************/ /*************************************************************/ void CANReceiver(int fd) { pid_t tmp=0; struct can_frame frame; int nbytes; unsigned char FanspeedGetTime=0; if(CANReceiverPid==0) { tmp=fork(); if(tmp>0) { CANReceiverPid=tmp; { unsigned char buf[64]; memset(buf,0,sizeof(buf)); sprintf(buf,"renice -20 -p %d",tmp); system(buf); } return; } } while(1) { memset(&frame,0,sizeof(struct can_frame)); nbytes = read(fd, &frame, sizeof(struct can_frame)); if((frame.can_id==0)||(frame.can_id&0x08000000)||(((frame.can_id&0x000000FF)!=ShmInternalComm->SlaveAddress)&&((frame.can_id&0x000000FF)!=0))) continue; switch(frame.can_id&0x0000FF00)//Message ID { case MsgGetFwVersion: ShmInternalComm->InternalCommUnion.bits.FwVersion=1; break; case MsgGetHwVersion: ShmInternalComm->InternalCommUnion.bits.HwVersion=1; break; case MsgChargingPermission: ShmInternalComm->ChargingPermission=frame.data[0]; ShmSysConfigAndInfo->SysInfo.CcsChargingData[0].AvailableChargingPower=(float)((unsigned int)frame.data[2]<<8|frame.data[1])/10; ShmSysConfigAndInfo->SysInfo.CcsChargingData[0].AvailableChargingCurrent=(float)((unsigned int)frame.data[4]<<8|frame.data[3])/10; ShmSysConfigAndInfo->SysInfo.CcsChargingData[0].MaximumChargingVoltage=(float)((unsigned int)frame.data[6]<<8|frame.data[5])/10; break; case MsgPresentOutputPower: if( ShmInternalComm->SlaveAddress==1) { ShmSysConfigAndInfo->SysInfo.CcsChargingData[0].PresentChargingVoltage=(float)((unsigned int)frame.data[1]<<8|frame.data[0])/10; ShmSysConfigAndInfo->SysInfo.CcsChargingData[0].PresentChargingCurrent=(float)((unsigned int)frame.data[3]<<8|frame.data[2])/10; } else { ShmSysConfigAndInfo->SysInfo.CcsChargingData[0].PresentChargingVoltage=(float)((unsigned int)frame.data[5]<<8|frame.data[4])/10; ShmSysConfigAndInfo->SysInfo.CcsChargingData[0].PresentChargingCurrent=(float)((unsigned int)frame.data[7]<<8|frame.data[6])/10; } break; case MsgPresentOutputCapacity: if( ShmInternalComm->SlaveAddress==1) { ShmSysConfigAndInfo->SysInfo.CcsChargingData[0].AvailableChargingPower=(float)((unsigned int)frame.data[1]<<8|frame.data[0])/10; ShmSysConfigAndInfo->SysInfo.CcsChargingData[0].AvailableChargingCurrent=(float)((unsigned int)frame.data[3]<<8|frame.data[2])/10; } else { ShmSysConfigAndInfo->SysInfo.CcsChargingData[0].AvailableChargingPower=(float)((unsigned int)frame.data[5]<<8|frame.data[4])/10; ShmSysConfigAndInfo->SysInfo.CcsChargingData[0].AvailableChargingCurrent=(float)((unsigned int)frame.data[7]<<8|frame.data[6])/10; } break; case MsgGetOutputRequirement: ShmInternalComm->InternalCommUnion.bits.OutputRequirement=1; break; case MsgGetEvBatteryInfo: ShmInternalComm->InternalCommUnion.bits.EvBatteryInfo=1; break; case MsgEvseStopEvent: break; case MsgGetMiscInfo: ShmInternalComm->InternalCommUnion.bits.MiscInfo=1; break; case MsgDownloadRequest: break; case MsgStartBlockTransfer: break; case MsgDataTransfer: break; case MsgDownloadFinish: break; } } } /**************************************************************/ /************** main function***********************************/ /*************************************************************/ int main(int argc,char *argv[]) { int CanFd; struct can_frame frame; struct timeb StartTime,EndTime; unsigned int TmpValue; unsigned char Buffer[8]; //Initialization if(InitShareMemory()==0) { #ifdef SystemLogMessage StoreLogMsg("[CsuComm]main:InitShareMemory NG"); #endif if(ShmStatusCodeData!=NULL) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FailToCreateShareMemory=1; } sleep(5); return 0; } CanFd=InitCanBus(); CANReceiverPid=0; ShmInternalComm->SlaveAddress=0xFF; //Address Request while(ShmInternalComm->SlaveAddress==0xFF) { ftime(&StartTime); ftime(&EndTime); srandom(StartTime.millitm); TmpValue=random(); #ifdef Debug printf("[CsuComm]main => TmpValue=%d\n",TmpValue); #endif memset(Buffer,0,sizeof(Buffer)); memcpy(Buffer,&TmpValue,sizeof(int)); SendMsg(CanFd, MsgAddressRequest, ShmInternalComm->SlaveAddress, 4, Buffer); while(DiffTimeb(StartTime, EndTime)<100)//resend interval: 100ms { unsigned int TmpValue2=0; ftime(&EndTime); memset(&frame,0,sizeof(struct can_frame)); read(CanFd, &frame, sizeof(struct can_frame)); if((frame.can_id==0)||(frame.can_id&0x08000000)||((frame.can_id&0x0000FF00)!=MsgAddressAssign)||(frame.can_dlc!=4)) continue; memcpy(&TmpValue2,frame.data,sizeof(int)); if(TmpValue2==TmpValue) { ShmInternalComm->SlaveAddress=frame.can_id&0x000000FF; #ifdef SystemLogMessage { unsigned char Buffer[128]; memset(Buffer,0,sizeof(Buffer)); sprintf(Buffer,"[CsuComm]main: ShmCcsData->SlaveAddres=%d",ShmInternalComm->SlaveAddress); StoreLogMsg(Buffer); } #endif #ifdef Debug printf("[CsuComm]main => ShmCcsData->SlaveAddres=0x%x\n",ShmCcsData->SlaveAddres); #endif break; } } } CANReceiver(CanFd); //main loop ftime(&StartTime); while(1) { ftime(&EndTime); if(DiffTimeb(StartTime, EndTime)>=1000) { SendStatusNotification(CanFd); ftime(&StartTime); } if(ShmInternalComm->InternalCommUnion.bits.FwVersion==1) { SendFwVersion(CanFd); ShmInternalComm->InternalCommUnion.bits.FwVersion=0; } if(ShmInternalComm->InternalCommUnion.bits.HwVersion==1) { SendHwVersion(CanFd); ShmInternalComm->InternalCommUnion.bits.HwVersion=0; } if(ShmInternalComm->InternalCommUnion.bits.OutputRequirement==1) { SendOutputReq(CanFd); ShmInternalComm->InternalCommUnion.bits.OutputRequirement=0; } if(ShmInternalComm->InternalCommUnion.bits.EvBatteryInfo==1) { SendBatteryInfo(CanFd); ShmInternalComm->InternalCommUnion.bits.EvBatteryInfo=0; } if(ShmInternalComm->InternalCommUnion.bits.MiscInfo==1) { SendMiscInfo(CanFd); ShmInternalComm->InternalCommUnion.bits.MiscInfo=0; } } EndProcess: if(CANReceiverPid>0) { char Buf[32]; memset(Buf,0,32); sprintf(Buf,"kill %d",CANReceiverPid); system(Buf); } close(CanFd); 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"); system("/sbin/ip link set can0 down"); system("killall CsuComm"); }