From 8d592a310cfe0a36a61bb6f59179f12fdf3db79a Mon Sep 17 00:00:00 2001 From: MonHun Date: Sat, 29 Jun 2024 12:06:48 +0900 Subject: [PATCH] win 0628 --- .../lib/state-spring-boot-starter-1.0.3.jar | Bin 30350 -> 0 bytes .../lib/state-spring-boot-starter-1.0.5.jar | Bin 0 -> 30718 bytes tss_integrate/pom.xml | 6 +- .../main/java/kr/gmtc/tss/Application.java | 3 +- .../java/kr/gmtc/tss/config/DbConfig.java | 37 +++ .../java/kr/gmtc/tss/config/TssConfig.java | 100 ++---- .../runnable/AiLocationParseRunnable.java | 195 ++++++++++++ .../elkdata/runnable/AiVoiceMetaRunnable.java | 102 ++++++- .../elkdata/runnable/AsdeParseRunnable.java | 186 +++++++++++ .../runnable/CctvPtzParseRunnable.java | 63 ++-- .../elkdata/runnable/FusionParseRunnable.java | 174 +++++++++++ .../elkdata/runnable/RadarParseRunnable.java | 178 +++++++++++ .../elkdata/runnable/RuteParseRunnable.java | 99 ++---- .../runnable/StandStatusParseRunnable.java | 154 ++++++++++ .../runnable/StatusAnaParseRunnable.java | 156 ++++++++++ .../java/kr/gmtc/tss/elkdata/vo/AlarmVO.java | 220 +++++++++++++ .../kr/gmtc/tss/elkdata/vo/AsdeTrackVO.java | 288 ++++++++++++++++++ .../kr/gmtc/tss/elkdata/vo/CctvTrackVO.java | 139 +++++++++ .../kr/gmtc/tss/elkdata/vo/RadarTrackVO.java | 163 ++++++++++ .../kr/gmtc/tss/elkdata/vo/StandStatusVO.java | 177 +++++++++++ .../java/kr/gmtc/tss/elkdata/vo/StatsVO.java | 17 ++ .../java/kr/gmtc/tss/elkdata/vo/TrackVO.java | 29 +- .../java/kr/gmtc/tss/elkdata/vo/VoiceVo.java | 21 ++ .../java/kr/gmtc/tss/filelog/DataLogger.java | 5 - .../gmtc/tss/filelog/MessageBodyLogger.java | 5 - .../kr/gmtc/tss/kafka/KafkaTopicReader.java | 1 + .../java/kr/gmtc/tss/main/MainServer.java | 195 ++++++++---- .../tss/util/ArrayBlockingLoggingQueue.java | 6 - .../main/java/kr/gmtc/tss/util/FileUtil.java | 80 ++--- .../java/kr/gmtc/tss/util/LogFileDelete.java | 50 +++ .../src/main/resources/application.yml | 92 +++--- .../src/main/resources/logback-spring.xml | 23 +- 32 files changed, 2577 insertions(+), 387 deletions(-) delete mode 100644 tss_integrate/lib/state-spring-boot-starter-1.0.3.jar create mode 100644 tss_integrate/lib/state-spring-boot-starter-1.0.5.jar create mode 100644 tss_integrate/src/main/java/kr/gmtc/tss/config/DbConfig.java create mode 100644 tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/AiLocationParseRunnable.java create mode 100644 tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/AsdeParseRunnable.java create mode 100644 tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/FusionParseRunnable.java create mode 100644 tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/RadarParseRunnable.java create mode 100644 tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/StandStatusParseRunnable.java create mode 100644 tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/StatusAnaParseRunnable.java create mode 100644 tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/AlarmVO.java create mode 100644 tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/AsdeTrackVO.java create mode 100644 tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/CctvTrackVO.java create mode 100644 tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/RadarTrackVO.java create mode 100644 tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/StandStatusVO.java create mode 100644 tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/StatsVO.java create mode 100644 tss_integrate/src/main/java/kr/gmtc/tss/util/LogFileDelete.java diff --git a/tss_integrate/lib/state-spring-boot-starter-1.0.3.jar b/tss_integrate/lib/state-spring-boot-starter-1.0.3.jar deleted file mode 100644 index 4f5a7df592c24affb8e69cdaefac7bbf4d8aa02f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30350 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 AdjJ3c diff --git a/tss_integrate/lib/state-spring-boot-starter-1.0.5.jar b/tss_integrate/lib/state-spring-boot-starter-1.0.5.jar new file mode 100644 index 0000000000000000000000000000000000000000..ce29499768300470dc8113a40a673535270af21c GIT binary patch literal 30718 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
  • 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 rAm^|3{Cb~y`QG#zRtss 0.0.1-SNAPSHOT TSS - TSS Integrate + EyeAPN TSS 1.8 @@ -56,7 +56,7 @@ state-spring-boot-starter 1.0.3 system - ${basedir}/lib/state-spring-boot-starter-1.0.3.jar + ${basedir}/lib/state-spring-boot-starter-1.0.5.jar ipworks.local @@ -78,7 +78,7 @@ - EyeTSS_CctvPtz + EyeAPN_Tss org.springframework.boot diff --git a/tss_integrate/src/main/java/kr/gmtc/tss/Application.java b/tss_integrate/src/main/java/kr/gmtc/tss/Application.java index c534341..8773aa1 100644 --- a/tss_integrate/src/main/java/kr/gmtc/tss/Application.java +++ b/tss_integrate/src/main/java/kr/gmtc/tss/Application.java @@ -2,10 +2,11 @@ package kr.gmtc.tss; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableScheduling; +@EnableScheduling @SpringBootApplication public class Application { - public static void main(String[] args) { SpringApplication.run(Application.class, args); } diff --git a/tss_integrate/src/main/java/kr/gmtc/tss/config/DbConfig.java b/tss_integrate/src/main/java/kr/gmtc/tss/config/DbConfig.java new file mode 100644 index 0000000..b3904c2 --- /dev/null +++ b/tss_integrate/src/main/java/kr/gmtc/tss/config/DbConfig.java @@ -0,0 +1,37 @@ +package kr.gmtc.tss.config; + +import javax.sql.DataSource; + +import org.apache.ibatis.session.SqlSessionFactory; +import org.mybatis.spring.SqlSessionFactoryBean; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@Configuration +@MapperScan(value = "kr.gmtc.eyesvtss.mapper", sqlSessionFactoryRef = "batchSqlSessionFactory" ) +@EnableTransactionManagement +public class DbConfig { + + @Bean(name = "dbDataSource") + @ConfigurationProperties(prefix = "spring.db.datasource") + public DataSource db5DataSource() { + + return DataSourceBuilder.create().build(); + } + + @Bean(name="batchSqlSessionFactory") + public SqlSessionFactory batchSqlSessionFactoryBean(@Qualifier("dbDataSource") DataSource batchDataSource, ApplicationContext applicationContext) + throws Exception { + SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); + factoryBean.setDataSource(batchDataSource); + factoryBean.setConfigLocation(applicationContext.getResource("classpath:/mybatis-config.xml")); + return factoryBean.getObject(); + } + +} diff --git a/tss_integrate/src/main/java/kr/gmtc/tss/config/TssConfig.java b/tss_integrate/src/main/java/kr/gmtc/tss/config/TssConfig.java index aa449d2..651ba5e 100644 --- a/tss_integrate/src/main/java/kr/gmtc/tss/config/TssConfig.java +++ b/tss_integrate/src/main/java/kr/gmtc/tss/config/TssConfig.java @@ -1,16 +1,12 @@ package kr.gmtc.tss.config; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Queue; import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import kr.gmtc.tss.elkdata.vo.CctvPtzVO; import kr.gmtc.tss.util.ArrayBlockingLoggingQueue; @Configuration("TssConfig") @@ -21,34 +17,22 @@ public class TssConfig { @Value("${kafka.groupId}") public String consumeGroupId; - + @Value("${file-zip-path}") - public String fileZipPath; - - @Value("${file-zip-bak-path}") - public String fileZipBakPath; - - @Value("${file-make-time}") - public int fileMakeTime; - - @Value("${data-zip-path}") public String dataZipPath; - @Value("${data-zip-bak-path}") + @Value("${file-zip-bak-path}") public String dataZipBakPath; - @Value("${data-make-time}") + @Value("${file-make-time}") public int dataMakeTime; - // @Value("${flag.database}") - // public boolean flagDataBase; - + @Value("${file-save-days}") + public int dataSaveDays; + @Value("${flag.datafile}") public boolean flagDataFile; - // @Value("${flag.file}") - // public boolean flagFile; - @Value("${client.queue-count:10000}") public int queueCount=100000; @@ -80,71 +64,33 @@ public class TssConfig { public String logclassification; - public Queue rcvQueue; - public Queue messageBodyQueue; + public Map> rcvQueueMap; public Queue dataFileQueue; - public Queue trackQueue; - - public Queue sqlLogTrackQueue; - - public Queue trackLastQueue; - - public Queue sqlLogTrackLastQueue; - - - @Bean(name = "rcvQueue") + // @Bean(name = "rcvQueueMap") public Map> getRcvQueueMap() { - Map> queList = new HashMap>(); + if(this.rcvQueueMap == null){ + + this.rcvQueueMap = new HashMap>(); - for(String swIdx : swclassification){ - Queue rcvQueue = new ArrayBlockingLoggingQueue<>(queueCount); - queList.put(swIdx, rcvQueue); + for(String swIdx : swclassification){ + Queue rcvQueue = new ArrayBlockingLoggingQueue<>(queueCount); + this.rcvQueueMap.put(swIdx, rcvQueue); + } } + + return this.rcvQueueMap; - return queList; - - } - - @Bean(name = "messageBodyQueue") - public Queue getMessageBodyQueue() { - this.messageBodyQueue = new ArrayBlockingLoggingQueue<>(queueCount); - return messageBodyQueue; } - @Bean(name = "dataFileQueue") + // @Bean(name = "dataFileQueue") public Queue getDataFileQueue() { - this.dataFileQueue = new ArrayBlockingLoggingQueue<>(queueCount); - return dataFileQueue; - } - - - @Bean(name = "trackQueue") - public Queue getTrackQueue() { - this.trackQueue = new ArrayBlockingLoggingQueue<>(queueCount); - return trackQueue; + if(this.dataFileQueue == null ){ + this.dataFileQueue = new ArrayBlockingLoggingQueue<>(queueCount); + } + + return this.dataFileQueue; } - - @Bean(name = "trackLastQueue") - public Queue getTrackLastQueue() { - this.trackQueue = new ArrayBlockingLoggingQueue<>(queueCount); - return new ArrayBlockingLoggingQueue<>(queueCount); - } - - @Bean(name = "sqlLogTrackQueue") - public Queue getSqlLogTrackQueue() { - this.trackQueue = new ArrayBlockingLoggingQueue<>(queueCount); - return new ArrayBlockingLoggingQueue<>(queueCount); - } - - @Bean(name = "sqlLogTrackLastQueue") - public Queue getSqlLogTrackLastQueue() { - this.trackQueue = new ArrayBlockingLoggingQueue<>(queueCount); - return new ArrayBlockingLoggingQueue<>(queueCount); - } - - - } diff --git a/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/AiLocationParseRunnable.java b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/AiLocationParseRunnable.java new file mode 100644 index 0000000..3e6d306 --- /dev/null +++ b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/AiLocationParseRunnable.java @@ -0,0 +1,195 @@ +package kr.gmtc.tss.elkdata.runnable; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Queue; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +import kr.gmtc.tss.elkdata.vo.CctvTrackVO; + +public class AiLocationParseRunnable implements Runnable { + + private Logger logger = LoggerFactory.getLogger(this.getClass()); + + Queue rcvQueue; + Queue dataFileQueue; + + private boolean isRunning = false; + private int listChunkSize = 100; + private long sleepMillis; + + private String classification; + private String swclassification; + private String logclassification; + + public AiLocationParseRunnable(Queue rcvQueue + , Queue dataFileQueue + , int listChunkSize + , long sleepMillis + , String classification, String swclassification, String logclassification) { + this.rcvQueue = rcvQueue; + this.dataFileQueue = dataFileQueue; + this.listChunkSize = listChunkSize; + this.sleepMillis = sleepMillis; + this.classification = classification; + this.swclassification = swclassification; + this.logclassification = logclassification; + } + + @Override + public void run() { + isRunning = true; + + while (isRunning) { + try { + + int loopCnt = 0; + if(rcvQueue.size()>listChunkSize) { + loopCnt = listChunkSize; + }else { + loopCnt = rcvQueue.size(); + } + String [] chunkArr = new String[loopCnt]; + + for (int i = 0; i < loopCnt; i++) { + chunkArr[i] = rcvQueue.poll(); + } + + for (int i = 0; i < chunkArr.length; i++) { + parseAndEnqueue(chunkArr[i]); + } + + } catch (Exception e) { + if (e.getMessage() != null) { + logger.debug("[ParseTarget] Parsing Error Message : " ,e); + } else { + logger.info("[ParserThread] Parsing Error Call Stack" ,e); + } + } + + sleep(sleepMillis); + } + } + + private void parseAndEnqueue(String result) { + try { + ArrayList histroyQueue = new ArrayList(); + ObjectMapper mapper = new ObjectMapper(); + + Map convert = mapper.readValue(result, new TypeReference>() {}); + + @SuppressWarnings("unchecked") + ArrayList> list = (ArrayList>) convert.get("data"); + // LinkedHashMap map = (LinkedHashMap) convert.get("data"); + + logger.info("수신 데이터 변환 건수[" +swclassification + "] {}", list.size()); + + DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss.SSS"); + String dateTime = dateFormat.format(new Date()); + + StringBuilder sb = new StringBuilder(); + + sb.append(dateTime); sb.append(","); + sb.append(logclassification); sb.append(","); //log구분 + sb.append(swclassification); sb.append(","); //sw구분 + sb.append(classification); sb.append("|"); //서버구분 + int i = 0; + for (LinkedHashMap map : list) { + CctvTrackVO t = mapper.convertValue(map, CctvTrackVO.class); + + if (i > 0) sb.append("^"); + + sb.append(t.getDtctTm()); sb.append(","); + sb.append(t.getDtctCls()); sb.append(","); + sb.append(t.getMtaTm()); sb.append(","); + sb.append(t.getRwTm()); sb.append(","); + // sb.append(t.getCcId()); sb.append(","); + + int j = 0; + for (String k : t.getCcId()) { + if (j > 0) sb.append("@"); + sb.append(k); + j++; + } + sb.append(","); + + sb.append(t.getZnId()); sb.append(","); + sb.append(t.getArcrftTp()); sb.append(","); + sb.append(t.getArln()); sb.append(","); + sb.append(t.getTrckId().replace(",", "-")); sb.append(","); + + + j = 0; + for (String k : t.getBbTlp()) { + if (j > 0) sb.append("@"); + sb.append(k); + j++; + } + sb.append(","); + + j = 0; + for (String k : t.getBbBrp()) { + if (j > 0) sb.append("@"); + sb.append(k); + j++; + } + sb.append(","); + + j = 0; + for (String k : t.getCrdFrm()) { + if (j > 0) sb.append("@"); + sb.append(k); + j++; + } + sb.append(","); + + j = 0; + for (String k : t.getCrdGlbl()) { + if (j > 0) sb.append("@"); + sb.append(k); + j++; + } + sb.append(","); + + sb.append(t.getDrctn()); sb.append(","); + sb.append(t.getArcrftStnd()); sb.append(","); + sb.append(t.getSpd()); + + i++; + histroyQueue.add(t); + } + + logger.info("logstash 포맷 변환 건수[" +swclassification + "] {}", histroyQueue.size()); + + dataFileQueue.add(sb.toString()); + + histroyQueue.clear(); + + } catch (Exception e) { + logger.error("[ParserThread] Parsing Error Message : " + e.getMessage()); + } + } + + + + private void sleep(long millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) { + logger.debug("[ParseTargetRunnable] sleep error : "+e.getLocalizedMessage()); + } + } + + public void setRunning(boolean isRunning) { + this.isRunning = isRunning; + } +} diff --git a/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/AiVoiceMetaRunnable.java b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/AiVoiceMetaRunnable.java index 27f3eee..4a25d72 100644 --- a/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/AiVoiceMetaRunnable.java +++ b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/AiVoiceMetaRunnable.java @@ -3,6 +3,7 @@ package kr.gmtc.tss.elkdata.runnable; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Calendar; import java.util.Date; import java.util.LinkedHashMap; import java.util.Map; @@ -14,12 +15,16 @@ import org.slf4j.LoggerFactory; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; -import kr.gmtc.tss.elkdata.vo.RuteVO; -import kr.gmtc.tss.elkdata.vo.RuteVO.MvPoints; +import kr.gmtc.tss.elkdata.vo.StatsVO; +import kr.gmtc.tss.elkdata.vo.VoiceVo; +import kr.gmtc.tss.elkdata.vo.VoiceVo.VoiceKeyword; +import kr.gmtc.tss.elkdata.vo.VoiceVo.VoiceReadback; + public class AiVoiceMetaRunnable implements Runnable { private Logger logger = LoggerFactory.getLogger(this.getClass()); + private Logger logger_sts = LoggerFactory.getLogger("STATS"); Queue rcvQueue; Queue dataFileQueue; @@ -83,13 +88,15 @@ public class AiVoiceMetaRunnable implements Runnable { private void parseAndEnqueue(String result) { try { - ArrayList histroyQueue = new ArrayList(); + ArrayList histroyQueue = new ArrayList(); ObjectMapper mapper = new ObjectMapper(); Map convert = mapper.readValue(result, new TypeReference>() {}); + + @SuppressWarnings("unchecked") ArrayList> list = (ArrayList>) convert.get("data"); - logger.info("수신 데이터 변환 건수 {}", list.size()); + logger.info("수신 데이터 변환 건수[" +swclassification + "] {}", list.size()); DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss.SSS"); String dateTime = dateFormat.format(new Date()); @@ -100,36 +107,101 @@ public class AiVoiceMetaRunnable implements Runnable { sb.append(logclassification); sb.append(","); //log구분 sb.append(swclassification); sb.append(","); //sw구분 sb.append(classification); sb.append("|"); //서버구분 + + String dateRecv = ""; + int i = 0; - int z = 0; for (LinkedHashMap map : list) { - RuteVO t = mapper.convertValue(map, RuteVO.class); + VoiceVo t = mapper.convertValue(map, VoiceVo.class); if (i > 0) sb.append("^"); - sb.append(t.getMv_id()); sb.append(","); - sb.append(t.getTrgt_id()); sb.append(","); - sb.append(t.getMv_type()); sb.append(","); - sb.append(t.getDep_arr_ty()); sb.append(","); + sb.append(t.getStarttime()); sb.append(","); + sb.append(t.getEndtime()); sb.append(","); + sb.append(t.getCom_type()); sb.append(","); + sb.append(t.getChannel()); sb.append(","); + sb.append(t.getSpeaker()); sb.append(","); + sb.append(t.getFacility()); sb.append(","); + sb.append(t.getCallsign()); sb.append(","); + sb.append(t.getDoc_type()); sb.append(","); + sb.append(t.getControl_type()); sb.append(","); + int j = 0; - for (MvPoints b : t.getMv_points()) { + for (VoiceKeyword row : t.getKeywords()) { if (j > 0) sb.append("$"); - sb.append(b.toDataFormat()); + sb.append(row.getKeywordRow()); j++; } - - logger.info("logstash 포맷 변환 건수 {}", z++); - + + sb.append(","); + + j = 0; + for (VoiceReadback row : t.getReadback()) { + if (j > 0) sb.append("$"); + sb.append(row.getReadbackRow()); + + j++; + } + + sb.append(","); + sb.append(t.getFrequency()); sb.append(","); + sb.append(t.getMedia_name()); sb.append(","); + sb.append(t.getText()); + histroyQueue.add(t); + + dateRecv = t.getEndtime(); + i++; } + // logger.info("logstash 포맷 변환 건수[" +swclassification + "] {}", histroyQueue.size()); + if(dateRecv == null || dateRecv.equals("")){ + dateRecv = dateFormat.format(new Date()); + }else{ + + // 1. 포멧 변경 + // 2. UTC -> KST + + SimpleDateFormat recvDTFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + Date cnvDate = null; + + cnvDate = recvDTFormat.parse(dateRecv); + + Calendar cal = Calendar.getInstance(); + + cal.setTime(cnvDate); + cal.add(Calendar.HOUR_OF_DAY, 9); + cnvDate = new Date(cal.getTimeInMillis()); + + dateRecv = dateFormat.format(cnvDate); + } + + StatsVO stsVO = new StatsVO(); + + stsVO.setIntrfc_dt(dateRecv); + stsVO.setIntrfc_id(swclassification); + if(swclassification.equals("6")){ + stsVO.setIntrfc_nm("VCCS"); + }else{ + stsVO.setIntrfc_nm("LTE-A"); + } + + stsVO.setRecv_co(1); + stsVO.setParse_co(histroyQueue.size()); + + String sSts = mapper.writeValueAsString(stsVO); + + // 수신 통계 로그 + logger_sts.info(sSts); + dataFileQueue.add(sb.toString()); + histroyQueue.clear(); } catch (Exception e) { logger.error("[ParserThread] Parsing Error Message : " + e.getMessage()); diff --git a/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/AsdeParseRunnable.java b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/AsdeParseRunnable.java new file mode 100644 index 0000000..579fda7 --- /dev/null +++ b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/AsdeParseRunnable.java @@ -0,0 +1,186 @@ +package kr.gmtc.tss.elkdata.runnable; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Queue; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +import kr.gmtc.tss.elkdata.vo.AsdeTrackVO; +import kr.gmtc.tss.elkdata.vo.StatsVO; + +public class AsdeParseRunnable implements Runnable { + + private Logger logger = LoggerFactory.getLogger(this.getClass()); + private Logger logger_sts = LoggerFactory.getLogger("STATS"); + + Queue rcvQueue; + Queue dataFileQueue; + + private boolean isRunning = false; + private int listChunkSize = 100; + private long sleepMillis; + + private String classification; + private String swclassification; + private String logclassification; + + public AsdeParseRunnable(Queue rcvQueue + , Queue dataFileQueue + , int listChunkSize + , long sleepMillis + , String classification, String swclassification, String logclassification) { + this.rcvQueue = rcvQueue; + this.dataFileQueue = dataFileQueue; + this.listChunkSize = listChunkSize; + this.sleepMillis = sleepMillis; + this.classification = classification; + this.swclassification = swclassification; + this.logclassification = logclassification; + } + + @Override + public void run() { + isRunning = true; + + while (isRunning) { + try { + + int loopCnt = 0; + if(rcvQueue.size()>listChunkSize) { + loopCnt = listChunkSize; + }else { + loopCnt = rcvQueue.size(); + } + String [] chunkArr = new String[loopCnt]; + + for (int i = 0; i < loopCnt; i++) { + chunkArr[i] = rcvQueue.poll(); + } + + for (int i = 0; i < chunkArr.length; i++) { + parseAndEnqueue(chunkArr[i]); + } + + } catch (Exception e) { + if (e.getMessage() != null) { + logger.debug("[ParseTarget] Parsing Error Message : " ,e); + } else { + logger.info("[ParserThread] Parsing Error Call Stack" ,e); + } + } + + sleep(sleepMillis); + } + } + + private void parseAndEnqueue(String result) { + try { + ArrayList histroyQueue = new ArrayList(); + ObjectMapper mapper = new ObjectMapper(); + + StatsVO stsVO = new StatsVO(); + + Map convert = mapper.readValue(result, new TypeReference>() {}); + //Map data = (Map) convert.get("data"); + + @SuppressWarnings("unchecked") + ArrayList> list = (ArrayList>) convert.get("data"); + + // logger.info("수신 데이터 변환 건수[" +swclassification + "] {}", list.size()); + + DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss.SSS"); + String dateTime = dateFormat.format(new Date()); + + StringBuilder sb = new StringBuilder(); + + sb.append(dateTime); sb.append(","); + sb.append(logclassification); sb.append(","); //log구분 + sb.append(swclassification); sb.append(","); //sw구분 + sb.append(classification); sb.append("|"); //서버구분 + + Date dateRecv = new Date(); + + int i = 0; + for (LinkedHashMap map : list) { + + AsdeTrackVO a = mapper.convertValue(map, AsdeTrackVO.class); + + if (i > 0) sb.append("^"); + + sb.append(a.getTrgtId()); sb.append(","); + sb.append(a.getModeScd()); sb.append(","); + sb.append(a.getSsrCd()); sb.append(","); + sb.append(a.getClsgn()); sb.append(","); + sb.append(a.getTailNo()); sb.append(","); + sb.append(a.getTrackNo()); sb.append(","); + sb.append(a.getRecptnDt()); sb.append(","); + sb.append(a.getCatTy()); sb.append(","); + sb.append(a.getLat()); sb.append(","); + sb.append(a.getLon()); sb.append(","); + sb.append(a.getSpd()); sb.append(","); + sb.append(a.getCos()); sb.append(","); + sb.append(a.getTrgtTy()); sb.append(","); + sb.append(a.getAlt()); + + histroyQueue.add(a); + dateRecv = a.getRecptnDt(); + i++; + } + + // logger.info("logstash 포맷 변환 건수[" +swclassification + "] {}", histroyQueue.size()); + + String strRecvDt = dateFormat.format(dateRecv); + + stsVO.setIntrfc_dt(strRecvDt); + stsVO.setIntrfc_id(swclassification); + stsVO.setIntrfc_nm("ASDE"); + stsVO.setRecv_co(1); + stsVO.setParse_co(histroyQueue.size()); + + String sSts = mapper.writeValueAsString(stsVO); + // 수신 통계 로그 + logger_sts.info(sSts); + + dataFileQueue.add(sb.toString()); + + + + histroyQueue.clear(); + + + + } catch (Exception e) { + e.printStackTrace(); + if (e.getMessage() != null) { + logger.debug("[ParserThread] Parsing Error Message : " + e.getMessage()); + logger.debug("",e); + } else { + logger.debug("[ParserThread] Parsing Error Packet Message :" + result); + } + } + } + + + + private void sleep(long millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) { + logger.debug("[ParseTargetRunnable] sleep error : "+e.getLocalizedMessage()); + } + } + + public void setRunning(boolean isRunning) { + this.isRunning = isRunning; + } +} diff --git a/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/CctvPtzParseRunnable.java b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/CctvPtzParseRunnable.java index 34927e1..ce6b21e 100644 --- a/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/CctvPtzParseRunnable.java +++ b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/CctvPtzParseRunnable.java @@ -19,20 +19,10 @@ import kr.gmtc.tss.elkdata.vo.CctvPtzVO; public class CctvPtzParseRunnable implements Runnable { - private boolean flagFile; - private boolean flagDataBase; - private boolean flagDataFile; - private Logger logger = LoggerFactory.getLogger(this.getClass()); Queue rcvQueue; - Queue trackQueue; - Queue trackLastQueue; Queue dataFileQueue; - Queue messageBodyQueue; - - private int rcvPos = 0; - private int rcvStatic = 0; private boolean isRunning = false; private int listChunkSize = 100; @@ -42,21 +32,15 @@ public class CctvPtzParseRunnable implements Runnable { private String swclassification; private String logclassification; - public CctvPtzParseRunnable(Queue rcvQueue, Queue trackQueue, Queue trackLastQueue - , Queue dataFileQueue,Queue messageBodyQueue - , int listChunkSize, long sleepMillis - , boolean flagFile, boolean flagDataBase, boolean flagDataFile - , String classification, String logclassification) { + public CctvPtzParseRunnable(Queue rcvQueue + , Queue dataFileQueue + , int listChunkSize + , long sleepMillis + , String classification, String swclassification, String logclassification) { this.rcvQueue = rcvQueue; - this.trackQueue = trackQueue; - this.trackLastQueue = trackLastQueue; this.dataFileQueue = dataFileQueue; - this.messageBodyQueue = messageBodyQueue; this.listChunkSize = listChunkSize; this.sleepMillis = sleepMillis; - this.flagFile = flagFile; - this.flagDataBase = flagDataBase; - this.flagDataFile = flagDataFile; this.classification = classification; this.swclassification = swclassification; this.logclassification = logclassification; @@ -103,9 +87,11 @@ public class CctvPtzParseRunnable implements Runnable { ObjectMapper mapper = new ObjectMapper(); Map convert = mapper.readValue(result, new TypeReference>() {}); + + @SuppressWarnings("unchecked") ArrayList> list = (ArrayList>) convert.get("data"); - logger.info("수신 데이터 변환 건수 {}", list.size()); + logger.info("수신 데이터 변환 건수[" +swclassification + "] {}", list.size()); DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss.SSS"); String dateTime = dateFormat.format(new Date()); @@ -116,41 +102,28 @@ public class CctvPtzParseRunnable implements Runnable { sb.append(logclassification); sb.append(","); //log구분 sb.append(swclassification); sb.append(","); //sw구분 sb.append(classification); sb.append("|"); //서버구분 + int i = 0; - int z = 0; for (LinkedHashMap map : list) { CctvPtzVO cnvVO = mapper.convertValue(map, CctvPtzVO.class); - if(flagDataFile) { - if (i > 0) sb.append("^"); + if (i > 0) sb.append("^"); - sb.append(cnvVO.getCam_id()); sb.append(","); - sb.append(cnvVO.getMove()); sb.append(","); - sb.append(cnvVO.getPan()); sb.append(","); - sb.append(cnvVO.getTilt()); sb.append(","); - sb.append(cnvVO.getZoom()); - - logger.info("logstash 포맷 변환 건수 {}", z++); - } + sb.append(cnvVO.getCam_id()); sb.append(","); + sb.append(cnvVO.getMove()); sb.append(","); + sb.append(cnvVO.getPan()); sb.append(","); + sb.append(cnvVO.getTilt()); sb.append(","); + sb.append(cnvVO.getZoom()); histroyQueue.add(cnvVO); i++; } + logger.info("logstash 포맷 변환 건수[" +swclassification + "] {}", histroyQueue.size()); - if(flagFile) { - messageBodyQueue.addAll(histroyQueue); - } + dataFileQueue.add(sb.toString()); - if(flagDataFile) { - dataFileQueue.add(sb.toString()); - } - - if(flagDataBase) { - if (histroyQueue.size() > 0) { - trackQueue.addAll(histroyQueue); - } - } + histroyQueue.clear(); } catch (Exception e) { logger.error("[ParserThread] Parsing Error Message : " + e.getMessage()); diff --git a/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/FusionParseRunnable.java b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/FusionParseRunnable.java new file mode 100644 index 0000000..bdbac95 --- /dev/null +++ b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/FusionParseRunnable.java @@ -0,0 +1,174 @@ +package kr.gmtc.tss.elkdata.runnable; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Queue; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +import kr.gmtc.tss.elkdata.vo.TrackVO; +import kr.gmtc.tss.elkdata.vo.TrackVO.BoundingBox; + +public class FusionParseRunnable implements Runnable { + + private Logger logger = LoggerFactory.getLogger(this.getClass()); + + Queue rcvQueue; + Queue dataFileQueue; + + private boolean isRunning = false; + private int listChunkSize = 100; + private long sleepMillis; + + private String classification; + private String swclassification; + private String logclassification; + + public FusionParseRunnable(Queue rcvQueue + , Queue dataFileQueue + , int listChunkSize + , long sleepMillis + , String classification, String swclassification, String logclassification) { + this.rcvQueue = rcvQueue; + this.dataFileQueue = dataFileQueue; + this.listChunkSize = listChunkSize; + this.sleepMillis = sleepMillis; + this.classification = classification; + this.swclassification = swclassification; + this.logclassification = logclassification; + } + + @Override + public void run() { + isRunning = true; + + while (isRunning) { + try { + + int loopCnt = 0; + if(rcvQueue.size()>listChunkSize) { + loopCnt = listChunkSize; + }else { + loopCnt = rcvQueue.size(); + } + String [] chunkArr = new String[loopCnt]; + + for (int i = 0; i < loopCnt; i++) { + chunkArr[i] = rcvQueue.poll(); + } + + for (int i = 0; i < chunkArr.length; i++) { + parseAndEnqueue(chunkArr[i]); + } + + } catch (Exception e) { + if (e.getMessage() != null) { + logger.debug("[ParseTarget] Parsing Error Message : " ,e); + } else { + logger.info("[ParserThread] Parsing Error Call Stack" ,e); + } + } + + sleep(sleepMillis); + } + } + + private void parseAndEnqueue(String result) { + try { + ArrayList histroyQueue = new ArrayList(); + ObjectMapper mapper = new ObjectMapper(); + + Map convert = mapper.readValue(result, new TypeReference>() {}); + + @SuppressWarnings("unchecked") + ArrayList> list = (ArrayList>) convert.get("data"); + + logger.info("수신 데이터 변환 건수[" +swclassification + "] {}", list.size()); + + DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss.SSS"); + String dateTime = dateFormat.format(new Date()); + + StringBuilder sb = new StringBuilder(); + + sb.append(dateTime); sb.append(","); + sb.append(logclassification); sb.append(","); //log구분 + sb.append(swclassification); sb.append(","); //sw구분 + sb.append(classification); sb.append("|"); //서버구분 + int i = 0; + for (LinkedHashMap map : list) { + TrackVO t = mapper.convertValue(map, TrackVO.class); + + if (i > 0) sb.append("^"); + + sb.append(t.getTargetId()); sb.append(","); + sb.append(t.getReceptionDate()); sb.append(","); + sb.append(t.getLatitude()); sb.append(","); + sb.append(t.getLongitude()); sb.append(","); + sb.append(t.getSpeed()); sb.append(","); + sb.append(t.getCourse()); sb.append(","); + sb.append(t.getTargetType()); sb.append(","); + sb.append(t.getCorrectedLatitude()); sb.append(","); + sb.append(t.getCorrectedLongitude()); sb.append(","); + sb.append(t.getModeSCode()); sb.append(","); + sb.append(t.getSsrCode()); sb.append(","); + sb.append(t.getCallsign()); sb.append(","); + sb.append(t.getTailNumber()); sb.append(","); + + int j = 0; + for (BoundingBox b : t.getBbox()) { + if (j > 0) sb.append("$"); + sb.append(b.toDataFormat()); + + j++; + } + sb.append(","); + sb.append(t.getAlt()); sb.append(","); + sb.append(t.getSchdulId()); sb.append(","); + sb.append(t.getIsCntrlzone()); + + histroyQueue.add(t); + i++; + } + + + logger.info("logstash 포맷 변환 건수[" +swclassification + "] {}", histroyQueue.size()); + + dataFileQueue.add(sb.toString()); + + histroyQueue.clear(); + + } catch (Exception e) { + logger.error("[ParserThread] Parsing Error Message : " + e.getMessage()); + +// e.printStackTrace(); +// if (e.getMessage() != null) { +// logger.debug("[ParserThread] Parsing Error Message : " + e.getMessage()); +// logger.debug("",e); +// } else { +// logger.debug("[ParserThread] Parsing Error Packet Message :" + result); +// } + } + } + + + + private void sleep(long millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) { + logger.debug("[ParseTargetRunnable] sleep error : "+e.getLocalizedMessage()); + } + } + + public void setRunning(boolean isRunning) { + this.isRunning = isRunning; + } +} diff --git a/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/RadarParseRunnable.java b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/RadarParseRunnable.java new file mode 100644 index 0000000..112e662 --- /dev/null +++ b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/RadarParseRunnable.java @@ -0,0 +1,178 @@ +package kr.gmtc.tss.elkdata.runnable; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Queue; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +import kr.gmtc.tss.elkdata.vo.RadarTrackVO; +import kr.gmtc.tss.elkdata.vo.StatsVO; + +public class RadarParseRunnable implements Runnable { + + private Logger logger = LoggerFactory.getLogger(this.getClass()); + private Logger logger_sts = LoggerFactory.getLogger("STATS"); + + Queue rcvQueue; + Queue dataFileQueue; + + private boolean isRunning = false; + private int listChunkSize = 100; + private long sleepMillis; + + private String classification; + private String swclassification; + private String logclassification; + + public RadarParseRunnable(Queue rcvQueue + , Queue dataFileQueue + , int listChunkSize + , long sleepMillis + , String classification, String swclassification, String logclassification) { + this.rcvQueue = rcvQueue; + this.dataFileQueue = dataFileQueue; + this.listChunkSize = listChunkSize; + this.sleepMillis = sleepMillis; + this.classification = classification; + this.swclassification = swclassification; + this.logclassification = logclassification; + } + + @Override + public void run() { + isRunning = true; + + while (isRunning) { + try { + + int loopCnt = 0; + if(rcvQueue.size()>listChunkSize) { + loopCnt = listChunkSize; + }else { + loopCnt = rcvQueue.size(); + } + String [] chunkArr = new String[loopCnt]; + + for (int i = 0; i < loopCnt; i++) { + chunkArr[i] = rcvQueue.poll(); + } + + for (int i = 0; i < chunkArr.length; i++) { + parseAndEnqueue(chunkArr[i]); + } + + } catch (Exception e) { + if (e.getMessage() != null) { + logger.debug("[ParseTarget] Parsing Error Message : " ,e); + } else { + logger.info("[ParserThread] Parsing Error Call Stack" ,e); + } + } + + sleep(sleepMillis); + } + } + + private void parseAndEnqueue(String result) { + try { + ArrayList histroyQueue = new ArrayList(); + ObjectMapper mapper = new ObjectMapper(); + + StatsVO stsVO = new StatsVO(); + + Map convert = mapper.readValue(result, new TypeReference>() {}); + + @SuppressWarnings("unchecked") + ArrayList> list = (ArrayList>) convert.get("data"); + + // logger.info("수신 데이터 변환 건수[" +swclassification + "] {}", list.size()); + + DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss.SSS"); + String dateTime = dateFormat.format(new Date()); + + StringBuilder sb = new StringBuilder(); + + sb.append(dateTime); sb.append(","); + sb.append(logclassification); sb.append(","); //log구분 + sb.append(swclassification); sb.append(","); //sw구분 + sb.append(classification); sb.append("|"); //서버구분 + + String dateRecv = ""; + + int i = 0; + for (LinkedHashMap map : list) { + RadarTrackVO r = mapper.convertValue(map, RadarTrackVO.class); + + if (i > 0) sb.append("^"); + + sb.append(r.getTrgtId()); sb.append(","); + sb.append(r.getRecptnDt()); sb.append(","); + sb.append(r.getLat()); sb.append(","); + sb.append(r.getLon()); sb.append(","); + sb.append(r.getSpd()); sb.append(","); + sb.append(r.getCos()); sb.append(","); + sb.append(r.getDetctCnt()); sb.append(","); + sb.append(r.getUndetctCnt()); + + histroyQueue.add(r); + dateRecv = r.getRecptnDt(); + i++; + } + + // logger.info("logstash 포맷 변환 건수[" +swclassification + "] {}", histroyQueue.size()); + + // String strRecvDt = dateFormat.format(dateRecv); + + if(dateRecv == null || dateRecv.equals("")){ + dateRecv = dateFormat.format(new Date()); + } + + stsVO.setIntrfc_dt(dateRecv); + stsVO.setIntrfc_id(swclassification); + stsVO.setIntrfc_nm("RADAR"); + stsVO.setRecv_co(1); + stsVO.setParse_co(histroyQueue.size()); + + String sSts = mapper.writeValueAsString(stsVO); + + // 수신 통계 로그 + logger_sts.info(sSts); + + dataFileQueue.add(sb.toString()); + + histroyQueue.clear(); + + } catch (Exception e) { + if (e.getMessage() != null) { + logger.debug("[ParserThread] Parsing Error Message : " + e.getMessage()); + logger.debug("",e); + } else { + logger.debug("[ParserThread] Parsing Error Packet Message :" + result); + } + e.printStackTrace(); + } + } + + + + private void sleep(long millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) { + logger.debug("[ParseTargetRunnable] sleep error : "+e.getLocalizedMessage()); + } + } + + public void setRunning(boolean isRunning) { + this.isRunning = isRunning; + } +} diff --git a/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/RuteParseRunnable.java b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/RuteParseRunnable.java index d3b8591..91c025a 100644 --- a/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/RuteParseRunnable.java +++ b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/RuteParseRunnable.java @@ -19,17 +19,10 @@ import kr.gmtc.tss.elkdata.vo.RuteVO.MvPoints; public class RuteParseRunnable implements Runnable { - private boolean flagFile; - private boolean flagDataBase; - private boolean flagDataFile; - private Logger logger = LoggerFactory.getLogger(this.getClass()); Queue rcvQueue; - Queue trackQueue; - Queue trackLastQueue; Queue dataFileQueue; - Queue messageBodyQueue; private int listChunkSize = 100; private long sleepMillis; @@ -38,20 +31,15 @@ public class RuteParseRunnable implements Runnable { private String swclassification; private String logclassification; - public RuteParseRunnable(Queue rcvQueue, Queue trackQueue, Queue trackLastQueue - , Queue dataFileQueue,Queue messageBodyQueue, int listChunkSize - , long sleepMillis, boolean flagFile, boolean flagDataBase, boolean flagDataFile - , String classification, String swclassification, String logclassification) { + public RuteParseRunnable(Queue rcvQueue + , Queue dataFileQueue + , int listChunkSize + , long sleepMillis + , String classification, String swclassification, String logclassification) { this.rcvQueue = rcvQueue; - this.trackQueue = trackQueue; - this.trackLastQueue = trackLastQueue; this.dataFileQueue = dataFileQueue; - this.messageBodyQueue = messageBodyQueue; this.listChunkSize = listChunkSize; this.sleepMillis = sleepMillis; - this.flagFile = flagFile; - this.flagDataBase = flagDataBase; - this.flagDataFile = flagDataFile; this.classification = classification; this.swclassification = swclassification; this.logclassification = logclassification; @@ -97,9 +85,11 @@ public class RuteParseRunnable implements Runnable { ObjectMapper mapper = new ObjectMapper(); Map convert = mapper.readValue(result, new TypeReference>() {}); + + @SuppressWarnings("unchecked") ArrayList> list = (ArrayList>) convert.get("data"); - logger.info("수신 데이터 변환 건수 {}", list.size()); + logger.info("수신 데이터 변환 건수[" +swclassification + "] {}", list.size()); DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss.SSS"); String dateTime = dateFormat.format(new Date()); @@ -111,78 +101,39 @@ public class RuteParseRunnable implements Runnable { sb.append(swclassification); sb.append(","); //sw구분 sb.append(classification); sb.append("|"); //서버구분 int i = 0; - int z = 0; + for (LinkedHashMap map : list) { RuteVO t = mapper.convertValue(map, RuteVO.class); - if(flagDataFile) { - if (i > 0) sb.append("^"); + if (i > 0) sb.append("^"); - sb.append(t.getMv_id()); sb.append(","); - sb.append(t.getTrgt_id()); sb.append(","); - sb.append(t.getMv_type()); sb.append(","); - sb.append(t.getDep_arr_ty()); sb.append(","); + sb.append(t.getMv_id()); sb.append(","); + sb.append(t.getTrgt_id()); sb.append(","); + sb.append(t.getMv_type()); sb.append(","); + sb.append(t.getDep_arr_ty()); sb.append(","); + + int j = 0; + for (MvPoints b : t.getMv_points()) { + if (j > 0) sb.append("$"); + sb.append(b.toDataFormat()); - int j = 0; - for (MvPoints b : t.getMv_points()) { - if (j > 0) sb.append("$"); - sb.append(b.toDataFormat()); - - j++; - } - - logger.info("logstash 포맷 변환 건수 {}", z++); + j++; } histroyQueue.add(t); i++; } + + logger.info("logstash 포맷 변환 건수[" +swclassification + "] {}", histroyQueue.size()); + dataFileQueue.add(sb.toString()); - // if(flagFile) { - // messageBodyQueue.addAll(histroyQueue); - // } - - if(flagDataFile) { - dataFileQueue.add(sb.toString()); - } - - // if(flagDataBase) { - // if (histroyQueue.size() > 0) { - // trackQueue.addAll(histroyQueue); - // } - -// if (flagDataBase) { -// histroyQueue -// .stream() -// .collect(Collectors.groupingBy(RuteVO::getTargetId, -// Collectors.maxBy(Comparator.comparing(RuteVO::getReceptionDate)) -// )).forEach((key, value) -> { -// trackLastQueue.add(value.get()); -// });; -// } - // } + histroyQueue.clear(); } catch (Exception e) { - logger.error("[ParserThread] Parsing Error Message : " + e.getMessage()); - -// e.printStackTrace(); -// if (e.getMessage() != null) { -// logger.debug("[ParserThread] Parsing Error Message : " + e.getMessage()); -// logger.debug("",e); -// } else { -// logger.debug("[ParserThread] Parsing Error Packet Message :" + result); -// } + logger.error("[ParserThread] Parsing Error Message : " + e.getMessage()); } } - - - // public synchronized CountStatus getCountAndSetZero() { - // CountStatus countStatus = new CountStatus(rcvPos,rcvStatic); - // rcvPos = 0; - // rcvStatic = 0; - // return countStatus; - // } private void sleep(long millis) { try { diff --git a/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/StandStatusParseRunnable.java b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/StandStatusParseRunnable.java new file mode 100644 index 0000000..fb0d9b9 --- /dev/null +++ b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/StandStatusParseRunnable.java @@ -0,0 +1,154 @@ +package kr.gmtc.tss.elkdata.runnable; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Queue; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +import kr.gmtc.tss.elkdata.vo.StandStatusVO; + +public class StandStatusParseRunnable implements Runnable { + + private Logger logger = LoggerFactory.getLogger(this.getClass()); + + Queue rcvQueue; + Queue dataFileQueue; + + private boolean isRunning = false; + private int listChunkSize = 100; + private long sleepMillis; + + private String classification; + private String swclassification; + private String logclassification; + + public StandStatusParseRunnable(Queue rcvQueue + , Queue dataFileQueue + , int listChunkSize + , long sleepMillis + , String classification, String swclassification, String logclassification) { + this.rcvQueue = rcvQueue; + this.dataFileQueue = dataFileQueue; + this.listChunkSize = listChunkSize; + this.sleepMillis = sleepMillis; + this.classification = classification; + this.swclassification = swclassification; + this.logclassification = logclassification; + } + + @Override + public void run() { + isRunning = true; + + while (isRunning) { + try { + + int loopCnt = 0; + if(rcvQueue.size()>listChunkSize) { + loopCnt = listChunkSize; + }else { + loopCnt = rcvQueue.size(); + } + String [] chunkArr = new String[loopCnt]; + + for (int i = 0; i < loopCnt; i++) { + chunkArr[i] = rcvQueue.poll(); + } + + for (int i = 0; i < chunkArr.length; i++) { + parseAndEnqueue(chunkArr[i]); + } + + } catch (Exception e) { + if (e.getMessage() != null) { + logger.debug("[ParseTarget] Parsing Error Message : " ,e); + } else { + logger.info("[ParserThread] Parsing Error Call Stack" ,e); + } + } + + sleep(sleepMillis); + } + } + + private void parseAndEnqueue(String result) { + + try { + + ArrayList histroyQueue = new ArrayList(); + ObjectMapper mapper = new ObjectMapper(); + + Map convert = mapper.readValue(result, new TypeReference>() {}); + + @SuppressWarnings("unchecked") + ArrayList> list = (ArrayList>) convert.get("data"); + + logger.info("수신 데이터 변환 건수[" +swclassification + "] {}", list.size()); + + DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss.SSS"); + String dateTime = dateFormat.format(new Date()); + + StringBuilder sb = new StringBuilder(); + + sb.append(dateTime); sb.append(","); + sb.append(logclassification); sb.append(","); //log구분 + sb.append(swclassification); sb.append(","); //sw구분 + sb.append(classification); sb.append("|"); //서버구분 + int i = 0; + + for (LinkedHashMap map : list) { + StandStatusVO s = mapper.convertValue(map, StandStatusVO.class); + + + if (i > 0) sb.append("^"); + + sb.append(s.getStandNo()); sb.append(","); + sb.append(s.getStandSttusTy().toDataFormat()); sb.append(","); + sb.append(s.getAircraftSttusTy()); sb.append(","); + sb.append(s.getClsgn()); + + histroyQueue.add(s); + i++; + } + + logger.info("logstash 포맷 변환 건수[" +swclassification + "] {}", histroyQueue.size()); + + dataFileQueue.add(sb.toString()); + + histroyQueue.clear(); + + } catch (Exception e) { + e.printStackTrace(); + if (e.getMessage() != null) { + logger.debug("[ParserThread] Parsing Error Message : " + e.getMessage()); + logger.debug("",e); + } else { + logger.debug("[ParserThread] Parsing Error Packet Message :" + result); + } + } + + } + + + + private void sleep(long millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) { + logger.debug("[ParseTargetRunnable] sleep error : "+e.getLocalizedMessage()); + } + } + + public void setRunning(boolean isRunning) { + this.isRunning = isRunning; + } +} diff --git a/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/StatusAnaParseRunnable.java b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/StatusAnaParseRunnable.java new file mode 100644 index 0000000..76147d9 --- /dev/null +++ b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/runnable/StatusAnaParseRunnable.java @@ -0,0 +1,156 @@ +package kr.gmtc.tss.elkdata.runnable; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Queue; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +import kr.gmtc.tss.elkdata.vo.AlarmVO; + +public class StatusAnaParseRunnable implements Runnable { + + private Logger logger = LoggerFactory.getLogger(this.getClass()); + + Queue rcvQueue; + Queue dataFileQueue; + + private boolean isRunning = false; + private int listChunkSize = 100; + private long sleepMillis; + + private String classification; + private String swclassification; + private String logclassification; + + public StatusAnaParseRunnable(Queue rcvQueue + , Queue dataFileQueue + , int listChunkSize + , long sleepMillis + , String classification, String swclassification, String logclassification) { + this.rcvQueue = rcvQueue; + this.dataFileQueue = dataFileQueue; + this.listChunkSize = listChunkSize; + this.sleepMillis = sleepMillis; + this.classification = classification; + this.swclassification = swclassification; + this.logclassification = logclassification; + } + + @Override + public void run() { + isRunning = true; + + while (isRunning) { + try { + + int loopCnt = 0; + if(rcvQueue.size()>listChunkSize) { + loopCnt = listChunkSize; + }else { + loopCnt = rcvQueue.size(); + } + String [] chunkArr = new String[loopCnt]; + + for (int i = 0; i < loopCnt; i++) { + chunkArr[i] = rcvQueue.poll(); + } + + for (int i = 0; i < chunkArr.length; i++) { + parseAndEnqueue(chunkArr[i]); + } + + } catch (Exception e) { + if (e.getMessage() != null) { + logger.debug("[ParseTarget] Parsing Error Message : " ,e); + } else { + logger.info("[ParserThread] Parsing Error Call Stack" ,e); + } + } + + sleep(sleepMillis); + } + } + + private void parseAndEnqueue(String result) { + try { + ArrayList histroyQueue = new ArrayList(); + ObjectMapper mapper = new ObjectMapper(); + + Map convert = mapper.readValue(result, new TypeReference>() {}); + + @SuppressWarnings("unchecked") + ArrayList> list = (ArrayList>) convert.get("data"); + + logger.info("수신 데이터 변환 건수[" +swclassification + "] {}", list.size()); + + DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss.SSS"); + String dateTime = dateFormat.format(new Date()); + + StringBuilder sb = new StringBuilder(); + + sb.append(dateTime); sb.append(","); + sb.append(logclassification); sb.append(","); //log구분 + sb.append(swclassification); sb.append(","); //sw구분 + sb.append(classification); sb.append("|"); //서버구분 + + int i = 0; + for (LinkedHashMap map : list) { + AlarmVO a = mapper.convertValue(map, AlarmVO.class); + + + if (i > 0) sb.append("^"); + + sb.append(a.getAnalsId()); sb.append(","); + sb.append(a.getAnalsDt()); sb.append(","); + sb.append(a.getAnalsTy()); sb.append(","); + sb.append(a.getArea().toDataFormat()); sb.append(","); + sb.append(a.getTarget1().toDataFormat()); sb.append(","); + sb.append(a.getTarget2().toDataFormat()); sb.append(","); + sb.append(a.getAnalsMsg()); sb.append(","); + sb.append(a.getRls_ty()); + + histroyQueue.add(a); + i++; + } + + logger.info("logstash 포맷 변환 건수[" +swclassification + "] {}", histroyQueue.size()); + + dataFileQueue.add(sb.toString()); + + histroyQueue.clear(); + + } catch (Exception e) { + e.printStackTrace(); + if (e.getMessage() != null) { + logger.debug("[ParserThread] Parsing Error Message : " + e.getMessage()); + logger.debug("",e); + } else { + logger.debug("[ParserThread] Parsing Error Packet Message :" + result); + } + } + + } + + + + private void sleep(long millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) { + logger.debug("[ParseTargetRunnable] sleep error : "+e.getLocalizedMessage()); + } + } + + public void setRunning(boolean isRunning) { + this.isRunning = isRunning; + } +} diff --git a/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/AlarmVO.java b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/AlarmVO.java new file mode 100644 index 0000000..0fbea64 --- /dev/null +++ b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/AlarmVO.java @@ -0,0 +1,220 @@ +package kr.gmtc.tss.elkdata.vo; + +import java.time.LocalDateTime; +import java.time.ZoneOffset; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class AlarmVO implements Comparable { + + private boolean inserted=false; + private String marineAreaId=""; + + public long timeStamp = LocalDateTime.now().toInstant(ZoneOffset.ofHours(9)).toEpochMilli(); + + public AlarmVO() { + } + + protected LocalDateTime dateTime; + + @JsonProperty("anals_id") + private String analsId; + @JsonProperty("anals_dt") + private String analsDt; + @JsonProperty("anals_ty") + private String analsTy; + private Area area; + private Target target1; + private Target target2; + @JsonProperty("anals_msg") + private String analsMsg; + + private String rls_ty; + + + @Override + public String toString() { + return "{" + + "\"anals_id\":\"" + analsId + "\"" + + ",\"anals_dt\":\"" + analsDt + "\"" + + ",\"anals_ty\":\"" + analsTy + "\"" + + ",\"area\":{" + area.toString() + "}" + + ",\"target1\":" + target1.toString() + + ",\"target2\":" + target2.toString() + + ",\"anals_msg\":\"" + analsMsg + "\"" + + "}"; + } + + public String getAnalsId() { + return analsId; + } + + public void setAnalsId(String analsId) { + this.analsId = analsId; + } + + public String getAnalsDt() { + return analsDt; + } + + public void setAnalsDt(String analsDt) { + this.analsDt = analsDt; + } + + public String getAnalsTy() { + return analsTy; + } + + public void setAnalsTy(String analsTy) { + this.analsTy = analsTy; + } + + public Area getArea() { + return area; + } + + public void setArea(Area area) { + this.area = area; + } + + public Target getTarget1() { + return target1; + } + + public void setTarget1(Target target1) { + this.target1 = target1; + } + + public Target getTarget2() { + return target2; + } + + public void setTarget2(Target target2) { + this.target2 = target2; + } + + public String getAnalsMsg() { + return analsMsg; + } + + public void setAnalsMsg(String analsMsg) { + this.analsMsg = analsMsg; + } + + public boolean isInserted() { + return inserted; + } + + public void setInserted(boolean inserted) { + this.inserted = inserted; + } + + public String getMarineAreaId() { + return marineAreaId; + } + + public void setMarineAreaId(String marineAreaId) { + this.marineAreaId = marineAreaId; + } + + public long getTimeStamp() { + return timeStamp; + } + + public void setTimeStamp(long timeStamp) { + this.timeStamp = timeStamp; + } + + public LocalDateTime getDateTime() { + return dateTime; + } + + public void setDateTime(LocalDateTime dateTime) { + this.dateTime = dateTime; + } + + public String getRls_ty() { + return rls_ty; + } + + public void setRls_ty(String rls_ty) { + this.rls_ty = rls_ty; + } + + + public static class Area { + private String area_type; + private String area_id; + + public String getArea_type() { + return area_type; + } + public void setArea_type(String area_type) { + this.area_type = area_type; + } + public String getArea_id() { + return area_id; + } + public void setArea_id(String area_id) { + this.area_id = area_id; + } + + @Override + public String toString() { + return "{" + + "\"area_type\":\"" + area_type + "\"" + + ",\"area_id\":\"" + area_id + "\"" + + "}"; + } + + public String toDataFormat() { + return area_type+"@"+area_id; + } + } + + public static class Target { + private String trgt_ty; + private String trgt_id; + + public String getTrgt_ty() { + return trgt_ty; + } + public void setTrgt_ty(String trgt_ty) { + this.trgt_ty = trgt_ty; + } + public String getTrgt_id() { + return trgt_id; + } + public void setTrgt_id(String trgt_id) { + this.trgt_id = trgt_id; + } + + @Override + public String toString() { + return "{" + + "\"trgt_ty\":\"" + trgt_ty + "\"" + + ",\"trgt_id\":\"" + trgt_id + "\"" + + "}"; + } + + public String toDataFormat() { + return trgt_ty+"@"+trgt_id; + } + } + + @Override + public boolean equals(Object obj) { + //p1.equals(p2) + if(obj instanceof AlarmVO) { + AlarmVO p = (AlarmVO)obj; + return this.hashCode()==p.hashCode(); + + } + return false; + } + + @Override + public int compareTo(AlarmVO o) { + return 0; + } +} diff --git a/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/AsdeTrackVO.java b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/AsdeTrackVO.java new file mode 100644 index 0000000..842b303 --- /dev/null +++ b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/AsdeTrackVO.java @@ -0,0 +1,288 @@ +package kr.gmtc.tss.elkdata.vo; + +import java.sql.Date; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @author choi + * + */ +public class AsdeTrackVO implements Comparable { + + private boolean inserted=false; + //private String marineAreaId=""; + + //public long timeStamp = LocalDateTime.now().toInstant(ZoneOffset.ofHours(9)).toEpochMilli(); + + public AsdeTrackVO() { + } + + //protected LocalDateTime dateTime; + @JsonProperty("trgt_id") + private String trgtId; // 타겟 ID + @JsonProperty("mode_s_cd") + private String modeScd; // Mode-S 코드 + @JsonProperty("ssr_cd") + private String ssrCd; // + private String clsgn; // + @JsonProperty("tail_no") + private String tailNo; // + @JsonProperty("track_no") + private int trackNo; // 추가 2023.04.07 + @JsonProperty("recptn_dt") @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul") + private Date recptnDt; // + @JsonProperty("cat_ty") + private double catTy; // + private double lat; // + private double lon; // + private double spd; // + private double cos; // + @JsonProperty("trgt_ty") + private String trgtTy; // + + +// private String acRegNo; + private String alt; +// private String virtlTrgtAt; +// private String trackCrrctAt; +// private String trackCnfdnc; + private String registerId; + private String registDt; + private String updusrId; + private String updtDt; + private boolean lstFlag; + + public boolean isInserted() { + return inserted; + } + + public void setInserted(boolean inserted) { + this.inserted = inserted; + } + +// public String getMarineAreaId() { +// return marineAreaId; +// } +// +// public void setMarineAreaId(String marineAreaId) { +// this.marineAreaId = marineAreaId; +// } +// +// public long getTimeStamp() { +// return timeStamp; +// } +// +// public void setTimeStamp(long timeStamp) { +// this.timeStamp = timeStamp; +// } + + public String getTrgtId() { + return trgtId; + } + + public void setTrgtId(String trgtId) { + this.trgtId = trgtId; + } + +// public String getAcRegNo() { +// return acRegNo; +// } +// +// public void setAcRegNo(String acRegNo) { +// this.acRegNo = acRegNo; +// } + + public String getClsgn() { + return clsgn; + } + + public void setClsgn(String clsgn) { + this.clsgn = clsgn; + } + + public String getSsrCd() { + return ssrCd; + } + + public void setSsrCd(String ssrCd) { + this.ssrCd = ssrCd; + } + + public String getModeScd() { + return modeScd; + } + + public void setModeScd(String modeScd) { + this.modeScd = modeScd; + } + + public Date getRecptnDt() { + return recptnDt; + } + + public void setRecptnDt(Date recptnDt) { + this.recptnDt = recptnDt; + } + + public double getCatTy() { + return catTy; + } + + public void setCatTy(double catTy) { + this.catTy = catTy; + } + + public double getLat() { + return lat; + } + + public void setLat(double lat) { + this.lat = lat; + } + + public double getLon() { + return lon; + } + + public void setLon(double lon) { + this.lon = lon; + } + + public double getSpd() { + return spd; + } + + public void setSpd(double spd) { + this.spd = spd; + } + + public double getCos() { + return cos; + } + + public void setCos(double cos) { + this.cos = cos; + } + +// public String getVirtlTrgtAt() { +// return virtlTrgtAt; +// } +// +// public void setVirtlTrgtAt(String virtlTrgtAt) { +// this.virtlTrgtAt = virtlTrgtAt; +// } +// +// public String getTrackCrrctAt() { +// return trackCrrctAt; +// } +// +// public void setTrackCrrctAt(String trackCrrctAt) { +// this.trackCrrctAt = trackCrrctAt; +// } +// +// public String getTrackCnfdnc() { +// return trackCnfdnc; +// } +// +// public void setTrackCnfdnc(String trackCnfdnc) { +// this.trackCnfdnc = trackCnfdnc; +// } + + public String getAlt() { + return alt; + } + + public void setAlt(String alt) { + this.alt = alt; + } + + public String getRegisterId() { + return registerId; + } + + public void setRegisterId(String registerId) { + this.registerId = registerId; + } + + public String getRegistDt() { + return registDt; + } + + public void setRegistDt(String registDt) { + this.registDt = registDt; + } + + public String getUpdusrId() { + return updusrId; + } + + public void setUpdusrId(String updusrId) { + this.updusrId = updusrId; + } + + public String getUpdtDt() { + return updtDt; + } + + public void setUpdtDt(String updtDt) { + this.updtDt = updtDt; + } + +// public LocalDateTime getDateTime() { +// return dateTime; +// } +// +// public void setDateTime(LocalDateTime dateTime) { +// this.dateTime = dateTime; +// } + + public boolean isLstFlag() { + return lstFlag; + } + + public void setLstFlag(boolean lstFlag) { + this.lstFlag = lstFlag; + } + + public String getTailNo() { + return tailNo; + } + + public void setTailNo(String tailNo) { + this.tailNo = tailNo; + } + + public int getTrackNo() { + return trackNo; + } + + public void setTrackNo(int trackNo) { + this.trackNo = trackNo; + } + + public String getTrgtTy() { + return trgtTy; + } + + public void setTrgtTy(String trgtTy) { + this.trgtTy = trgtTy; + } + + @Override + public boolean equals(Object obj) { + //p1.equals(p2) + if(obj instanceof AsdeTrackVO) { + AsdeTrackVO p = (AsdeTrackVO)obj; + return this.hashCode()==p.hashCode(); + + } + return false; + } + + @Override + public int compareTo(AsdeTrackVO o) { + return 0; + } +} diff --git a/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/CctvTrackVO.java b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/CctvTrackVO.java new file mode 100644 index 0000000..e6532b3 --- /dev/null +++ b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/CctvTrackVO.java @@ -0,0 +1,139 @@ +package kr.gmtc.tss.elkdata.vo; + +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class CctvTrackVO implements Comparable { + + private boolean inserted=false; + + public long timeStamp = LocalDateTime.now().toInstant(ZoneOffset.ofHours(9)).toEpochMilli(); + + public CctvTrackVO() { + } + + protected LocalDateTime dateTime; + + @JsonProperty("dtct_tm") + private String dtctTm; + + @JsonProperty("dtct_cls") + private String dtctCls; + + @JsonProperty("mta_tm") + private String mtaTm; + + @JsonProperty("rw_tm") + private String rwTm; + + @JsonProperty("cc_id") + private List ccId; + + @JsonProperty("zn_id") + private String znId; + + @JsonProperty("arcrft_tp") + private String arcrftTp; + + @JsonProperty("arln") + private String arln; + + @JsonProperty("trck_id") + private String trckId; + + @JsonProperty("bb_tlp") + private List bbTlp; + + @JsonProperty("bb_brp") + private List bbBrp; + + @JsonProperty("crd_frm") + private List crdFrm; + + @JsonProperty("crd_glbl") + private List crdGlbl; + + @JsonProperty("drctn") + private String drctn; + + @JsonProperty("arcrft_stnd") + private String arcrftStnd; + + @JsonProperty("spd") + private String spd; + + @JsonProperty("prc_tm") + private String prcTm; + + + @Override + public String toString() { + return "TrackVO [inserted=" + inserted + ", timeStamp=" + timeStamp + ", dateTime=" + dateTime + ", dtctTm=" + + dtctTm + ", dtctCls=" + dtctCls + ", mtaTm=" + mtaTm + ", rwTm=" + rwTm + ", ccId=" + ccId + ", znId=" + + znId + ", arcrftTp=" + arcrftTp + ", arln=" + arln + ", trckId=" + trckId + ", bbTlp=" + bbTlp + + ", bbBrp=" + bbBrp + ", crdFrm=" + crdFrm + ", crdGlbl=" + crdGlbl + ", drctn=" + drctn + + ", arcrftStnd=" + arcrftStnd + ", spd=" + spd + ", prc_tm=" + prcTm +"]"; + } + + public String toDataFormat(List arr) { + int j = 0; + String s = ""; + for (String k : arr) { + if (j > 0) s += "$"; + s += k; + j++; + } + + return s; + } + + + public boolean isInserted() { + return inserted; + } + + + + public void setInserted(boolean inserted) { + this.inserted = inserted; + } + + + + public long getTimeStamp() { + return timeStamp; + } + + + + public void setTimeStamp(long timeStamp) { + this.timeStamp = timeStamp; + } + + + @Override + public boolean equals(Object obj) { + //p1.equals(p2) + if(obj instanceof CctvTrackVO) { + CctvTrackVO p = (CctvTrackVO)obj; + return this.hashCode()==p.hashCode(); + + } + return false; + } + + @Override + public int compareTo(CctvTrackVO o) { + return 0; + } + + +} diff --git a/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/RadarTrackVO.java b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/RadarTrackVO.java new file mode 100644 index 0000000..bf3253a --- /dev/null +++ b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/RadarTrackVO.java @@ -0,0 +1,163 @@ +package kr.gmtc.tss.elkdata.vo; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class RadarTrackVO implements Comparable { + + private boolean inserted=false; + + public RadarTrackVO() { + } + + @JsonProperty("trgt_id") + private String trgtId; + @JsonProperty("recptn_dt") + private String recptnDt; + private double lat; + private double lon; + private double spd; + private double cos; + @JsonProperty("detct_cnt") + private int detctCnt; + @JsonProperty("undetct_cnt") + private int undetctCnt; + + + private String registerId; + private String registDt; + private String updusrId; + private String updtDt; + private boolean lstFlag; + + public boolean isInserted() { + return inserted; + } + + public void setInserted(boolean inserted) { + this.inserted = inserted; + } + + + + public String getTrgtId() { + return trgtId; + } + + public void setTrgtId(String trgtId) { + this.trgtId = trgtId; + } + + public String getRecptnDt() { + return recptnDt; + } + + public void setRecptnDt(String recptnDt) { + this.recptnDt = recptnDt; + } + + public double getLat() { + return lat; + } + + public void setLat(double lat) { + this.lat = lat; + } + + public double getLon() { + return lon; + } + + public void setLon(double lon) { + this.lon = lon; + } + + public double getSpd() { + return spd; + } + + public void setSpd(double spd) { + this.spd = spd; + } + + public double getCos() { + return cos; + } + + public void setCos(double cos) { + this.cos = cos; + } + + public String getRegisterId() { + return registerId; + } + + public void setRegisterId(String registerId) { + this.registerId = registerId; + } + + public String getRegistDt() { + return registDt; + } + + public void setRegistDt(String registDt) { + this.registDt = registDt; + } + + public String getUpdusrId() { + return updusrId; + } + + public void setUpdusrId(String updusrId) { + this.updusrId = updusrId; + } + + public String getUpdtDt() { + return updtDt; + } + + public void setUpdtDt(String updtDt) { + this.updtDt = updtDt; + } + + + + public boolean isLstFlag() { + return lstFlag; + } + + public void setLstFlag(boolean lstFlag) { + this.lstFlag = lstFlag; + } + + public int getDetctCnt() { + return detctCnt; + } + + public void setDetctCnt(int detctCnt) { + this.detctCnt = detctCnt; + } + + public int getUndetctCnt() { + return undetctCnt; + } + + public void setUndetctCnt(int undetctCnt) { + this.undetctCnt = undetctCnt; + } + + @Override + public boolean equals(Object obj) { + //p1.equals(p2) + if(obj instanceof RadarTrackVO) { + RadarTrackVO p = (RadarTrackVO)obj; + return this.hashCode()==p.hashCode(); + + } + return false; + } + + @Override + public int compareTo(RadarTrackVO o) { + return 0; + } +} diff --git a/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/StandStatusVO.java b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/StandStatusVO.java new file mode 100644 index 0000000..935d5c6 --- /dev/null +++ b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/StandStatusVO.java @@ -0,0 +1,177 @@ +package kr.gmtc.tss.elkdata.vo; + +import java.time.LocalDateTime; +import java.time.ZoneOffset; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class StandStatusVO implements Comparable { + + private boolean inserted=false; + + public long timeStamp = LocalDateTime.now().toInstant(ZoneOffset.ofHours(9)).toEpochMilli(); + + public StandStatusVO() { + } + + protected LocalDateTime dateTime; + + @JsonProperty("stand_no") + private String standNo; + @JsonProperty("stand_sttus_ty") + private StandSttusTy standSttusTy; //AI 주기장 상황 분석 유형(공통코드-CT038) + @JsonProperty("aircraft_sttus_ty") + private String aircraftSttusTy; //주기장 항공기 상태 타입(공통코드-CT019) + private String clsgn; + private String schdul_id; + private String ac_reg_no; + + + @Override + public String toString() { + return "StandStatusVO [inserted=" + inserted + ", timeStamp=" + timeStamp + ", dateTime=" + dateTime + + ", standNo=" + standNo + ", standSttusTy=" + standSttusTy.toString() + ", aircraftSttusTy=" + aircraftSttusTy + + ", clsgn=" + clsgn + "]"; + } + + public boolean isInserted() { + return inserted; + } + + public void setInserted(boolean inserted) { + this.inserted = inserted; + } + + public long getTimeStamp() { + return timeStamp; + } + + public void setTimeStamp(long timeStamp) { + this.timeStamp = timeStamp; + } + + public LocalDateTime getDateTime() { + return dateTime; + } + + public void setDateTime(LocalDateTime dateTime) { + this.dateTime = dateTime; + } + + public String getStandNo() { + return standNo; + } + + public void setStandNo(String standNo) { + this.standNo = standNo; + } + + public String getClsgn() { + return clsgn; + } + + public void setClsgn(String clsgn) { + this.clsgn = clsgn; + } + + public StandSttusTy getStandSttusTy() { + return standSttusTy; + } + + public void setStandSttusTy(StandSttusTy standSttusTy) { + this.standSttusTy = standSttusTy; + } + + public String getAircraftSttusTy() { + return aircraftSttusTy; + } + + public void setAircraftSttusTy(String aircraftSttusTy) { + this.aircraftSttusTy = aircraftSttusTy; + } + + public String getSchdul_id() { + return schdul_id; + } + + public void setSchdul_id(String schdul_id) { + this.schdul_id = schdul_id; + } + + public String getAc_reg_no() { + return ac_reg_no; + } + + public void setAc_reg_no(String ac_reg_no) { + this.ac_reg_no = ac_reg_no; + } + + @Override + public boolean equals(Object obj) { + //p1.equals(p2) + if(obj instanceof StandStatusVO) { + StandStatusVO p = (StandStatusVO)obj; + return this.hashCode()==p.hashCode(); + + } + return false; + } + + @Override + public int compareTo(StandStatusVO o) { + return 0; + } + + public static class StandSttusTy { + @JsonProperty("arcft_stand") + private String arcrftStnd; + @JsonProperty("brdg_cnnctd") + private String brdgCnnctd; + @JsonProperty("crg_dr_opnd") + private String crgDrOpnd; + @JsonProperty("pad_clear") + private String padClear; + @JsonProperty("twng_cr_cnnctd") + private String twngCrCnnctd; + public String getArcrftStnd() { + return arcrftStnd; + } + public void setArcrftStnd(String arcrftStnd) { + this.arcrftStnd = arcrftStnd; + } + public String getBrdgCnnctd() { + return brdgCnnctd; + } + public void setBrdgCnnctd(String brdgCnnctd) { + this.brdgCnnctd = brdgCnnctd; + } + public String getCrgDrOpnd() { + return crgDrOpnd; + } + public void setCrgDrOpnd(String crgDrOpnd) { + this.crgDrOpnd = crgDrOpnd; + } + public String getPadClear() { + return padClear; + } + public void setPadClear(String padClear) { + this.padClear = padClear; + } + public String getTwngCrCnnctd() { + return twngCrCnnctd; + } + public void setTwngCrCnnctd(String twngCrCnnctd) { + this.twngCrCnnctd = twngCrCnnctd; + } + + @Override + public String toString() { + return "StandSttusTy [arcrftStnd=" + arcrftStnd + ", brdgCnnctd=" + brdgCnnctd + ", crgDrOpnd=" + crgDrOpnd + + ", padClear=" + padClear + ", twngCrCnnctd=" + twngCrCnnctd + "]"; + } + + public String toDataFormat() { + return arcrftStnd+"@"+brdgCnnctd+"@"+crgDrOpnd+"@"+padClear+"@"+twngCrCnnctd; + } + } +} diff --git a/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/StatsVO.java b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/StatsVO.java new file mode 100644 index 0000000..065ec2d --- /dev/null +++ b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/StatsVO.java @@ -0,0 +1,17 @@ +package kr.gmtc.tss.elkdata.vo; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class StatsVO { + + private String intrfc_dt; + private String intrfc_id; + private String intrfc_nm; + private int recv_co; + private int parse_co; + + +} diff --git a/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/TrackVO.java b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/TrackVO.java index b2e0f6c..d151545 100644 --- a/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/TrackVO.java +++ b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/TrackVO.java @@ -29,8 +29,12 @@ public class TrackVO implements Comparable { private String speed; @JsonProperty("cos") private String course; + @JsonProperty("alt") + private String alt; @JsonProperty("trgt_ty") private String targetType; + @JsonProperty("schdul_id") + private String schdulId; @JsonProperty("mode_s_cd") private String modeSCode; @JsonProperty("ssr_cd") @@ -43,9 +47,11 @@ public class TrackVO implements Comparable { private String correctedLatitude; @JsonProperty("crrct_lon") private String correctedLongitude; + @JsonProperty("is_cntrlzone") + private String isCntrlzone; + private List bbox; - @JsonProperty("alt") - private String alt; + @Override public String toString() { return "{" + @@ -56,12 +62,14 @@ public class TrackVO implements Comparable { ",\"spd\":\"" + speed + "\"" + ",\"cos\":\"" + course + "\"" + ",\"trgt_ty\":\"" + targetType + "\"" + + ",\"schdul_id\":\"" + schdulId + "\"" + ",\"mode_s_cd\":\"" + modeSCode + "\"" + ",\"ssr_cd\":\"" + ssrCode + "\"" + ",\"clsgn\":\"" + callsign + "\"" + ",\"tail_no\":\"" + tailNumber + "\"" + ",\"crrct_lat\":\"" + correctedLatitude + "\"" + ",\"crrct_lon\":\"" + correctedLongitude + "\"" + + ",\"is_cntrlzone\":\"" + isCntrlzone + "\"" + ",\"bbox\":" + bbox.toString() + "}"; } @@ -219,6 +227,22 @@ public class TrackVO implements Comparable { public void setAlt(String alt) { this.alt = alt; } + + public String getSchdulId() { + return schdulId; + } + + public void setSchdulId(String schdulId) { + this.schdulId = schdulId; + } + + public String getIsCntrlzone() { + return isCntrlzone; + } + + public void setIsCntrlzone(String isCntrlzone) { + this.isCntrlzone = isCntrlzone; + } @Override public boolean equals(Object obj) { @@ -310,4 +334,5 @@ public class TrackVO implements Comparable { this.py = py; } } + } diff --git a/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/VoiceVo.java b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/VoiceVo.java index c65915e..8e45673 100644 --- a/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/VoiceVo.java +++ b/tss_integrate/src/main/java/kr/gmtc/tss/elkdata/vo/VoiceVo.java @@ -20,6 +20,10 @@ public class VoiceVo { @JsonProperty("tag") private String tag; + public String getKeywordRow() { + return keyword+"@"+tag; + } + } @Getter @@ -37,6 +41,21 @@ public class VoiceVo { private List keywords; + public String getReadbackRow() { + + StringBuilder sbReadbackRow = new StringBuilder(); + sbReadbackRow.append(result+"@"+read_starttime+"@"); + int j = 0; + for(VoiceKeyword vk : keywords){ + if (j > 0) sbReadbackRow.append("$"); + + sbReadbackRow.append(vk.getKeywordRow()); + + } + + return sbReadbackRow.toString(); + } + } @JsonProperty("starttime") @@ -79,5 +98,7 @@ public class VoiceVo { @JsonProperty("text") private String text; + + } diff --git a/tss_integrate/src/main/java/kr/gmtc/tss/filelog/DataLogger.java b/tss_integrate/src/main/java/kr/gmtc/tss/filelog/DataLogger.java index 4413a1b..ead97ff 100644 --- a/tss_integrate/src/main/java/kr/gmtc/tss/filelog/DataLogger.java +++ b/tss_integrate/src/main/java/kr/gmtc/tss/filelog/DataLogger.java @@ -5,11 +5,6 @@ import java.util.Queue; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; - -import kr.gmtc.tss.elkdata.vo.TrackVO; import kr.gmtc.tss.main.MainServer; import kr.gmtc.tss.util.FileUtil; diff --git a/tss_integrate/src/main/java/kr/gmtc/tss/filelog/MessageBodyLogger.java b/tss_integrate/src/main/java/kr/gmtc/tss/filelog/MessageBodyLogger.java index 38fd86c..e3b3a1f 100644 --- a/tss_integrate/src/main/java/kr/gmtc/tss/filelog/MessageBodyLogger.java +++ b/tss_integrate/src/main/java/kr/gmtc/tss/filelog/MessageBodyLogger.java @@ -1,14 +1,10 @@ package kr.gmtc.tss.filelog; -import java.text.SimpleDateFormat; -import java.util.Date; import java.util.Queue; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.fasterxml.jackson.databind.ObjectMapper; - import kr.gmtc.tss.elkdata.vo.TrackVO; import kr.gmtc.tss.main.MainServer; import kr.gmtc.tss.util.FileUtil; @@ -80,7 +76,6 @@ private Logger logger = LoggerFactory.getLogger(this.getClass()); // } private String getMessageBody(TrackVO vo) { - ObjectMapper mapper = new ObjectMapper(); StringBuilder sb = new StringBuilder(); sb.append(vo.toString()); diff --git a/tss_integrate/src/main/java/kr/gmtc/tss/kafka/KafkaTopicReader.java b/tss_integrate/src/main/java/kr/gmtc/tss/kafka/KafkaTopicReader.java index 0aae941..49a31a9 100644 --- a/tss_integrate/src/main/java/kr/gmtc/tss/kafka/KafkaTopicReader.java +++ b/tss_integrate/src/main/java/kr/gmtc/tss/kafka/KafkaTopicReader.java @@ -28,6 +28,7 @@ public class KafkaTopicReader implements Runnable { } public void run() { + Properties props = new Properties(); props.put("bootstrap.servers", bootstrapServers); props.put("group.id", consumeGroupId); diff --git a/tss_integrate/src/main/java/kr/gmtc/tss/main/MainServer.java b/tss_integrate/src/main/java/kr/gmtc/tss/main/MainServer.java index c13bfc0..6a96a38 100644 --- a/tss_integrate/src/main/java/kr/gmtc/tss/main/MainServer.java +++ b/tss_integrate/src/main/java/kr/gmtc/tss/main/MainServer.java @@ -13,7 +13,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @@ -21,15 +20,20 @@ import kr.gmt.so.state.StateManager; import kr.gmt.so.state.model.SystemState; import kr.gmtc.tss.config.TopicsList; import kr.gmtc.tss.config.TssConfig; +import kr.gmtc.tss.elkdata.runnable.AiLocationParseRunnable; import kr.gmtc.tss.elkdata.runnable.AiVoiceMetaRunnable; +import kr.gmtc.tss.elkdata.runnable.AsdeParseRunnable; import kr.gmtc.tss.elkdata.runnable.CctvPtzParseRunnable; -import kr.gmtc.tss.elkdata.vo.RuteVO; +import kr.gmtc.tss.elkdata.runnable.FusionParseRunnable; +import kr.gmtc.tss.elkdata.runnable.RadarParseRunnable; +import kr.gmtc.tss.elkdata.runnable.RuteParseRunnable; +import kr.gmtc.tss.elkdata.runnable.StandStatusParseRunnable; +import kr.gmtc.tss.elkdata.runnable.StatusAnaParseRunnable; import kr.gmtc.tss.filelog.DataLogger; -import kr.gmtc.tss.filelog.MessageBodyLogger; import kr.gmtc.tss.kafka.KafkaTopicReader; import kr.gmtc.tss.util.FileUtil; +import kr.gmtc.tss.util.LogFileDelete; -@EnableScheduling @Component public class MainServer implements InitializingBean { @@ -41,8 +45,6 @@ public class MainServer implements InitializingBean { KafkaTopicReader kafkaTopicReader; // Runnable parserRunnable; DataLogger dataLoggerRunnable; - - MessageBodyLogger messageBodyLogger; List threadList = new ArrayList(); @@ -57,6 +59,7 @@ public class MainServer implements InitializingBean { @Autowired private StateManager stateMgr; + private boolean swBeforeStatus = true; public static int LAST_DATA_CNT = 0; @@ -69,7 +72,10 @@ public class MainServer implements InitializingBean { // logger.info("flagFile : "+cfg.flagFile); // 최초 한번만 실행 - 로그파일이 없을 시 생성 - DATA_FILE_NAME = fileUtil.createLogFile(cfg.dataZipPath, cfg.dataZipBakPath, cfg.dataMakeTime); // logstash data file log + String[] arrSW = cfg.swclassification; + for(String swIdx : arrSW){ + DATA_FILE_NAME = fileUtil.createLogFile(cfg.dataZipPath +"/"+ swIdx , cfg.dataZipBakPath +"/"+ swIdx, cfg.dataMakeTime); // logstash data file log + } } @PreDestroy @@ -94,7 +100,7 @@ public class MainServer implements InitializingBean { startKafkaThread(); startParserThread(); - // startSqlLoggerThread(); + } @Scheduled(cron = "${process.status-check-cron}") @@ -105,55 +111,69 @@ public class MainServer implements InitializingBean { boolean running = true; boolean swNewStatus = stateMgr.isActive(); - // 해당 프로그램이 Active일때 Thread Interrupt 유무 체크 - if(swNewStatus){ - + // Active 상태로 변경된경우 + if(swNewStatus && !swBeforeStatus){ + logger.info("SW상태 변경됨[Active] 스레드 시작."); for(Thread ct : threadList ){ - if(ct.isInterrupted()){ - running = false; - break; - } + ct.start(); } + // Standby 상태로 변경된경우 + }else if(!swNewStatus && swBeforeStatus){ + logger.info("SW상태 변경됨[Standby] 스레드 중지."); + for(Thread ct : threadList ){ + ct.interrupt(); + } + }else { + + // 해당 프로그램이 Active일때 Thread Interrupt 유무 체크 + if(swNewStatus){ + for(Thread ct : threadList ){ + if(ct.isInterrupted()){ + running = false; + break; + } + } + + if(running){ + stateMgr.updateState(SystemState.Normal); + + for(Thread ct : threadList ){ + if(ct.getState() == Thread.State.NEW) ct.start(); + } + + }else{ + stateMgr.updateState(SystemState.Error); + } - if(running){ - stateMgr.updateState(SystemState.Normal); - }else{ - stateMgr.updateState(SystemState.Error); } } + swBeforeStatus = swNewStatus; + } - @Scheduled(cron = "${process.file-backup-cron}") - public void fileRecv() throws Exception{ - // if (cfg.flagFile) { - /* 파일 압축 */ - // fileUtil.createZipFile(cfg.fileZipPath, cfg.fileZipBakPath, cfg.fileMakeTime); - // } - } + @Scheduled(cron = "${process.data-backup-cron}") public void dataFileRecv() throws Exception{ - if (cfg.flagDataFile) { - /* 파일 압축 */ - fileUtil.createZipFile(cfg.dataZipPath, cfg.dataZipBakPath, cfg.dataMakeTime); + String[] arrSW = cfg.swclassification; + for(String swIdx : arrSW){ + fileUtil.createZipFile(cfg.dataZipPath +"/"+ swIdx , cfg.dataZipBakPath +"/"+ swIdx, cfg.dataMakeTime); } } - // 매 시간 10분 간격 으로 실행 - @Scheduled(cron = "${process.file-make-cron}") - public void fileMake() throws Exception{ - // if (cfg.flagFile) { - // FILE_LOG_NAME = fileUtil.createLogFile(cfg.fileZipPath, cfg.fileZipBakPath, cfg.fileMakeTime); - // } - } - @Scheduled(cron = "${process.data-make-cron}") public void dataFileMake() throws Exception{ - if (cfg.flagDataFile) { - DATA_FILE_NAME = fileUtil.createLogFile(cfg.dataZipPath, cfg.dataZipBakPath, cfg.dataMakeTime); + String[] arrSW = cfg.swclassification; + for(String swIdx : arrSW){ + DATA_FILE_NAME = fileUtil.createLogFile(cfg.dataZipPath +"/"+ swIdx , cfg.dataZipBakPath +"/"+ swIdx, cfg.dataMakeTime); } } + @Scheduled(cron = "${process.data-delete-cron}") + public void dataFileDelete() throws Exception{ + fileUtil.deleteLogFiles(cfg.dataZipBakPath, cfg.dataSaveDays); + } + public void startKafkaThread() { @@ -169,7 +189,7 @@ public class MainServer implements InitializingBean { this.kafkaTopicReader=topicReader; Thread thread = new Thread(topicReader); thread.setDaemon(true); - thread.start(); + //thread.start(); threadList.add(thread); @@ -186,38 +206,97 @@ public class MainServer implements InitializingBean { String[] arrSW = cfg.swclassification; - Map topics = topicList.getTopics(); + // Map topics = topicList.getTopics(); + + Queue dataFileQue = cfg.getDataFileQueue(); + + Thread thread = null; for(String swIdx : arrSW){ - String topic = topics.get(swIdx); + // String topic = topics.get(swIdx); Queue rcvQueue = cfg.getRcvQueueMap().get(swIdx); - if(swIdx.equals("6")){ + if(swIdx.equals("1")){ - AiVoiceMetaRunnable aiVoiceParseRunnable = new AiVoiceMetaRunnable(rcvQueue, cfg.dataFileQueue, + AsdeParseRunnable parseRunnable = new AsdeParseRunnable(rcvQueue, dataFileQue, cfg.queueChunkSize, cfg.parseTargetSleepMs, cfg.classification, swIdx, cfg.logclassification ); - Thread thread = new Thread(aiVoiceParseRunnable); - thread.setDaemon(true); - thread.start(); - threadList.add(thread); - - logger.info("parserThread 생성 [" +swIdx+ "]"); - } - - if(swIdx.equals("11")){ + thread = new Thread(parseRunnable); - AiVoiceMetaRunnable aiVoiceParseRunnable = new AiVoiceMetaRunnable(rcvQueue, cfg.dataFileQueue, + } + else if(swIdx.equals("2")){ + + AiLocationParseRunnable parseRunnable = new AiLocationParseRunnable(rcvQueue, dataFileQue, cfg.queueChunkSize, cfg.parseTargetSleepMs, cfg.classification, swIdx, cfg.logclassification ); - Thread thread = new Thread(aiVoiceParseRunnable); + thread = new Thread(parseRunnable); + } + else if(swIdx.equals("3")){ + + FusionParseRunnable parseRunnable = new FusionParseRunnable(rcvQueue, dataFileQue, + cfg.queueChunkSize, cfg.parseTargetSleepMs, + cfg.classification, swIdx, cfg.logclassification ); + thread = new Thread(parseRunnable); + } + else if(swIdx.equals("4")){ + + RadarParseRunnable parseRunnable = new RadarParseRunnable(rcvQueue, dataFileQue, + cfg.queueChunkSize, cfg.parseTargetSleepMs, + cfg.classification, swIdx, cfg.logclassification ); + thread = new Thread(parseRunnable); + } + else if(swIdx.equals("6")){ + + AiVoiceMetaRunnable parseRunnable = new AiVoiceMetaRunnable(rcvQueue, dataFileQue, + cfg.queueChunkSize, cfg.parseTargetSleepMs, + cfg.classification, swIdx, cfg.logclassification ); + thread = new Thread(parseRunnable); + } + else if(swIdx.equals("7")){ + + StatusAnaParseRunnable parseRunnable = new StatusAnaParseRunnable(rcvQueue, dataFileQue, + cfg.queueChunkSize, cfg.parseTargetSleepMs, + cfg.classification, swIdx, cfg.logclassification ); + thread = new Thread(parseRunnable); + } + else if(swIdx.equals("8")){ + + StandStatusParseRunnable parseRunnable = new StandStatusParseRunnable(rcvQueue, dataFileQue, + cfg.queueChunkSize, cfg.parseTargetSleepMs, + cfg.classification, swIdx, cfg.logclassification ); + thread = new Thread(parseRunnable); + } + else if(swIdx.equals("9")){ + + CctvPtzParseRunnable parseRunnable = new CctvPtzParseRunnable(rcvQueue, dataFileQue, + cfg.queueChunkSize, cfg.parseTargetSleepMs, + cfg.classification, swIdx, cfg.logclassification ); + thread = new Thread(parseRunnable); + } + else if(swIdx.equals("10")){ + + RuteParseRunnable parseRunnable = new RuteParseRunnable(rcvQueue, dataFileQue, + cfg.queueChunkSize, cfg.parseTargetSleepMs, + cfg.classification, swIdx, cfg.logclassification ); + thread = new Thread(parseRunnable); + } + else if(swIdx.equals("11")){ + + AiVoiceMetaRunnable aiVoiceParseRunnable = new AiVoiceMetaRunnable(rcvQueue, dataFileQue, + cfg.queueChunkSize, cfg.parseTargetSleepMs, + cfg.classification, swIdx, cfg.logclassification ); + thread = new Thread(aiVoiceParseRunnable); + } + + if(thread != null){ thread.setDaemon(true); - thread.start(); + //thread.start(); threadList.add(thread); - + logger.info("parserThread 생성 [" +swIdx+ "]"); } + } @@ -229,7 +308,7 @@ public class MainServer implements InitializingBean { } public void startDataLoggerThread() { - DataLogger dataLoggerRunnable = new DataLogger(cfg.dataFileQueue, cfg.queueChunkSize, cfg.sqlLoggerSleepMs); + DataLogger dataLoggerRunnable = new DataLogger(cfg.getDataFileQueue(), cfg.queueChunkSize, cfg.sqlLoggerSleepMs); this.dataLoggerRunnable = dataLoggerRunnable; Thread thread = new Thread(dataLoggerRunnable); diff --git a/tss_integrate/src/main/java/kr/gmtc/tss/util/ArrayBlockingLoggingQueue.java b/tss_integrate/src/main/java/kr/gmtc/tss/util/ArrayBlockingLoggingQueue.java index ec4f2de..6834f7c 100644 --- a/tss_integrate/src/main/java/kr/gmtc/tss/util/ArrayBlockingLoggingQueue.java +++ b/tss_integrate/src/main/java/kr/gmtc/tss/util/ArrayBlockingLoggingQueue.java @@ -15,36 +15,30 @@ public class ArrayBlockingLoggingQueue extends ArrayBlockingQueue c) { super(capacity, fair, c); - // TODO Auto-generated constructor stub } public ArrayBlockingLoggingQueue(int capacity, boolean fair) { super(capacity, fair); - // TODO Auto-generated constructor stub } public ArrayBlockingLoggingQueue(int capacity) { super(capacity); - // TODO Auto-generated constructor stub } @Override public synchronized boolean add(Object e) { - // TODO Auto-generated method stub logger.debug(e+""); return super.add(e); } @Override public synchronized boolean offer(Object e) { - // TODO Auto-generated method stub logger.debug(e+""); return super.offer(e); } @Override public synchronized boolean offer(Object e, long timeout, TimeUnit unit) throws InterruptedException { - // TODO Auto-generated method stub logger.debug(e+""); return super.offer(e, timeout, unit); } diff --git a/tss_integrate/src/main/java/kr/gmtc/tss/util/FileUtil.java b/tss_integrate/src/main/java/kr/gmtc/tss/util/FileUtil.java index 83d9db1..5e0d167 100644 --- a/tss_integrate/src/main/java/kr/gmtc/tss/util/FileUtil.java +++ b/tss_integrate/src/main/java/kr/gmtc/tss/util/FileUtil.java @@ -7,27 +7,24 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.attribute.BasicFileAttributes; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; +import java.util.concurrent.TimeUnit; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; @Component public class FileUtil { -// @Value("${file-zip-path}") -// private String fileZipPath; -// -// @Value("${file-zip-bak-path}") -// private String fileZipBakPath; -// -// @Value("${file-make-time}") -// private int fileMakeTime; - -// public static String FILE_LOG_NAME; + private static final Logger logger = LoggerFactory.getLogger(FileUtil.class); /** * 로그파일을 압축한다. @@ -41,14 +38,14 @@ public class FileUtil { backDir.mkdirs(); } - SimpleDateFormat fileFormatter = new SimpleDateFormat("yyyyMMddHHmm"); + SimpleDateFormat fileFormatter = new SimpleDateFormat("yyyyMMdd-HHmm"); Calendar cal = Calendar.getInstance(); cal.add(Calendar.MINUTE, -20); // 20분전 데이터 확인 String time20 = fileFormatter.format(cal.getTime()); // 압축할 파일 명 확인. - String bakFileName = "file."+time20+".log"; + String bakFileName = "data."+time20+".log"; String fileName = ""; ZipOutputStream zip_out = null; @@ -84,7 +81,7 @@ public class FileUtil { } } else { - System.out.println("파일이 존재하지 않습니다."); + //System.out.println("파일이 존재하지 않습니다."); } } @@ -117,26 +114,39 @@ public class FileUtil { } - private void bakFileDelete(String fileZipPath, String date) throws IOException { - File folder = new File(fileZipPath+"/"+date); // file 생성 - - try { - while(folder.exists()){ - File[] files = folder.listFiles(); - - for(File file : files){ - file.delete(); // 하위 파일 삭제 - } + public void deleteLogFiles(String sFile, int day) { + + File dirPath = new File(sFile); + int sec = day * (24*60*60); + + if (!dirPath.isDirectory()) return; + + for (File adminDirs : dirPath.listFiles()) { + + File files[] = adminDirs.listFiles(); + if (files == null) continue; + + for (File f : files) { + try { + long fModify = getSecondsFromModification(f); + if (fModify > sec) { + logger.info("백업 파일 삭제 : " + f.getAbsolutePath() + " 최종 로깅 : " + (fModify /24/60/60) + "일 전" ); + f.delete(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + // 파일의 수정한 날짜를 현재 시간 대비 경과 시간을 초로 환산 하여 리턴 + private static long getSecondsFromModification(File f) throws IOException { + + Path attribPath = f.toPath(); + BasicFileAttributes basicAttribs = Files.readAttributes(attribPath, BasicFileAttributes.class); + return (System.currentTimeMillis() - basicAttribs.lastModifiedTime().to(TimeUnit.MILLISECONDS)) / 1000; - // 폴더 삭제 - if(files.length == 0 && folder.isDirectory()){ // 하위 파일이 없는지와 폴더인지 확인 후 폴더 삭제 - folder.delete(); // 대상폴더 삭제 - } - } - - } catch(Exception e) { - e.printStackTrace(); - } } /** @@ -172,11 +182,11 @@ public class FileUtil { } // 생성할 파일명을 설정한다. - SimpleDateFormat fileFormatter = new SimpleDateFormat("yyyyMMddHH"); + SimpleDateFormat fileFormatter = new SimpleDateFormat("yyyyMMdd-HH"); String fileTime = fileFormatter.format(now) + nowT; try { - _path = fileZipPath+"/file."+fileTime+".log"; + _path = fileZipPath+"/data."+fileTime+".log"; // static 변수에 값을 세팅한다. //FILE_LOG_NAME = _path; @@ -190,7 +200,7 @@ public class FileUtil { if (file.createNewFile()) { System.out.println("파일 생성 완료"); } else { - System.out.println("파일 이미 존재"); + //System.out.println("파일 이미 존재"); } } catch (IOException e) { e.printStackTrace(); diff --git a/tss_integrate/src/main/java/kr/gmtc/tss/util/LogFileDelete.java b/tss_integrate/src/main/java/kr/gmtc/tss/util/LogFileDelete.java new file mode 100644 index 0000000..abeb0b3 --- /dev/null +++ b/tss_integrate/src/main/java/kr/gmtc/tss/util/LogFileDelete.java @@ -0,0 +1,50 @@ +package kr.gmtc.tss.util; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.concurrent.TimeUnit; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class LogFileDelete { + + private static final Logger log = LoggerFactory.getLogger(LogFileDelete.class); + + public static void deleteFolders(String sFile, int sec) { + + File video = new File(sFile); + + if (!video.isDirectory()) return; + + for (File adminDirs : video.listFiles()) { + + File files[] = adminDirs.listFiles(); + if (files == null) continue; + + for (File f : files) { + try { + long fModify = getSecondsFromModification(f); + if (fModify > sec) { + log.info("백업 파일 삭제 : " + f.getAbsolutePath() + " 최종 로깅 : " + (fModify /24/60/60) + "일 전" ); + f.delete(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + // 파일의 수정한 날짜를 현재 시간 대비 경과 시간을 초로 환산 하여 리턴 + private static long getSecondsFromModification(File f) throws IOException { + + Path attribPath = f.toPath(); + BasicFileAttributes basicAttribs = Files.readAttributes(attribPath, BasicFileAttributes.class); + return (System.currentTimeMillis() - basicAttribs.lastModifiedTime().to(TimeUnit.MILLISECONDS)) / 1000; + + } +} diff --git a/tss_integrate/src/main/resources/application.yml b/tss_integrate/src/main/resources/application.yml index b5e3eff..0957f13 100644 --- a/tss_integrate/src/main/resources/application.yml +++ b/tss_integrate/src/main/resources/application.yml @@ -1,32 +1,18 @@ server: - port: 8090 + port: 18990 -# spring: - # datasource: - # hikari: - # maximum-pool-size: 1 - # minimum-idle: 1 - #main: - #web-application-type: none - # db: - # #db-type:oracle,mariadb(other - coding more!) - # #db-type: oracle - # batch-insert-size: 1000 - # datasource: - # #jdbc-url: jdbc:tibero:thin:@118.220.143.174:18629:SACP_T_DB - # jdbc-url: jdbc:tibero:thin:@10.200.31.4:8629:sacp #공항 - # driver-class-name: com.tmax.tibero.jdbc.TbDriver - # username: UTRACK - # password: UTRACK - # connectionTimeout: 5000 - # maxLifetime: 30000 - +spring: + db: + batch-insert-size: 1000 + datasource: + driver-class-name: com.tmax.tibero.jdbc.TbDriver + jdbc-url: jdbc:tibero:thin:@118.220.143.174:18629:SACP_T_DB + username: UTRACK + password: UTRACK + connectionTimeout: 5000 + maxLifetime: 30000 client: - server: - ip: 127.0.0.1 - port: 8030 - reconn-time-sec: 5 queue-count: 1000000 selep-time-ms: @@ -42,60 +28,50 @@ dynamic-dedupl: process: - #count-log-cron: 0 0/1 * 1/1 * * - #count-log-cron: 0/10 * * 1/1 * * queue-chunk-size: 1000 - # 매일 오전 9시부터 오후7시까지 1분마다 실행 - # rest api 호출 스케줄러 - rest-cron: 0 0/1 * * * * - # 파일 백업 스케쥴러 시간 - file-backup-cron: 0 0/10 * * * * - # 파일 생성 스케쥴러 시간 - file-make-cron: 0 0/10 * * * * # 파일 백업 스케쥴러 시간 data-backup-cron: 0 0/10 * * * * # 파일 생성 스케쥴러 시간 data-make-cron: 0 0/10 * * * * + # 파일 삭제 스케쥴러 시간 + data-delete-cron: 0 0 03 * * * # 스레드 상태 체크 스케줄러 status-check-cron: 0/10 * * * * * flag: - # database: false datafile: true #logstash data log file, Log 포멧 - # file: true #rest api log file, Json - -file-zip-path: ./logs/file -file-zip-bak-path: ./logs/backup -file-make-time: 10 -data-zip-path: ./logs/data -data-zip-bak-path: ./logs/databackup -data-make-time: 10 +file-zip-path: ./logs/data +file-zip-bak-path: ./logs/databackup +file-make-time: 10 #Min +file-save-days: 90 #Day kafka: bootstrapServers: http://10.200.31.6:9091,http://10.200.31.8:9091,http://10.200.31.142:9091 #공항 groupId: TssTopicReader_TEST topics: # swclassification 동일하게 번호 설정 - 1: ic.recv.asde - 2: ai.analyze.location - 3: ic.tracking.fusion - 4: ic.recv.radar - 5: ai.analyze.video - 6: ai.analyze.voice - 7: ic.analyze.situation - 8: ic.analyze.stand.status - 9: ic.tracking.ptz - 10: ic.service.route - 11: ai.analyze.ltea - 12: ic.tracking.ptz.manual + 1: ic.recv.asde # LK0402 #ASDE정보저장S/W + 2: ai.analyze.location # AI0202 #영상메타데이터저장S/W + 3: ic.tracking.fusion # IC0102 #위치융합정보저장S/W + 4: ic.recv.radar # LK0503 #레이더추적정보저장S/W + # 5: ai.analyze.video # 미사용, 8번으로 대체 + 6: ai.analyze.voice # AI0402 #음성메타데이터저장S/W + 7: ic.analyze.situation # IC0303 #주기장 상태 분석 정보저장S/W + 8: ic.analyze.stand.status # IC0303 #주기장 상태 분석 정보저장S/W + 9: ic.tracking.ptz # IC0502 #추적용CCTV제어정보저장S/W + 10: ic.service.route # IC0702 #이동경로분석정보저장S/W + 11: ai.analyze.ltea # AI0402 #음성메타데이터저장S/W + 12: ic.tracking.ptz.manual # IC0502 #추적용CCTV제어정보저장S/W classification: 1 #이중화되어 있는 서버의 Index -swclassification: 6, 11 #sw구분 +swclassification: 1 #sw구분 logclassification: 1 #log구분 state: - # 공통코드 CT001의 코드 6자리 + # 공통코드 시스템 코드(CT001)의 코드 6자리 id: TEST09 # 위치융합정보 # 1:Primary, 2:Secondary - type: Primary \ No newline at end of file + type: Primary + # DisplayLog: true + sendlog: true diff --git a/tss_integrate/src/main/resources/logback-spring.xml b/tss_integrate/src/main/resources/logback-spring.xml index 6296625..c1802d5 100644 --- a/tss_integrate/src/main/resources/logback-spring.xml +++ b/tss_integrate/src/main/resources/logback-spring.xml @@ -16,7 +16,6 @@ ${LOG_PATTERN} - UTF-8 @@ -27,7 +26,6 @@ ${LOG_PATTERN} - UTF-8 @@ -37,6 +35,21 @@ + + ${LOG_PATH}/STATS/stats.log + + %msg%n + + + ${LOG_PATH}/STATS/stats.%d{yyyy-MM-dd}.log + + 30 + + + %msg%n - UTF-8 @@ -80,5 +92,10 @@ + + + + + \ No newline at end of file