#include "evpLocal.h" server_info g_server; /* server information */ word g_sequence = 0; int g_sockId = -1; /* server socket connect id */ char g_serverConn = D_SERVER_DISCONNECT; /* server connect flag */ char g_serverLogin= D_SERVER_DISCONNECT; /* server connect flag */ int g_termApp = D_TERMAPP_NO; /* app terminate flag */ struct tm g_tmTod; /* system time variable */ char g_serviceId[EVPS_SERVICE_ID_SIZE+1]; /* *************************************************************************************************** * global variables ***************************************************************************************************/ char* BuildTime = __DATE__ " " __TIME__; char* AppName = "evpLocal"; int _LogWrite(const char *fmt, ...) { va_list args; va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); return 1; } int _read_config_file() { char *pServerIp = "10.4.4.51"; //char *pServerIp = "192.168.20.91"; memset((char*)&g_server, 0x00, sizeof(g_server)); memcpy(g_server.ipaddr, pServerIp, strlen(pServerIp)); g_server.port = 7800; _LogWrite("EVPS SERVER: %s::%d\n", g_server.ipaddr, g_server.port); return 0; } void _getNetTime(struct tm *localTod) { time_t localTime; localTime = time(NULL); localtime_r(&localTime, localTod); } void _cliEpipe(int sig) { _LogWrite("[ERROR] SIGPIPE.........\n"); signal(SIGPIPE, _cliEpipe); } void _cliBreak(int sig) { _LogWrite("[ERROR] SIGUSR1.........\n"); g_termApp = D_TERMAPP_YES; } void _cliNetDisconnected(void) { if (g_sockId > 0) { close(g_sockId); g_sockId = -1; } g_serverConn = D_SERVER_DISCONNECT; } int _cliInit(void) { char opt; struct sockaddr_in client; if (g_serverConn == D_SERVER_CONNECT) { return g_serverConn; } if ((g_sockId = socket(AF_INET, SOCK_STREAM, 0)) < 0) { g_serverConn = D_SERVER_DISCONNECT; return g_serverConn; } memset((char *) &client, 0x00, sizeof(client)); client.sin_family = AF_INET; client.sin_addr.s_addr = inet_addr(g_server.ipaddr); client.sin_port = htons(g_server.port); opt = 1; setsockopt(g_sockId, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(int)); setsockopt(g_sockId, SOL_SOCKET, SO_KEEPALIVE, (char*)&opt, sizeof(int)); if (connect(g_sockId, (struct sockaddr *)&client, sizeof(struct sockaddr_in)) < 0) { _LogWrite("NetWork Connected..Error...\n"); _cliNetDisconnected(); return g_serverConn; } g_serverConn = D_SERVER_CONNECT; g_serverLogin = D_SERVER_DISCONNECT; _LogWrite("NetWork Connected...\n"); return g_serverConn; } void dumpData(char *AData, int ALen) { int ii, jj, pos; fprintf(stderr, "\nDATA DUMP***************\n"); for(ii = 0; ii < ALen; ii += 16) { for(jj = 0; jj < 16; ++jj) { pos = ii + jj; if (pos >= ALen) { break; } fprintf(stderr, "%02X ", (byte)(AData[pos] & 0xFF)); } fprintf(stderr, "\n"); } fprintf(stderr, "\n\n"); } int _cliSend(char* AData, int APktSize) { int writeCount; dumpData(AData, APktSize); if ((writeCount = send(g_sockId, AData, APktSize, 0)) <= 0) { fprintf(stderr, "DATA Send Failed!!!\n"); _cliNetDisconnected(); return -1; } fprintf(stderr, "DATA Send %d Bytes, RC(%d)!!!\n", APktSize, writeCount); usleep(10000); return 0; } void makeHead(pkt_headp pHead, byte opCode, word sequence, word current, word total, word length) { _getNetTime(&g_tmTod); memset(pHead, 0x00, sizeof(pkt_head)); pHead->stx1 = EVPS_STX1; pHead->stx2 = EVPS_STX2; pHead->opCode = opCode; SETWORD(pHead->sequence, sequence); SETWORD(pHead->current, current); SETWORD(pHead->total, total); SETWORD(pHead->year, g_tmTod.tm_year+1900); pHead->month = g_tmTod.tm_mon+1; pHead->day = g_tmTod.tm_mday; pHead->hour = g_tmTod.tm_hour; pHead->min = g_tmTod.tm_min; pHead->sec = g_tmTod.tm_sec; memcpy(pHead->serviceId, g_serviceId, EVPS_SERVICE_ID_SIZE); SETWORD(pHead->dataLength, length); //fprintf(stderr, "***** HEAD: %02X, SEQ: %d, CUR: %d, TOT: %d, LENGTH: %d, SERIVCE ID: %s\n", opCode, sequence, current, total, length, g_serviceId); } void sendEvpsData(byte opCode, char *pData, int length) { evps_pkt pkt; int sequence = g_sequence++; int ii, idx, current, total, dataSize; current = 1; total = (length / MAX_DATA_SIZE) + 1; if (0 == (length % MAX_DATA_SIZE)) { total--; } for (ii = 0; ii < total; ii++) { dataSize = MAX_DATA_SIZE; if ((ii+1) * MAX_DATA_SIZE > length) { dataSize = length - (MAX_DATA_SIZE * ii); } fprintf(stderr, "ServiceId: %s, OpCode: %02X, Sequence: %d, Total: %d, Current: %d, DataLength: %d\n", g_serviceId, opCode, sequence, total, current, dataSize); makeHead(&pkt.head, opCode, sequence, current++, total, dataSize); idx = ii*MAX_DATA_SIZE; memcpy(&pkt.data[0], &pData[idx], dataSize); _cliSend((char*)&pkt, sizeof(pkt_head) + dataSize); } } void makeServiceId() { _getNetTime(&g_tmTod); memset(g_serviceId, 0x00, sizeof(g_serviceId)); sprintf(g_serviceId, "184%04d%02d%02d%02d%02d%02d01", g_tmTod.tm_year+1900, g_tmTod.tm_mon+1, g_tmTod.tm_mday, g_tmTod.tm_hour, g_tmTod.tm_min, g_tmTod.tm_sec); } void sendService() { service pkt; int routeList = 10; int dataLength; fprintf(stderr, "1. 긴급차량우선신호 발생에 따른 출발지-목적지 사이의 경로정보\n"); memset((char*)&pkt, 0x00, sizeof(pkt)); dataLength = sizeof(service_veh) + (routeList * sizeof(pos)); makeHead(&pkt.head, EVPS_SERVICE, g_sequence++, 1, 1, dataLength); strcpy(pkt.veh.evNo, "998나1655"); //차량 번호 pkt.veh.current.lat = htonl( 37.692329 * 1000000); //현재위치LAT, LNG pkt.veh.current.lng = htonl(126.746276 * 1000000); //현재위치LAT, LNG strcpy(pkt.veh.serviceName, "인제대학교일산백병원 응급의료센터"); //서비스명 pkt.veh.arrival.lat = htonl( 37.674431 * 1000000); //도착위치LAT, LNG pkt.veh.arrival.lng = htonl(126.750063 * 1000000); //도착위치LAT, LNG pkt.veh.vehicleLength = htonl(43); //차량길이(군집차량 길이 포함) strcpy(pkt.veh.ocrNo, "XZ4137118774"); //재난번호 strcpy(pkt.veh.ocrType, "구급"); //재난종별명 pkt.veh.arrivalTime = htonl(462); //예상도착시각 pkt.veh.distance = htonl(2838); //거리 SETWORD(pkt.veh.routeList, routeList); //경로수 for (int ii = 0; ii < routeList; ii++) { pkt.route[ii].lat = htonl(( 37.692329+ii) * 1000000); pkt.route[ii].lng = htonl((126.746276+ii) * 1000000); } _cliSend((char*)&pkt, sizeof(pkt.head)+dataLength); } void sendNode() { service_node pkt; node_info node; int idx; int dataLength; int nodeList = 2; int phaseList; int ii; int nodeSize; fprintf(stderr, "2. 경로 내의 교차로/현시구성 정보\n"); memset((char*)&pkt, 0x00, sizeof(pkt)); dataLength = 0; idx = 0; SETWORD(pkt.lcList, nodeList); memset((char*)&node, 0x00, sizeof(node)); phaseList = 5; nodeSize = (phaseList * sizeof(node_phase)) + 114; dataLength += nodeSize; node.intLcNo = htonl(2147483647); //교차로 번호 strcpy(node.intName, "향남힐링스파 사거리"); //교차로명 node.location.lat = htonl( 37.692329 * 1000000); //현재위치LAT, LNG node.location.lng = htonl(126.746276 * 1000000); //현재위치LAT, LNG SETWORD(node.phaseList, phaseList); //현시 정보 for (ii = 0; ii < phaseList; ii++) { node.phase[ii].intRing = (ii % 2) + 1; //링번호, A링(1)/B링(2) node.phase[ii].intPhaseNo = ii; //현시정보, 1-8 node.phase[ii].intPlanClass = ii; //맵 번호, 맵 번호 (0: 일반제, 1~5: 시차제, 6: 전용맵) node.phase[ii].intFlowNo = ii+1; //이동류번호, 이동류번호(1-16, 17, 18) node.phase[ii].intHead.lat = htonl(( 37.692329+ii) * 1000000); node.phase[ii].intHead.lng = htonl((126.746276+ii) * 1000000); node.phase[ii].intMiddle.lat = htonl(( 37.692329+ii) * 1000000); node.phase[ii].intMiddle.lng = htonl((126.746276+ii) * 1000000); node.phase[ii].intEnd.lat = htonl(( 37.692329+ii) * 1000000); node.phase[ii].intEnd.lng = htonl((126.746276+ii) * 1000000); SETWORD(node.phase[ii].intHeadAngle, 90); //시작점각도 SETWORD(node.phase[ii].intEndAngle, 180); //종점각도 } memcpy(&pkt.data[idx], (char*)&node, nodeSize); idx += nodeSize; memset((char*)&node, 0x00, sizeof(node)); phaseList = 3; nodeSize = (phaseList * sizeof(node_phase)) + 114; dataLength += nodeSize; node.intLcNo = htonl(2147483650); //교차로 번호 strcpy(node.intName, "향남힐링스파 AAA"); //교차로명 node.location.lat = htonl( 37.692329 * 1000000); //현재위치LAT, LNG node.location.lng = htonl(126.746276 * 1000000); //현재위치LAT, LNG SETWORD(node.phaseList, phaseList); //현시 정보 for (ii = 0; ii < phaseList; ii++) { node.phase[ii].intRing = (ii % 2) + 1; //링번호, A링(1)/B링(2) node.phase[ii].intPhaseNo = ii; //현시정보, 1-8 node.phase[ii].intPlanClass = ii; //맵 번호, 맵 번호 (0: 일반제, 1~5: 시차제, 6: 전용맵) node.phase[ii].intFlowNo = ii+1; //이동류번호, 이동류번호(1-16, 17, 18) node.phase[ii].intHead.lat = htonl(( 37.692329+ii) * 1000000); node.phase[ii].intHead.lng = htonl((126.746276+ii) * 1000000); node.phase[ii].intMiddle.lat = htonl(( 37.692329+ii) * 1000000); node.phase[ii].intMiddle.lng = htonl((126.746276+ii) * 1000000); node.phase[ii].intEnd.lat = htonl(( 37.692329+ii) * 1000000); node.phase[ii].intEnd.lng = htonl((126.746276+ii) * 1000000); SETWORD(node.phase[ii].intHeadAngle, 90); //시작점각도 SETWORD(node.phase[ii].intEndAngle, 180); //종점각도 } memcpy(&pkt.data[idx], (char*)&node, nodeSize); idx += nodeSize; makeHead(&pkt.head, EVPS_NODE, g_sequence++, 1, 1, dataLength+2); _cliSend((char*)&pkt, sizeof(pkt.head)+dataLength+2); } void sendEvent() { service_event pkt; fprintf(stderr, "3. 긴급차량의 위치와 속도 정보\n"); memset((char*)&pkt, 0x00, sizeof(pkt)); makeHead(&pkt.head, EVPS_EVENT, g_sequence++, 1, 1, sizeof(veh_event)); strcpy(pkt.event.evNo, "998나1655"); //차량 번호 pkt.event.current.lat = htonl( 37.692329 * 1000000); //현재위치LAT, LNG pkt.event.current.lng = htonl(126.746276 * 1000000); //현재위치LAT, LNG pkt.event.speed = htonl(22); //차량길이(군집차량 길이 포함) pkt.event.distance = htonl(333); //잔여 거리 _cliSend((char*)&pkt, sizeof(pkt)); } void sendSignal() { service_signal pkt; int ii; int dataLength; int signalList = 2; fprintf(stderr, "4. 긴급차량의 위치에서 진행방향의 각 교차로까지의 남은거리 및 현시현황\n"); memset((char*)&pkt, 0x00, sizeof(pkt)); dataLength = signalList * sizeof(signal_info); for (ii = 0; ii < signalList; ii++) { pkt.signal[ii].intLcNo = htonl(2147483650+ii); //교차로 번호, 국토부 표준 NODE ID pkt.signal[ii].remainDist = htonl(111110+ii); //교차로 남은거리 pkt.signal[ii].state = ii % 6; //교차로운영상태, 0: 통신이상, 1: 정상, 2: 점멸, 3: 소등, 4: 수동진행, 5: 현시유지 pkt.signal[ii].plan = ii % 6; //현재 운영중인 맵 번호, 맵 번호(0: 일반제, 1~5: 시차제, 6: 전용맵) pkt.signal[ii].ARingPhase = (ii % 8) + 1; //A링 현시번호, 현시번호(1-8) pkt.signal[ii].BRingPhase = (ii % 8) + 1; //B링 현시번호, 현시번호(1-8) pkt.signal[ii].holdPhase = (ii % 8) + 1; //유지현시번호, 현시번호(1-8) } SETWORD(pkt.signalList, signalList); makeHead(&pkt.head, EVPS_SIGNAL, g_sequence++, 1, 1, dataLength+2); _cliSend((char*)&pkt, sizeof(pkt.head)+dataLength+2); } void sendServiceEnd() { service_end pkt; memset((char*)&pkt, 0x00, sizeof(pkt)); fprintf(stderr, "5. 긴급차량 서비스 종료\n"); makeHead(&pkt.head, EVPS_SERVICE_END, g_sequence++, 1, 1, 4); pkt.reason = htonl(2); _cliSend((char*)&pkt, sizeof(pkt)); } int getSendOption() { int opt; fprintf(stderr, "****** Input Test Data Send Options\n"); fprintf(stderr, " 1. 긴급차량우선신호 발생에 따른 출발지-목적지 사이의 경로정보\n"); fprintf(stderr, " 2. 경로 내의 교차로/현시구성 정보\n"); fprintf(stderr, " 3. 긴급차량의 위치와 속도 정보\n"); fprintf(stderr, " 4. 긴급차량의 위치에서 진행방향의 각 교차로까지의 남은거리 및 현시현황\n"); fprintf(stderr, " 5. 긴급차량 서비스 종료\n"); fprintf(stderr, " 0. Exit\n"); fprintf(stderr, "Input Option: "); opt = getchar(); return opt; } int main(int AArgc, char* AArgv[]) { int opt; fprintf(stderr, "pkt_head: %ld\n", sizeof(pkt_head)); fprintf(stderr, " dword: %ld\n", sizeof(dword)); fprintf(stderr, " time_t: %ld\n", sizeof(time_t)); _getNetTime(&g_tmTod); #if 1 signal(SIGUSR1, _cliBreak); signal(SIGPIPE, _cliEpipe); signal(SIGINT, SIG_IGN); #endif _LogWrite("\n"); _LogWrite("\n"); _LogWrite("**********************************************************\n"); _LogWrite(" KoROAD EVPS Local Client Test Program !!!\n"); _LogWrite(" %s \n", BuildTime); _LogWrite(" %04d/%02d/%02d %02d:%02d:%02d \n", g_tmTod.tm_year+1900, g_tmTod.tm_mon+1, g_tmTod.tm_mday, g_tmTod.tm_hour, g_tmTod.tm_min, g_tmTod.tm_sec); _LogWrite("**********************************************************\n"); _LogWrite("\n"); /* * ȯ�漳���� ���� �б�. ./signal.cfg */ if (_read_config_file() < 0) { _LogWrite("[ERROR] config file loading failed...\n"); return 0; } if (_cliInit() == D_SERVER_DISCONNECT) { _LogWrite("[ERROR] Evps Server Connect failed...\n"); return 0; } //opt = getSendOption(); makeServiceId(); while (g_termApp != D_TERMAPP_YES) { opt = getSendOption(); _getNetTime(&g_tmTod); switch(opt) { case '1': sendService(); break; case '2': sendNode(); break; case '3': sendEvent(); break; case '4': sendSignal(); break; case '5': sendServiceEnd(); break; case '0': g_termApp = D_TERMAPP_YES; break; } } _cliNetDisconnected(); }