shjung 10 місяців тому
коміт
1b0b068e78
3 змінених файлів з 769 додано та 0 видалено
  1. 53 0
      src/Makefile
  2. 470 0
      src/evpLocal.c
  3. 246 0
      src/evpLocal.h

+ 53 - 0
src/Makefile

@@ -0,0 +1,53 @@
+CC		= gcc
+CFLAG	= -D_REENTRANT -DSCU -I. -DBSD_COMP -DLINUX
+LFLAG	= #-lsocket -lnsl
+CINC	=
+LIB		= 
+DEPENDS	= 
+MV		= mv
+RM		= rm
+CP		= cp
+ECHO	= echo
+BINDIR	= .
+
+APPHDR	= 
+APPSRC	= evpLocal.c
+APPOBJ	= evpLocal.o
+
+TARGET	= evpLocal
+
+
+#---------------------------------------------------------------------------------
+.c.o 	:
+	@echo "Compile .c.o [$(@F:.o=.c)] ..."
+	$(CC) $(CFLAG) -c $*.c
+#---------------------------------------------------------------------------------
+
+all	: LOGO $(TARGET)
+	@$(RM) -rf *.lis core $(APPOBJ)
+
+install	: inst 
+
+clean	: LOGO
+	@$(ECHO) "Clean App & Objs ..."
+	@$(RM) -rf *.lis core $(APPOBJ) $(TARGET)
+
+
+LOGO 	:
+	@$(ECHO) "***************************************************************************"
+	@$(ECHO) " KoROAD EVPS Local Client Test... Make compile $(TARGET) ..."
+	@$(ECHO) "***************************************************************************"
+	
+$(TARGET) : $(APPSRC) $(APPOBJ)
+	@$(ECHO) "Compile [ $@ ] ..." 
+	@$(ECHO) $(CFLAG) -o $(TARGET) $(APPOBJ) $(LIBINC)
+	@$(CC) $(CFLAG) -o $(TARGET) $(APPOBJ) $(LFLAG) 
+
+inst 	: LOGO
+	@$(ECHO) "Install Application ... $(TARGET)"
+	@$(ECHO) $(TARGET) "===> " $(BINDIR)/$(TARGET)
+	@$(CP) $(TARGET) $(BINDIR)/$(TARGET)
+
+
+	
+

+ 470 - 0
src/evpLocal.c

@@ -0,0 +1,470 @@
+#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();
+}

+ 246 - 0
src/evpLocal.h

@@ -0,0 +1,246 @@
+
+#ifndef __EVPLOCAL_H__
+#define __EVPLOCAL_H__
+
+/*
+***************************************************************************************************
+* include
+***************************************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/times.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/msg.h>
+#include <sys/utsname.h>
+#include <sys/ioctl.h>
+#include <time.h>
+#include <fcntl.h>
+#include <math.h>
+#include <errno.h>
+#include <termios.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <setjmp.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+/*
+***************************************************************************************************
+* 시스템에서 사용할 데이터 형식을 재정의
+***************************************************************************************************/
+typedef unsigned char  byte;
+typedef unsigned short word;
+typedef unsigned int   dword;
+
+
+/*
+*  Application defines
+***************************************************************************************************/
+#define D_SERVER_CONNECT        1
+#define D_SERVER_DISCONNECT     0
+
+#define D_TERMAPP_YES           1
+#define D_TERMAPP_NO            0
+
+#define SETWORD(b,w)            do{ \
+                                  (b)[0]=w/256; \
+                                  (b)[1]=w%256; \
+                                }while(0)
+
+#define GETWORD(b)              (b)[0]*256+(b)[1]
+
+
+typedef struct _serverinfo
+{
+    char ipaddr[20];
+    word port;
+} server_info, *server_infop;
+
+
+#define	EVPS_STX1				'U'  /* STX1 */
+#define	EVPS_STX2				'E'  /* STX1 */
+#define	EVPS_NULL				(byte)0x00
+
+#define	EVPS_SERVICE_ID_SIZE	19
+#define	EVPS_SERVICE_NAME_SIZE	100
+#define	EVPS_VEHICLE_NO_SIZE	10
+#define	EVPS_OCR_NO_SIZE		20
+#define	EVPS_OCR_TYPE_SIZE		20
+#define	EVPS_NODE_NAME_SIZE		100
+
+#define	EVPS_GEO_CORRECT		1000000.0
+
+
+#define	EVPS_SERVICE		(byte)0x14	//"긴급차량우선신호 발생에 따른 출발지-목적지 사이의 경로정보"),
+#define	EVPS_NODE			(byte)0x15	//"경로 내의 교차로/현시구성 정보"),
+#define	EVPS_EVENT			(byte)0x16	//"긴급차량의 위치와 속도 정보"),
+#define	EVPS_SIGNAL			(byte)0x17	//"긴급차량의 위치에서 진행방향의 각 교차로까지의 남은거리 및 현시현황"),
+#define	EVPS_SERVICE_END	(byte)0x18	//"긴급차량 서비스 종료"); // 사용 안함(예비)
+
+#pragma pack(push, 1)
+
+/**
+* PACKET HEAD
+********************************************************************************/
+#define MAX_DATA_SIZE		8155
+
+typedef struct _pkt_head
+{
+	byte stx1;
+    byte stx2;
+    byte opCode;
+    byte sequence[2];
+    byte current[2];
+    byte total[2];
+    byte year[2];
+    byte month;
+    byte day;
+    byte hour;
+    byte min;
+    byte sec;
+    char serviceId[EVPS_SERVICE_ID_SIZE];
+    byte dataLength[2];
+} pkt_head, *pkt_headp;
+
+typedef struct _evps_pkt
+{
+	pkt_head 	head;
+	byte        data[MAX_DATA_SIZE];
+} evps_pkt, *evps_pktp;
+
+/**
+* GEO Location Lat, Lng
+********************************************************************************/
+typedef struct _pos
+{
+	dword lat; 	//위치LAT
+	dword lng;	//위치LNG
+} pos, *posp;
+
+
+/**
+* SERVICE ROUTE
+********************************************************************************/
+#define MAX_ROUTE_POS	1000
+
+typedef struct _service_veh
+{
+	char  evNo[EVPS_VEHICLE_NO_SIZE];			//차량 번호
+	pos   current;								//현재위치LAT, LNG
+	char  serviceName[EVPS_SERVICE_NAME_SIZE];	//서비스명
+	pos   arrival;								//도착위치LAT, LNG
+	dword vehicleLength;						//차량길이(군집차량 길이 포함)
+	char  ocrNo[EVPS_OCR_NO_SIZE];				//재난번호
+	char  ocrType[EVPS_OCR_TYPE_SIZE];			//재난종별명
+	dword arrivalTime;							//예상도착시각
+	dword distance;								//거리
+	byte  routeList[2];							//경로수
+} service_veh, *service_vehp;
+
+typedef struct _service
+{
+	pkt_head 	head;
+	service_veh veh;
+	pos         route[MAX_ROUTE_POS];
+} service, *servicep;
+
+/**
+* NODE
+********************************************************************************/
+#define MAX_NODE_PHASE	20
+
+typedef struct _node_phase
+{
+	byte intRing;			//링번호, A링(1)/B링(2)
+	byte intPhaseNo;		//현시정보, 1-8
+	byte intPlanClass;		//맵 번호, 맵 번호 (0: 일반제, 1~5: 시차제, 6: 전용맵)
+	byte intFlowNo;			//이동류번호, 이동류번호(1-16, 17, 18)
+	pos  intHead;			//시작점LAT, LNG
+	pos  intMiddle;			//중심점LAT, 중심점LNG
+	pos  intEnd;			//끝점LAT, LNG
+	byte intHeadAngle[2];	//시작점각도
+	byte intEndAngle[2];	//종점각도
+} node_phase, *node_phasep;
+
+typedef struct _node_info
+{
+	dword 		intLcNo;						//교차로 번호
+	char  		intName[EVPS_NODE_NAME_SIZE];	//교차로명
+	pos   		location;						//교차로위치LAT, LNG
+	byte  		phaseList[2];					//현시 정보
+	node_phase	phase[MAX_NODE_PHASE];
+} node_info, *node_infop;
+
+typedef struct _service_node
+{
+	pkt_head 	head;
+	
+	byte		lcList[2];		//교차로 갯수
+	byte		data[10000];
+} service_node, *service_nodep;
+
+/**
+* SIGNAL
+********************************************************************************/
+#define MAX_SIGNAL		1000
+
+typedef struct _signal_info
+{
+	dword intLcNo;		//교차로 번호, 국토부 표준 NODE ID
+	dword remainDist;	//교차로 남은거리
+	byte  state;		//교차로운영상태, 0: 통신이상, 1: 정상, 2: 점멸, 3: 소등, 4: 수동진행, 5: 현시유지
+	byte  plan;			//현재 운영중인 맵 번호, 맵 번호(0: 일반제, 1~5: 시차제, 6: 전용맵)
+	byte  ARingPhase;	//A링 현시번호, 현시번호(1-8)
+	byte  BRingPhase;	//B링 현시번호, 현시번호(1-8)
+	byte  holdPhase;	//유지현시번호, 현시번호(1-8)
+} signal_info, *signal_infop;
+
+typedef struct _service_signal
+{
+	pkt_head 	head;
+	
+	byte		signalList[2];		//교차로현황 리스트 갯수
+	signal_info	signal[MAX_SIGNAL];	//교차로현황
+} service_signal, *service_signalp;
+
+/**
+* EVENT
+********************************************************************************/
+typedef struct _veh_event
+{
+	char  evNo[EVPS_VEHICLE_NO_SIZE];	//차량 번호
+	pos   current;						//현재위치LAT, LNG
+	dword speed;						//속도
+	dword distance;						//잔여 거리
+} veh_event, *veh_eventp;
+
+typedef struct _service_event
+{
+	pkt_head 	head;
+	veh_event 	event;							//잔여 거리
+} service_event, *service_eventp;
+
+/**
+* SERVICE END
+********************************************************************************/
+typedef struct _service_end
+{
+	pkt_head head;
+
+	dword    reason;
+} service_end, *service_endp;
+
+#pragma pack(pop)
+
+#endif /* __EVPLOCAL_H__ */