/* * Module_Payment_Enegate.c * * Created on: 2022/5/4 * Author: folus */ #include "Module_Payment_Enegate.h" ParsingRatedCur modelnameInfo = {0}; uint8_t gunType[4] = {0}; struct timespec tmr[4][TIMER_CNT]; Message rx; Message tx; //========================================== // Common routine //========================================== int StoreLogMsg(const char *fmt, ...) { char Buf[65536+256]; char buffer[65536]; //char Buf[4096+256]; //char buffer[4096]; time_t CurrentTime; struct tm *tm; struct timeval tv; va_list args; va_start(args, fmt); int rc = vsnprintf(buffer, sizeof(buffer), fmt, args); va_end(args); memset(Buf,0,sizeof(Buf)); CurrentTime = time(NULL); tm=localtime(&CurrentTime); gettimeofday(&tv, NULL); // get microseconds, 10^-6 sprintf(Buf,"echo -n \"[%04d.%02d.%02d %02d:%02d:%02d.%03ld]%s\" >> /Storage/SystemLog/[%04d.%02d]PaymentLog", tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec,tv.tv_usec/1000, buffer, tm->tm_year+1900,tm->tm_mon+1); system((const char*)Buf); #ifdef ConsloePrintLog printf("[%04d.%02d.%02d %02d:%02d:%02d.%03ld]%s", tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec,tv.tv_usec/1000, buffer); #endif return rc; } /** * Execute shell command * @param cmd: shell command string * @return shell command execution result */ int runShellCmd(const char*cmd) { int result = FAIL; char buf[256]; FILE *fp; fp = popen(cmd, "r"); if(fp != NULL) { while(fgets(buf, sizeof(buf), fp) != NULL) { DEBUG_INFO("%s\n", buf); } result = PASS; } pclose(fp); return result; } /** * * @param timer */ void refreshStartTimer(struct timespec *timer) { clock_gettime(CLOCK_MONOTONIC, timer); } /** * * @param timer * @return */ int getDiffSecNow(struct timespec timer) { struct timespec timerNow; clock_gettime(CLOCK_MONOTONIC, &timerNow); return (int)((((unsigned long)(timerNow.tv_sec - timer.tv_sec) * 1000) + ((unsigned long)((timerNow.tv_nsec / 1000000) - (timer.tv_nsec / 1000000))))/1000); } /** * * @param ST */ long long DiffTimebWithNow(struct timeb ST) { //return milli-second struct timeb ET; long long StartTime,StopTime; ftime(&ET); StartTime=(long long)ST.time; StopTime=(long long)ET.time; return ((StopTime-StartTime)*1000) + (ET.millitm-ST.millitm); } /** * * @return */ int getTimePassSinceToday() { int result = -1; time_t t; struct tm *tmStartToday; struct timeb tbStartToday; t=time(NULL); tmStartToday=localtime(&t); tmStartToday->tm_hour = 0; tmStartToday->tm_min = 0; tmStartToday->tm_sec = 0; tbStartToday.time = mktime(tmStartToday); tbStartToday.millitm = 0; result = DiffTimebWithNow(tbStartToday)/1000; return result; } /** * * @param startTime * @param stopTime * @return */ int isPausedService(uint8_t *startTime, uint8_t *stopTime) { int result = FALSE; if((strlen((char*)startTime) > 0) && (strlen((char*)stopTime) > 0)) { int start, stop; if(sscanf((char*)startTime, "%d", &start) && sscanf((char*)stopTime, "%d", &stop)) { if(((getTimePassSinceToday() < ((start/100)*3600)+((start%100)*60))) || ((((stop/100)*3600)+((stop%100)*60)) <= getTimePassSinceToday())) { result = TRUE; } } } return result; } /** * Show communication raw data to debug info * @param data: raw data * @param len: data length * @param isRX: is receive data */ void show_raw(uint8_t *data, uint16_t len, uint8_t isRX) { uint8_t output[512]={0}; if(isRX) DEBUG_INFO("RX ---------------------------------------------\n"); else DEBUG_INFO("TX ---------------------------------------------\n"); DEBUG_INFO(" 0 1 2 3 4 5 6 7 8 9 A B C D E F \n"); DEBUG_INFO("------------------------------------------------\n"); memset(output, 0x00, ARRAY_SIZE(output)); for(int idx=0;idxsize-3);idx++) { result += data->buffer[idx]; } //DEBUG_INFO("calChksum: %02X\n", (result&0xff)); return result; } /** * * @param result */ void getDateTimeString(char* result) { time_t CurrentTime; struct tm *tm; CurrentTime = time(NULL); tm=localtime(&CurrentTime); sprintf(result, "%04d%02d%02d%02d%02d%02d", tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec); } //========================================== // Init share memory //========================================== /** * Share memory initialization * @return function result */ int InitShareMemory() { int result = PASS; int MeterSMId; #ifndef X86 //init ShmSysConfigAndInfo if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo), 0777)) < 0) { DEBUG_ERROR("shmget ShmSysConfigAndInfo NG\n"); result = FAIL; } else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1) { DEBUG_ERROR("shmat ShmSysConfigAndInfo NG\n"); result = FAIL; } else {} //init ShmStatusCodeData if ((MeterSMId = shmget(ShmStatusCodeKey, sizeof(struct StatusCodeData), 0777)) < 0) { DEBUG_ERROR("shmget ShmStatusCodeData NG\n"); result = FAIL; } else if ((ShmStatusCodeData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { DEBUG_ERROR("shmat ShmStatusCodeData NG\n"); result = FAIL; } else {} //init ShmOCPP16Data if ((MeterSMId = shmget(ShmOcppModuleKey, sizeof(struct OCPP16Data), 0777)) < 0) { DEBUG_ERROR("shmget ShmOCPP16Data NG\n"); result = FAIL; } else if ((ShmOCPP16Data = shmat(MeterSMId, NULL, 0)) == (void *) -1) { DEBUG_ERROR("shmat ShmOCPP16Data NG\n"); result = FAIL; } else {} // Parsing model name to get related info about charger if(RatedCurrentParsing((char*)ShmSysConfigAndInfo->SysConfig.ModelName, &modelnameInfo) != -1) { DEBUG_INFO("Model name rated power: %d\n", modelnameInfo.ratedPower); if((ShmSysConfigAndInfo->SysConfig.ModelName[0]=='D') && ((ShmSysConfigAndInfo->SysConfig.ModelName[1]=='B') || (ShmSysConfigAndInfo->SysConfig.ModelName[1]=='K') || (ShmSysConfigAndInfo->SysConfig.ModelName[1]=='O')) ) // 'D' means DC { // DO series for(int gun_index=0; gun_indexsize = read(uart, rx->buffer, ARRAY_SIZE(rx->buffer)); #ifdef DEBUG show_raw(rx->buffer, rx->size, YES); #endif if(calChksum(rx)) { result = PASS; } return result; } /** * * @param uart * @param tx * @return */ int pollingResponse(int uart, Message* tx) { int result=FAIL; tcflush(uart,TCIOFLUSH); tx->buffer[tx->size-3] = calChksum(tx); #ifdef DEBUG show_raw(tx->buffer, tx->size, NO); #endif if(write(uart, tx->buffer, tx->size) > 0) { result = PASS; } else { DEBUG_ERROR("pollingResponse fail.\n"); } return result; } /** * * @param gun_index */ void getResponseState(uint8_t gun_index, uint8_t *charger_state, uint8_t *energy) { struct ChargingInfoData *targetChargingInfoData = NULL; // Get target gun data if(gunType[gun_index] == GUN_TYPE_CHAdeMO) { for (int index = 0; index < CHAdeMO_QUANTITY; index++) { if ((ShmSysConfigAndInfo->SysInfo.ChademoChargingData[index].Index == gun_index)) { targetChargingInfoData = &ShmSysConfigAndInfo->SysInfo.ChademoChargingData[index]; break; } } } else if(gunType[gun_index] == GUN_TYPE_CCS) { for (int index = 0; index < CCS_QUANTITY; index++) { if ((ShmSysConfigAndInfo->SysInfo.CcsChargingData[index].Index == gun_index)) { targetChargingInfoData = &ShmSysConfigAndInfo->SysInfo.CcsChargingData[index]; break; } } } else if(gunType[gun_index] == GUN_TYPE_GBT) { for (int index = 0; index < GB_QUANTITY; index++) { if ((ShmSysConfigAndInfo->SysInfo.GbChargingData[index].Index == gun_index)) { targetChargingInfoData = &ShmSysConfigAndInfo->SysInfo.GbChargingData[index]; break; } } } else if(gunType[gun_index] == GUN_TYPE_DO) { for (int index = 0; index < GENERAL_GUN_QUANTITY; index++) { if ((ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].GeneralChargingData.Index == gun_index)) { targetChargingInfoData = &ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].GeneralChargingData; break; } } } else if(gunType[gun_index] == GUN_TYPE_AC) { for (int index = 0; index < AC_QUANTITY; index++) { if ((ShmSysConfigAndInfo->SysInfo.AcChargingData[index].Index == gun_index)) { targetChargingInfoData = &ShmSysConfigAndInfo->SysInfo.AcChargingData[index]; break; } } } // 1. Check gun status and cover to Enegate state code if(targetChargingInfoData != NULL) { if(targetChargingInfoData->SystemStatus == SYS_MODE_BOOTING)//S_IDLE { sprintf((char*)charger_state, "%05d", 0); memcpy(&tx.buffer[3], &charger_state[0], 5); } else if((targetChargingInfoData->SystemStatus == SYS_MODE_IDLE) || (targetChargingInfoData->SystemStatus == SYS_MODE_AUTHORIZING))//S_IDLE { if(!ShmSysConfigAndInfo->SysInfo.enegate.Operation.bits[gun_index].isConnectTimeout) { if(!ShmSysConfigAndInfo->SysInfo.enegate.Operation.bits[gun_index].isAutoStartEnable) { sprintf((char*)charger_state, "%05d", 1000); memcpy(&tx.buffer[3], &charger_state[0], 5); } else { sprintf((char*)charger_state, "%05d", 41000); memcpy(&tx.buffer[3], &charger_state[0], 5); } } else { sprintf((char*)charger_state, "%05d", 2010); memcpy(&tx.buffer[3], &charger_state[0], 5); ShmSysConfigAndInfo->SysInfo.enegate.Operation.bits[gun_index].isConnectTimeout = OFF; } } else if ( ((targetChargingInfoData->SystemStatus >= SYS_MODE_MODE_REASSIGN_CHECK)&&(targetChargingInfoData->SystemStatus <= SYS_MODE_PREPARE_FOR_EVSE)) || ((targetChargingInfoData->SystemStatus >= SYS_MODE_CCS_PRECHARGE_STEP0) && (targetChargingInfoData->SystemStatus <= SYS_MODE_CCS_PRECHARGE_STEP1) ) ) //S_PRECHARGE { if(!ShmSysConfigAndInfo->SysInfo.enegate.Operation.bits[gun_index].isConnectTimeout) { if(!ShmSysConfigAndInfo->SysInfo.enegate.Operation.bits[gun_index].isAutoStartEnable) { sprintf((char*)charger_state, "%05d", 2000); memcpy(&tx.buffer[3], &charger_state[0], 5); } else { sprintf((char*)charger_state, "%05d", 42000); memcpy(&tx.buffer[3], &charger_state[0], 5); } } else { sprintf((char*)charger_state, "%05d", 2010); memcpy(&tx.buffer[3], &charger_state[0], 5); ShmSysConfigAndInfo->SysInfo.enegate.Operation.bits[gun_index].isConnectTimeout = OFF; } } else if (targetChargingInfoData->SystemStatus == SYS_MODE_CHARGING) //S_CHARGING { if(!ShmSysConfigAndInfo->SysInfo.enegate.Operation.bits[gun_index].isAutoStartEnable) { sprintf((char*)charger_state, "%05d", 3000); memcpy(&tx.buffer[3], &charger_state[0], 5); sprintf((char*)energy, "%08d", (int)(targetChargingInfoData->PresentChargedEnergy*100)); memcpy(&tx.buffer[22], &energy[0], 8); memcpy(&tx.buffer[30], &energy[0], 8); } else { sprintf((char*)charger_state, "%05d", 43000); memcpy(&tx.buffer[3], &charger_state[0], 5); sprintf((char*)energy, "%08d", (int)(targetChargingInfoData->PresentChargedEnergy*100)); memcpy(&tx.buffer[22], &energy[0], 8); memcpy(&tx.buffer[30], &energy[0], 8); } } else if ((targetChargingInfoData->SystemStatus == SYS_MODE_TERMINATING) || (targetChargingInfoData->SystemStatus == SYS_MODE_COMPLETE)) { if(!ShmSysConfigAndInfo->SysInfo.enegate.Operation.bits[gun_index].isAutoStartEnable) { /* * TODO: * 1. Stop reason transfer */ sprintf((char*)charger_state, "%05d", 5020); memcpy(&tx.buffer[3], &charger_state[0], 5); sprintf((char*)energy, "%08d", (int)(targetChargingInfoData->PresentChargedEnergy*100)); memcpy(&tx.buffer[22], &energy[0], 8); memcpy(&tx.buffer[30], &energy[0], 8); } else { /* * TODO: * 1. Stop reason transfer */ sprintf((char*)charger_state, "%05d", 45020); memcpy(&tx.buffer[3], &charger_state[0], 5); sprintf((char*)energy, "%08d", (int)(targetChargingInfoData->PresentChargedEnergy*100)); memcpy(&tx.buffer[22], &energy[0], 8); memcpy(&tx.buffer[30], &energy[0], 8); } } else if ((targetChargingInfoData->SystemStatus == SYS_MODE_MAINTAIN) || (targetChargingInfoData->SystemStatus == SYS_MODE_DEBUG) || (targetChargingInfoData->SystemStatus == SYS_MODE_UPDATE)) // ---> Unavailable { if(!ShmSysConfigAndInfo->SysInfo.enegate.Operation.bits[gun_index].isAutoStartEnable) { sprintf((char*)charger_state, "%05d", 100); memcpy(&tx.buffer[3], &charger_state[0], 5); } else { sprintf((char*)charger_state, "%05d", 40100); memcpy(&tx.buffer[3], &charger_state[0], 5); } } else if ((targetChargingInfoData->SystemStatus == SYS_MODE_FAULT) || (targetChargingInfoData->SystemStatus == SYS_MODE_ALARM)) //S_ALARM,S_FAULT ---> Faulted { if(!ShmSysConfigAndInfo->SysInfo.enegate.Operation.bits[gun_index].isAutoStartEnable) { if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.EmergencyStopTrip) { sprintf((char*)charger_state, "%05d", 5108); } else if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.ChademoGfdTrip || ShmStatusCodeData->AlarmCode.AlarmEvents.bits.GbGfdTrip || ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CcsGfdTrip || ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcGroundfaultFail) { sprintf((char*)charger_state, "%05d", 5109); } else if(ShmStatusCodeData->FaultCode.FaultEvents.bits.ChademoConnectorLockFail || ShmStatusCodeData->FaultCode.FaultEvents.bits.GbConnectorLockFail || ShmStatusCodeData->FaultCode.FaultEvents.bits.AcConnectorLockFail) { sprintf((char*)charger_state, "%05d", 5104); } else if(ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoIsolationResultFail || ShmStatusCodeData->InfoCode.InfoEvents.bits.ERROR_CODE_GBT_ISOLATION_RESULT_FAIL) { sprintf((char*)charger_state, "%05d", 5102); } else { sprintf((char*)charger_state, "%05d", 5107); } memcpy(&tx.buffer[3], &charger_state[0], 5); } else { if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.EmergencyStopTrip) { sprintf((char*)charger_state, "%05d", 45108); } else if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.ChademoGfdTrip || ShmStatusCodeData->AlarmCode.AlarmEvents.bits.GbGfdTrip || ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CcsGfdTrip || ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcGroundfaultFail) { sprintf((char*)charger_state, "%05d", 45109); } else if(ShmStatusCodeData->FaultCode.FaultEvents.bits.ChademoConnectorLockFail || ShmStatusCodeData->FaultCode.FaultEvents.bits.GbConnectorLockFail || ShmStatusCodeData->FaultCode.FaultEvents.bits.AcConnectorLockFail) { sprintf((char*)charger_state, "%05d", 45104); } else if(ShmStatusCodeData->InfoCode.InfoEvents.bits.ChademoIsolationResultFail || ShmStatusCodeData->InfoCode.InfoEvents.bits.ERROR_CODE_GBT_ISOLATION_RESULT_FAIL) { sprintf((char*)charger_state, "%05d", 45102); } else { sprintf((char*)charger_state, "%05d", 45107); } memcpy(&tx.buffer[3], &charger_state[0], 5); } } } } //========================================== // Main loop //========================================== int main(void) { int UartFd; //=============================================== // Initialization //=============================================== if(InitShareMemory() == FAIL) { DEBUG_ERROR("InitShareMemory NG\n"); if(ShmStatusCodeData!=NULL) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FailToCreateShareMemory=1; } sleep(5); return FAIL; } UartFd=InitComPort(); if(UartFd<0) { DEBUG_ERROR("InitComPort NG\n"); if(ShmStatusCodeData!=NULL) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.CsuInitFailed=1; } sleep(5); return FAIL; } else { DEBUG_INFO("%s port open success.\n", TTY_PORT); } refreshStartTimer(&tmr[0][TIMER_COMM_TIMEOUT]); DEBUG_INFO("Payment module initialize completed...%s\n", FIRMWARE_VERSION); for(;;) { if(ShmSysConfigAndInfo->SysInfo.enegate.isEnable) { // Communication timeout if(getDiffSecNow(tmr[0][TIMER_COMM_TIMEOUT]) >= 10) { if(!ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PaymentCommTimeout) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PaymentCommTimeout = ON; DEBUG_WARN("Payment system communication timeout.\n"); } } else { if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PaymentCommTimeout) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PaymentCommTimeout = OFF; DEBUG_WARN("Payment system communication recover.\n"); } } if((getInputBufferCount(UartFd) >= 24)) { if(pollingRequest(UartFd, &rx)) { refreshStartTimer(&tmr[0][TIMER_COMM_TIMEOUT]); uint8_t charger_state[6] = {0}; uint8_t energy[9] = {0}; static uint8_t charger_state_previous[6] = {0}; static uint8_t energy_previous[9] = {0}; uint16_t cmd = ((rx.buffer[3]-0x30)*1000) + ((rx.buffer[4]-0x30)*100) + ((rx.buffer[5]-0x30)*10) + ((rx.buffer[6]-0x30)*1); uint8_t id = rx.buffer[1]; uint8_t gun_index = (id-0x30-ID_OFFSET); tx.size = 41; tx.buffer[0] = STX; tx.buffer[1] = id; tx.buffer[2] = ACK; sprintf((char*)&tx.buffer[3], "%05d", 0); getDateTimeString((char*)&tx.buffer[8]); sprintf((char*)energy, "00000000"); sprintf((char*)&tx.buffer[22], "00000000"); sprintf((char*)&tx.buffer[30], "00000000"); tx.buffer[39] = CR; tx.buffer[40] = LF; // 1. Check ID in command message if(((0<=gun_index) && (gun_index<(ShmSysConfigAndInfo->SysConfig.TotalConnectorCount+1)))) { switch(cmd) { case HOST_CMD_GET_STATUS: getResponseState(gun_index, charger_state, energy); if((strstr((char*)charger_state_previous, (char*)charger_state) == NULL) || (strstr((char*)energy_previous, (char*)energy) == NULL)) { DEBUG_INFO("id(%c)=> HOST_CMD_GET_STATUS(1000): %s, Energy: %s\n", id, charger_state, energy); memcpy(charger_state_previous, charger_state, ARRAY_SIZE(charger_state)); memcpy(energy_previous, energy, ARRAY_SIZE(energy)); } break; case HOST_CMD_AUTH_CHECKING: ShmSysConfigAndInfo->SysInfo.enegate.Operation.bits[gun_index].isAuthorizing = ON; getResponseState(gun_index, charger_state, energy); DEBUG_INFO("id(%c)=> HOST_CMD_AUTH_CHECKING(9000): %s, Energy: %s\n", id, charger_state, energy); break; case HOST_CMD_AUTH_CANCEL: ShmSysConfigAndInfo->SysInfo.enegate.Operation.bits[gun_index].isAuthorizing = OFF; ShmSysConfigAndInfo->SysInfo.enegate.Operation.bits[gun_index].isAuthorized = ON; ShmSysConfigAndInfo->SysInfo.enegate.Operation.bits[gun_index].isAuthorizedPass = OFF; getResponseState(gun_index, charger_state, energy); DEBUG_INFO("id(%c)=> HOST_CMD_AUTH_CANCEL(9001): %s, Energy: %s\n", id, charger_state, energy); break; case HOST_CMD_AUTH_PASS: ShmSysConfigAndInfo->SysInfo.enegate.Operation.bits[gun_index].isAuthorizing = OFF; ShmSysConfigAndInfo->SysInfo.enegate.Operation.bits[gun_index].isAuthorized = ON; ShmSysConfigAndInfo->SysInfo.enegate.Operation.bits[gun_index].isAuthorizedPass = ON; getResponseState(gun_index, charger_state, energy); DEBUG_INFO("id(%c)=> HOST_CMD_AUTH_PASS(3000): %s, Energy: %s\n", id, charger_state, energy); break; case HOST_CMD_AUTH_FAIL: ShmSysConfigAndInfo->SysInfo.enegate.Operation.bits[gun_index].isAuthorizing = OFF; ShmSysConfigAndInfo->SysInfo.enegate.Operation.bits[gun_index].isAuthorized = ON; ShmSysConfigAndInfo->SysInfo.enegate.Operation.bits[gun_index].isAuthorizedPass = OFF; getResponseState(gun_index, charger_state, energy); DEBUG_INFO("id(%c)=> HOST_CMD_AUTH_FAIL(3001): %s, Energy: %s\n", id, charger_state, energy); break; case HOST_CMD_AUTO_START_ENABLE: ShmSysConfigAndInfo->SysInfo.enegate.Operation.bits[gun_index].isAutoStartEnable = ON; ShmSysConfigAndInfo->SysConfig.AuthorisationMode = 1; getResponseState(gun_index, charger_state, energy); DEBUG_INFO("id(%c)=> HOST_CMD_AUTO_START_ENABLE(0200): %s, Energy: %s\n", id, charger_state, energy); break; case HOST_CMD_AUTOSTART_DIABLE: ShmSysConfigAndInfo->SysInfo.enegate.Operation.bits[gun_index].isAutoStartEnable = OFF; ShmSysConfigAndInfo->SysConfig.AuthorisationMode = 0; getResponseState(gun_index, charger_state, energy); DEBUG_INFO("id(%c)=> HOST_CMD_AUTOSTART_DIABLE(0222): %s, Energy: %s\n", id, charger_state, energy); break; case HOST_CMD_SESSION_STOP: ShmSysConfigAndInfo->SysInfo.enegate.Operation.bits[gun_index].isSessionStopReq = ON; getResponseState(gun_index, charger_state, energy); DEBUG_INFO("id(%c)=> HOST_CMD_SESSION_STOP(4000): %s, Energy: %s\n", id, charger_state, energy); break; case HOST_CMD_PAUSE_ENABLE: ShmSysConfigAndInfo->SysInfo.enegate.Operation.bits[gun_index].isStopService = ON; getResponseState(gun_index, charger_state, energy); DEBUG_INFO("id(%c)=> HOST_CMD_PAUSE_ENABLE(100): %s, Energy: %s\n", id, charger_state, energy); break; case HOST_CMD_PAUSE_DISABLE: ShmSysConfigAndInfo->SysInfo.enegate.Operation.bits[gun_index].isStopService = OFF; getResponseState(gun_index, charger_state, energy); DEBUG_INFO("id(%c)=> HOST_CMD_PAUSE_DISABLE(111): %s, Energy: %s\n", id, charger_state, energy); break; default: getResponseState(gun_index, charger_state, energy); DEBUG_WARN("id(%c)=> Unknown host command(%d): %s, Energy: %s.\n", id, cmd, charger_state, energy); tx.buffer[2] = NAK; break; } // Synchronize date time every 10 minutes if(getDiffSecNow(tmr[gun_index][TIMER_UPDATE_RTC]) >= 600) { struct tm tmOrg; struct tm *tmTarget; struct timeb tbTarget; char buf[64]={0}; tmOrg.tm_year = (((rx.buffer[7]-0x30)*1000)+((rx.buffer[8]-0x30)*100)+((rx.buffer[9]-0x30)*10)+((rx.buffer[10]-0x30)*1)) - 1900; tmOrg.tm_mon = (((rx.buffer[11]-0x30)*10)+((rx.buffer[12]-0x30)*1)) - 1; tmOrg.tm_mday = (((rx.buffer[13]-0x30)*10)+((rx.buffer[14]-0x30)*1)); tmOrg.tm_hour = (((rx.buffer[15]-0x30)*10)+((rx.buffer[16]-0x30)*1)); tmOrg.tm_min = (((rx.buffer[17]-0x30)*10)+((rx.buffer[18]-0x30)*1)); tmOrg.tm_sec = (((rx.buffer[19]-0x30)*10)+((rx.buffer[20]-0x30)*1)); tmOrg.tm_gmtoff = 0; tbTarget.time = mktime(&tmOrg); tbTarget.timezone = 0; tbTarget.time -= (9*3600); // Japan always in UTC+9 tmTarget = gmtime(&tbTarget.time); sprintf(buf, "date -s '%04d-%02d-%02d %02d:%02d:%02d'", (tmTarget->tm_year+1900), (tmTarget->tm_mon+1), tmTarget->tm_mday, tmTarget->tm_hour, tmTarget->tm_min, tmTarget->tm_sec); system(buf); system("/sbin/hwclock -w --systohc"); refreshStartTimer(&tmr[gun_index][TIMER_UPDATE_RTC]); } } else if(id == 'a') { if(cmd == HOST_CMD_GET_SELECTED_ID) { static int previousId = -1; tx.buffer[1] = (0x30 + ShmSysConfigAndInfo->SysInfo.CurGunSelected + ID_OFFSET); sprintf((char*)&tx.buffer[3], "%05d", 9302); if(previousId != tx.buffer[1]) { DEBUG_INFO("id(%c)=> HOST_CMD_GET_SELECTED_ID(9301): %c\n", id, tx.buffer[1]); previousId = tx.buffer[1]; } } else if(cmd == HOST_CMD_SET_SERVICE_TIME) { memset(ShmSysConfigAndInfo->SysInfo.enegate.serviceStartTimestamp, 0x00, ARRAY_SIZE(ShmSysConfigAndInfo->SysInfo.enegate.serviceStartTimestamp)); memset(ShmSysConfigAndInfo->SysInfo.enegate.serviceStopTimestamp, 0x00, ARRAY_SIZE(ShmSysConfigAndInfo->SysInfo.enegate.serviceStopTimestamp)); sprintf((char*)&tx.buffer[3], "%05d", 9200); memcpy(ShmSysConfigAndInfo->SysInfo.enegate.serviceStartTimestamp, &rx.buffer[7], 4); memcpy(ShmSysConfigAndInfo->SysInfo.enegate.serviceStopTimestamp, &rx.buffer[11], 4); DEBUG_INFO("id(%c)=> HOST_CMD_SET_SERVICE_TIME(9200): %s - %s with UTC+9\n", id, ShmSysConfigAndInfo->SysInfo.enegate.serviceStartTimestamp, ShmSysConfigAndInfo->SysInfo.enegate.serviceStopTimestamp); } else { DEBUG_WARN("Wrong id(%c) with get selected id command(%d).\n", id, cmd); tx.buffer[2] = NAK; } } else { DEBUG_WARN("Wrong id(%c) with command(%d).\n", id, cmd); tx.buffer[2] = NAK; } /* * TODO: * 1. Service time check locally. * 2. Usually server will send enable / disable command. */ //ShmSysConfigAndInfo->SysInfo.enegate.Operation.bits[gun_index].isStopService = isPausedService(ShmSysConfigAndInfo->SysInfo.enegate.serviceStartTimestamp, ShmSysConfigAndInfo->SysInfo.enegate.serviceStopTimestamp); } else { // Command with wron check sum. tx.size = 41; tx.buffer[0] = STX; tx.buffer[1] = rx.buffer[1]; tx.buffer[2] = NAK; getDateTimeString((char*)&tx.buffer[8]); sprintf((char*)&tx.buffer[22], "00000000"); sprintf((char*)&tx.buffer[30], "00000000"); tx.buffer[39] = CR; tx.buffer[40] = LF; } pollingResponse(UartFd, &tx); } } usleep(100000); } }