main
MonHun 2024-05-09 19:13:40 +09:00
parent 9b3d6e0fed
commit f169747946
27 changed files with 852 additions and 74 deletions

Binary file not shown.

24
pom.xml
View File

@ -38,6 +38,12 @@
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
@ -58,10 +64,24 @@
</dependency>
<dependency>
<groupId>org.locationtech.jts</groupId>
<artifactId>jts-core</artifactId>
<version>1.19.0</version>
</dependency>
<dependency>
<groupId>com.tmax.tibero</groupId>
<artifactId>tibero-jdbc</artifactId>
<version>7</version>
<scope>system</scope>
<systemPath>${basedir}/lib/tibero-jdbc-7.0.0.jar</systemPath>
</dependency>
<!-- <dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.9</version>
</dependency>
</dependency> -->
<!-- <dependency>
<groupId>kr.gmt.so</groupId>
@ -77,6 +97,8 @@
<systemPath>${basedir}/lib/ipworks-local-1.0.0.jar</systemPath>
</dependency> -->
</dependencies>
<build>

View File

@ -1,13 +1,17 @@
package kr.gmtc.gw.elastic;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.context.ApplicationPidFileWriter;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.scheduling.annotation.EnableScheduling;
@EnableScheduling
@SpringBootApplication
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class,HibernateJpaAutoConfiguration.class})
public class ESApplication {
public static void main(String[] args) {

View File

@ -0,0 +1,11 @@
package kr.gmtc.gw.elastic.config;
import java.util.Map;
import java.util.Queue;
public class AppConfig {
}

View File

@ -0,0 +1,54 @@
package kr.gmtc.gw.elastic.config;
import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
@Configuration
@MapperScan(value = "kr.gmtc.gw.elastic.mapper", sqlSessionFactoryRef = "factory")
public class DataSourceConfigDB1 {
@Primary
@Bean(name = "datasource")
@ConfigurationProperties(prefix = "database.db1.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
@Primary
@Bean(name = "factory")
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
sqlSessionFactory.setDataSource(dataSource);
Resource[] res = new PathMatchingResourcePatternResolver().getResources("classpath:mapper/DB1.xml");
sqlSessionFactory.setMapperLocations(res);
return sqlSessionFactory.getObject();
}
@Primary
@Bean(name="SqlSessionTemplate")
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) throws Exception{
return new SqlSessionTemplate(sqlSessionFactory);
}
@Primary
@Bean
public DataSourceTransactionManager ATransactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}

View File

@ -1,13 +1,17 @@
package kr.gmtc.gw.elastic.config;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.RestClients;
import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
@Configuration
//@EnableElasticsearchRepositories(basePackages = "kr.gmtc.gw.elk.repositories")
@ -18,19 +22,44 @@ public class ElasticsearchClientConfig extends AbstractElasticsearchConfiguratio
private String gsEsHost;
@Value("${app.config.elastic.port}")
private String gsEsPort;
private int gsEsPort;
// @Override
// @Bean(destroyMethod = "close")
// public RestHighLevelClient elasticsearchClient() {
// final ClientConfiguration clientConfiguration =
// ClientConfiguration
// .builder()
// .connectedTo(gsEsHost + ":" + gsEsPort)
// //.connectedTo( "10.200.31.129:9200")
// .build();
// return RestClients.create(clientConfiguration).rest();
// }
@Override
@Bean(destroyMethod = "close")
public RestHighLevelClient elasticsearchClient() {
final ClientConfiguration clientConfiguration =
ClientConfiguration
.builder()
.connectedTo(gsEsHost + ":" + gsEsPort)
//.connectedTo( "10.200.31.129:9200")
.build();
return RestClients.create(clientConfiguration).rest();
RestClientBuilder builder = RestClient.builder(
new HttpHost(gsEsHost, gsEsPort))
.setRequestConfigCallback(
new RestClientBuilder.RequestConfigCallback() {
@Override
public RequestConfig.Builder customizeRequestConfig(
RequestConfig.Builder requestConfigBuilder) {
return requestConfigBuilder
.setConnectTimeout(5000)
.setSocketTimeout(60000);
}
});
return new RestHighLevelClient(builder);
}
@Bean
public ElasticsearchOperations esTemplate() {
return new ElasticsearchRestTemplate(elasticsearchClient());
}
}

View File

@ -0,0 +1,23 @@
package kr.gmtc.gw.elastic.config;
import java.util.Map;
import java.util.Queue;
public class QueueManageBean {
private Map<String, Queue<?>> replayLogQ;
public void setQue(String qid, Queue<?> que){
replayLogQ.put(qid, que) ;
}
public Queue<?> getQue(String qid){
return replayLogQ.get(qid);
}
}

View File

@ -0,0 +1,238 @@
package kr.gmtc.gw.elastic.controller;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Point;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import co.elastic.clients.elasticsearch.ml.get_calendars.Calendar;
import kr.gmtc.gw.comp.thread.CustomThread;
import kr.gmtc.gw.elastic.services.AeraService;
import kr.gmtc.gw.elastic.services.ElkSearchService;
import kr.gmtc.gw.elastic.vo.AnalyzeArea.Area;
import kr.gmtc.gw.elastic.vo.ReplayLog.FusionVO;
import kr.gmtc.gw.elastic.vo.ReplayLog.LogMsgParserVO;
@Component("aeraSchduler")
public class AeraSchduler implements ApplicationListener<ContextClosedEvent> {
@Autowired
private ElkSearchService elkSearchService;
private AeraService aeraService;
private List<CustomThread> getDBdataThreads;
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private int areaSelectInterval = 10 * (60 * 1000);
private int analyzeOnAreaInterval = 1 * (60 * 1000);
private final GeometryFactory gf = new GeometryFactory();
private Map<String, Area> mapTaxiway = new ConcurrentHashMap<String, Area>();
private Queue<LogMsgParserVO> parserFusionQ = new LinkedBlockingQueue<LogMsgParserVO>();
private LocalDateTime procBeforeDT;
public AeraSchduler(AeraService aeraService){
this.aeraService = aeraService;
}
@Order(0)
@EventListener(ApplicationReadyEvent.class)
public void initialize() {
try {
// 업무 스래드(프로시저 호출)
getDBdataThreads = new ArrayList<CustomThread>();
getDBdataThreads.add(new CustomThread("selectAeraList", this, areaSelectInterval, this::selectAeraList, null, false));
getDBdataThreads.add(new CustomThread("analyzeOnArea", this, analyzeOnAreaInterval, this::analyzeOnArea, null, false));
} catch (Exception e) {
logger.error("MainContoller-Thread create fail");
System.exit(1);
}
}
/**
* (2)<br>
*
*/
@Order(1)
@EventListener(ApplicationReadyEvent.class)
public void start() {
try {
logger.info("MainContoller-Thread start");
for(CustomThread ct : getDBdataThreads ){
ct.start();
}
} catch (Exception e) {
logger.error("MainContoller-Thread start fail");
System.exit(1);
}
}
/** 종료 처리 */
public void stop() {
for(CustomThread ct : getDBdataThreads ){
ct.gracefulStop();
}
}
private void analyzeOnArea(){
if(mapTaxiway.size() == 0) selectAeraList();
if(searchElastic().equals("OK")) {
checkArea();
}
}
private void selectAeraList(){
// List<HashMap<String, Object>> getAeraList = aeraService.getAeraListMap();
// Map<String, List<HashMap<String, Object>>> groupedAreas = aeraService.groupAreasByID(getAeraList);
List<Area> areaList = aeraService.getAeraList();
mapTaxiway.clear();
areaList.forEach(area -> mapTaxiway.put(area.getId(), area));
mapTaxiway.forEach((id, area) -> area.generateLineToBufferedPolygon(10));
String asdfa = "asdfadf";
}
private String searchElastic(){
String sIndex = "3";
String sStartDt, sEndDt;
// TODO : DB table 시각 가져오기, file저장
if(procBeforeDT == null ){
procBeforeDT = LocalDateTime.now().minusMinutes(10);
}
LocalDateTime currentDT = LocalDateTime.now();
sStartDt = procBeforeDT.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss.SSS"));
sEndDt = currentDT.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss.SSS"));
procBeforeDT = currentDT;
String searchRes = elkSearchService.searchFusion(parserFusionQ, sIndex, sStartDt, sEndDt);
if(searchRes.equals("OK")){
logger.info("Elastic 데이터 조회 완료");
}
return searchRes;
}
public void checkArea(){
for(LogMsgParserVO logVO : parserFusionQ ){
for(int idx = 0; idx < logVO.getData().size(); idx ++ ){
List<FusionVO> fList = (List<FusionVO>) logVO.getData();
for(FusionVO fVO : fList){
double dLon = Double.parseDouble(fVO.getLon());
double dLat = Double.parseDouble(fVO.getLat());
// AeraSchduler as = new AeraSchduler( new AeraService() );
List<String> areaList = checkPositionInTaxiway(dLon, dLat);
if (!areaList.isEmpty()){
}
}
}
}
}
public List<String> checkPositionInTaxiway(double lon, double lat) {
List<String> useTwyList = new ArrayList<>();
Point point = gf.createPoint(new Coordinate(lon, lat));
try {
if (point == null) {
throw new NullPointerException("Point param is null");
}
for (Area area : mapTaxiway.values()) {
// result = result || area.isContains(point);
if(area.isContains(point)){
useTwyList.add(area.getId());
}
}
} catch (RuntimeException e) {
logger.error("[checkPositionInTaxiway] is generate runtime error ", e);
return useTwyList;
} catch(Exception e) {
logger.error("[checkPositionInTaxiway] is fatal error ", e);
return useTwyList;
}
return useTwyList;
}
@Override
public void onApplicationEvent(ContextClosedEvent event) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'onApplicationEvent'");
}
}

View File

@ -0,0 +1,17 @@
package kr.gmtc.gw.elastic.mapper;
import java.util.HashMap;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import kr.gmtc.gw.elastic.vo.AnalyzeArea.Area;
@Mapper
public interface AeraMapper {
List<HashMap<String, Object>> selectAeraListMap();
List<Area> selectAeraList();
}

View File

@ -6,10 +6,10 @@ import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
import kr.gmtc.gw.elastic.utils.LogMsgParserUtile;
import kr.gmtc.gw.elastic.vo.ElasticMsgHeader;
import kr.gmtc.gw.elastic.vo.ElasticResultMsgVO;
import kr.gmtc.gw.elastic.vo.LogMsgParserVO;
import kr.gmtc.gw.elastic.vo.ElasticRecv.ElasticMsgHeader;
import kr.gmtc.gw.elastic.vo.ElasticRecv.ElasticResultMsgVO;
import kr.gmtc.gw.elastic.vo.ReplayLog.AsdeVO;
import kr.gmtc.gw.elastic.vo.ReplayLog.LogMsgParserVO;
import kr.gmtc.gw.elastic.vo.ReplayLog.StandardRouteVO;
import kr.gmtc.gw.elastic.vo.ReplayLog.StandardRouteVO.RoutePoints;

View File

@ -6,9 +6,9 @@ import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
import kr.gmtc.gw.elastic.utils.LogMsgParserUtile;
import kr.gmtc.gw.elastic.vo.ElasticMsgHeader;
import kr.gmtc.gw.elastic.vo.ElasticResultMsgVO;
import kr.gmtc.gw.elastic.vo.LogMsgParserVO;
import kr.gmtc.gw.elastic.vo.ElasticRecv.ElasticMsgHeader;
import kr.gmtc.gw.elastic.vo.ElasticRecv.ElasticResultMsgVO;
import kr.gmtc.gw.elastic.vo.ReplayLog.LogMsgParserVO;
import kr.gmtc.gw.elastic.vo.ReplayLog.RadarVO;
import kr.gmtc.gw.elastic.vo.ReplayLog.StandardRouteVO;
import kr.gmtc.gw.elastic.vo.ReplayLog.StandardRouteVO.RoutePoints;

View File

@ -6,10 +6,10 @@ import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
import kr.gmtc.gw.elastic.utils.LogMsgParserUtile;
import kr.gmtc.gw.elastic.vo.ElasticMsgHeader;
import kr.gmtc.gw.elastic.vo.ElasticResultMsgVO;
import kr.gmtc.gw.elastic.vo.LogMsgParserVO;
import kr.gmtc.gw.elastic.vo.ElasticRecv.ElasticMsgHeader;
import kr.gmtc.gw.elastic.vo.ElasticRecv.ElasticResultMsgVO;
import kr.gmtc.gw.elastic.vo.ReplayLog.AiLocationVO;
import kr.gmtc.gw.elastic.vo.ReplayLog.LogMsgParserVO;
public class ParserAILocation {

View File

@ -6,10 +6,10 @@ import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
import kr.gmtc.gw.elastic.utils.LogMsgParserUtile;
import kr.gmtc.gw.elastic.vo.ElasticMsgHeader;
import kr.gmtc.gw.elastic.vo.ElasticResultMsgVO;
import kr.gmtc.gw.elastic.vo.LogMsgParserVO;
import kr.gmtc.gw.elastic.vo.ElasticRecv.ElasticMsgHeader;
import kr.gmtc.gw.elastic.vo.ElasticRecv.ElasticResultMsgVO;
import kr.gmtc.gw.elastic.vo.ReplayLog.AnaVO;
import kr.gmtc.gw.elastic.vo.ReplayLog.LogMsgParserVO;
import kr.gmtc.gw.elastic.vo.ReplayLog.AnaVO.Area;
import kr.gmtc.gw.elastic.vo.ReplayLog.AnaVO.Target;

View File

@ -5,11 +5,12 @@ import java.util.List;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
import kr.gmtc.gw.elastic.controller.AeraSchduler;
import kr.gmtc.gw.elastic.utils.LogMsgParserUtile;
import kr.gmtc.gw.elastic.vo.ElasticMsgHeader;
import kr.gmtc.gw.elastic.vo.ElasticResultMsgVO;
import kr.gmtc.gw.elastic.vo.LogMsgParserVO;
import kr.gmtc.gw.elastic.vo.ElasticRecv.ElasticMsgHeader;
import kr.gmtc.gw.elastic.vo.ElasticRecv.ElasticResultMsgVO;
import kr.gmtc.gw.elastic.vo.ReplayLog.FusionVO;
import kr.gmtc.gw.elastic.vo.ReplayLog.LogMsgParserVO;
import kr.gmtc.gw.elastic.vo.ReplayLog.FusionVO.BoundingBox;
@ -17,12 +18,14 @@ public class ParserFusion {
private List<ElasticResultMsgVO> logMsgs;
Queue<LogMsgParserVO> parserAiLocQ = new LinkedBlockingQueue<LogMsgParserVO>();
Queue<LogMsgParserVO> parserFusionQ = new LinkedBlockingQueue<LogMsgParserVO>();
LogMsgParserUtile pUtile;
public ParserFusion(){
AeraSchduler areaSc;
public ParserFusion(Queue<LogMsgParserVO> parserFusionQ){
this.parserFusionQ = parserFusionQ;
pUtile = new LogMsgParserUtile();
}
@ -31,7 +34,7 @@ public class ParserFusion {
this.logMsgs = recvMsgs;
List<FusionVO> parserList = new ArrayList<FusionVO>();
List<FusionVO> parserList;
FusionVO parserVO;
BoundingBox bBox;
@ -43,6 +46,8 @@ public class ParserFusion {
String sMsg = mv.getMessage();
parserList = new ArrayList<FusionVO>();
logVO = new LogMsgParserVO();
/*** 메시지 Pipe(|) 구분 ***/
@ -90,21 +95,20 @@ public class ParserFusion {
parserVO.setLon(split_Field[3]);
parserVO.setSpd(split_Field[4]);
parserVO.setCos(split_Field[5]);
parserVO.setAlt(split_Field[6]);
parserVO.setTrgt_ty(split_Field[7]);
parserVO.setSchdul_id(split_Field[8]);
parserVO.setTrgt_ty(split_Field[6]);
parserVO.setCrrct_lat(split_Field[7]);
parserVO.setCrrct_lon(split_Field[8]);
parserVO.setMode_s_cd(split_Field[9]);
parserVO.setSsr_cd(split_Field[10]);
parserVO.setClsgn(split_Field[11]);
parserVO.setTail_no(split_Field[12]);
parserVO.setCrrct_lat(split_Field[13]);
parserVO.setCrrct_lon(split_Field[14]);
parserVO.setIs_cntrlzone(split_Field[15]);
parserVO.setBbox(new ArrayList<BoundingBox>());
// bbox 담기
String[] split_List = pUtile.splitString(split_Field[17], pUtile.DIV_DOLLAR);
String[] split_List = pUtile.splitString(split_Field[13], pUtile.DIV_DOLLAR);
if(!split_List[0].equals("")) {
for(String loopList : split_List){
@ -123,6 +127,12 @@ public class ParserFusion {
}
}
parserVO.setAlt(split_Field[14]);
parserVO.setSchdul_id(split_Field[15]);
parserVO.setIs_cntrlzone(split_Field[16]);
parserList.add(parserVO);
}
/**** Data부 한줄씩 처리 END ****/
@ -131,15 +141,10 @@ public class ParserFusion {
/*** 메시지 data(body) 변환 END ***/
// Que에 파싱 데이터 담기
parserAiLocQ.offer(logVO) ;
parserFusionQ.offer(logVO) ;
} // for( ElasticResultMsgVO mv : logMsgs){... END
}
}

View File

@ -6,9 +6,9 @@ import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
import kr.gmtc.gw.elastic.utils.LogMsgParserUtile;
import kr.gmtc.gw.elastic.vo.ElasticMsgHeader;
import kr.gmtc.gw.elastic.vo.ElasticResultMsgVO;
import kr.gmtc.gw.elastic.vo.LogMsgParserVO;
import kr.gmtc.gw.elastic.vo.ElasticRecv.ElasticMsgHeader;
import kr.gmtc.gw.elastic.vo.ElasticRecv.ElasticResultMsgVO;
import kr.gmtc.gw.elastic.vo.ReplayLog.LogMsgParserVO;
import kr.gmtc.gw.elastic.vo.ReplayLog.StandardRouteVO;
import kr.gmtc.gw.elastic.vo.ReplayLog.StandardRouteVO.RoutePoints;

View File

@ -6,9 +6,9 @@ import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
import kr.gmtc.gw.elastic.utils.LogMsgParserUtile;
import kr.gmtc.gw.elastic.vo.ElasticMsgHeader;
import kr.gmtc.gw.elastic.vo.ElasticResultMsgVO;
import kr.gmtc.gw.elastic.vo.LogMsgParserVO;
import kr.gmtc.gw.elastic.vo.ElasticRecv.ElasticMsgHeader;
import kr.gmtc.gw.elastic.vo.ElasticRecv.ElasticResultMsgVO;
import kr.gmtc.gw.elastic.vo.ReplayLog.LogMsgParserVO;
import kr.gmtc.gw.elastic.vo.ReplayLog.StandStatusVO;
import kr.gmtc.gw.elastic.vo.ReplayLog.StandStatusVO.StandSttusTy;
import kr.gmtc.gw.elastic.vo.ReplayLog.StandardRouteVO.RoutePoints;

View File

@ -0,0 +1,47 @@
package kr.gmtc.gw.elastic.services;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import kr.gmtc.gw.elastic.mapper.AeraMapper;
import kr.gmtc.gw.elastic.vo.AnalyzeArea.Area;
@Service
public class AeraService {
@Autowired
private AeraMapper aeraMapper;
public List<HashMap<String, Object>> getAeraListMap() {
return aeraMapper.selectAeraListMap();
}
public List<Area> getAeraList() {
return aeraMapper.selectAeraList();
}
public Map<String, List<HashMap<String, Object>>> groupAreasByID(List<HashMap<String, Object>> areaList) {
Map<String, List<HashMap<String, Object>>> groupedAreas = new HashMap<>();
for (HashMap<String, Object> area : areaList) {
String areaId = (String) area.get("AREA_ID");
// 해당 지역 이름에 대한 맵 엔트리가 이미 있는지 확인하고, 없으면 새로운 리스트를 생성하여 추가합니다.
if (!groupedAreas.containsKey(areaId)) {
groupedAreas.put(areaId, new ArrayList<>());
}
// 해당 지역 이름에 해당하는 리스트를 가져와서 현재 지역 정보를 추가합니다.
groupedAreas.get(areaId).add(area);
}
return groupedAreas;
}
}

View File

@ -4,9 +4,11 @@ import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.SearchHits;
@ -16,12 +18,10 @@ import org.springframework.data.elasticsearch.core.query.Query;
import org.springframework.data.elasticsearch.core.query.StringQuery;
import org.springframework.stereotype.Service;
import kr.gmtc.gw.elastic.parser.logingIndex.ParserAade;
import kr.gmtc.gw.elastic.parser.replayLog.ParserAILocation;
import kr.gmtc.gw.elastic.parser.replayLog.ParserAna;
import kr.gmtc.gw.elastic.controller.AeraSchduler;
import kr.gmtc.gw.elastic.parser.replayLog.ParserFusion;
import kr.gmtc.gw.elastic.parser.replayLog.ParserRoute;
import kr.gmtc.gw.elastic.vo.ElasticResultMsgVO;
import kr.gmtc.gw.elastic.vo.ElasticRecv.ElasticResultMsgVO;
import kr.gmtc.gw.elastic.vo.ReplayLog.LogMsgParserVO;
@Service
public class ElkSearchService {
@ -41,7 +41,7 @@ public class ElkSearchService {
logMsgMatches = new ArrayList<ElasticResultMsgVO>();
//logParser = new ReplayLogParser_Route();
logParser = new ParserFusion();
//logParser = new ParserFusion(areaSc);
}
public String elkSearch_replay_log(String sLogType, String sStartDt, String sEndDt) {
@ -110,6 +110,73 @@ public class ElkSearchService {
return "OK";
}
public String searchFusion(Queue<LogMsgParserVO> parserFusionQ, String sLogType, String sStartDt, String sEndDt) {
ParserFusion psFusion = new ParserFusion(parserFusionQ);
List<Object> sAfter = null; // 일시(to)
//logMsgMatches = new ArrayList<ElasticResultMsgVO>();
String esQuery = "{ " + //
" \"bool\" : { " + //
" \"filter\" : [ " + //
" { \"terms\" : { " + //
" \"header.msg_type.keyword\" : [ " + //
" "+ sLogType +" ] } }, " + //
" { \"range\" : { " + //
" \"header.recv_time\" : { " + //
" \"from\" : \""+ sStartDt +"\", " + //
" \"to\" : \""+ sEndDt +"\" } } } ] } " + //
"}";
Query searchQuery = new StringQuery(esQuery);
// 한번에 가져올 row수 설정
((BaseQuery) searchQuery).setMaxResults(1000);
// 데이터 정렬할 필드 설정
searchQuery.addSort(Sort.by(new Sort.Order(Sort.Direction.ASC, "header.recv_time.keyword")));
LocalDateTime dt_before = LocalDateTime.now();
while (true) {
searchQuery.setSearchAfter(sAfter);
// 검색 요청하여 검색 결과 가져오기
SearchHits<ElasticResultMsgVO> searchHits = elasticsearchOperations.search(searchQuery, ElasticResultMsgVO.class, IndexCoordinates.of(INDEX_NAME));
if (searchHits.getTotalHits() <= 0) break;
Duration diff = Duration.between(dt_before, LocalDateTime.now());
logger.info("elastic Call " + searchHits.getTotalHits() + "건 " + diff.toMillis() + "msec");
sAfter = searchHits.toList().get(searchHits.toList().size() -1).getSortValues();
// IndexFusion Object에 데이터 담기
searchHits.forEach(srcHit -> {
logMsgMatches.add(srcHit.getContent());
});
logger.info("map cnt " + logMsgMatches.size() + "건 " );
if (searchHits.toList().size() != 1000) {
psFusion.logParser(logMsgMatches);
break;
}
}
return "OK";
}
}

View File

@ -12,7 +12,7 @@ import kr.gmtc.gw.elastic.services.ElkSearchService;
@RestController
@RequestMapping("/")
// @RequestMapping("/")
public class SearchController {
private ElkSearchService elkSearchService;
@ -23,9 +23,9 @@ public class SearchController {
this.elkSearchService = elkSearchService;
}
// http://localhost:8080/replay?idx=2&s=20240429145000.000&e=20240429145500.999
@GetMapping("/replay")
@ResponseBody
// http://localhost:8080/replay?idx=3&s=20240507145000.000&e=20240507145500.999
@GetMapping(value = "/replay")
// @ResponseBody
public String processSearch_replay_loop(@RequestParam(value = "idx", required = false) String sIndex,
@RequestParam(value = "s", required = false) String sStartDt,
@RequestParam(value = "e", required = false) String sEndDt) {

View File

@ -0,0 +1,52 @@
package kr.gmtc.gw.elastic.utils;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.util.AffineTransformation;
public class CommonUtils {
private static int ID_SEQ = 0;
public static String generateAnalysisID() {
ID_SEQ = (ID_SEQ >= 999) ? 0 : ID_SEQ+1;
String id = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS")) + String.format("%03d", ID_SEQ);
return id;
}
public static String getNow() {
return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss"));
}
public static String getNowWithMillsecond() {
return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss.SSS"));
}
public static double meterOnWGS84(double meter) {
return (1 * meter) / 111000;
}
public static Point rotatePoint(Point pointToRotate, Point rotationCenter, double angleInDegrees) {
AffineTransformation rotation = AffineTransformation.rotationInstance(
Math.toRadians(angleInDegrees), rotationCenter.getX(), rotationCenter.getY()
);
return (Point) rotation.transform(pointToRotate);
}
public static Coordinate rotatePoint(Coordinate pointToRotate, Coordinate rotationCenter, double angleInDegrees) {
//중심점을 기준으로 각도만큼 회전하는 변환을 생성. 양의 각도는 반시계 방향으로의 회전을 나타냄
AffineTransformation rotation = AffineTransformation.rotationInstance(
Math.toRadians( -1 * angleInDegrees), rotationCenter.x, rotationCenter.y
);
Coordinate dest = new Coordinate();
return rotation.transform(pointToRotate, dest);
}
}

View File

@ -0,0 +1,129 @@
package kr.gmtc.gw.elastic.vo.AnalyzeArea;
import java.util.List;
import org.locationtech.jts.algorithm.ConvexHull;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.LineString;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.Polygon;
import org.locationtech.jts.operation.buffer.BufferOp;
import org.locationtech.jts.operation.buffer.BufferParameters;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import kr.gmtc.gw.elastic.utils.CommonUtils;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class Area {
// private static final GeometryFactory gf = new GeometryFactory(
// new PrecisionModel(PrecisionModel.FLOATING),
// 4326,
// CoordinateArraySequenceFactory.instance());
private static final GeometryFactory gf = new GeometryFactory();
private static final Logger logger = LoggerFactory.getLogger(Area.class);
private boolean isValid = false;
private String id;
private String name;
private String areatype;
private Polygon polygon;
private List<AreaPoint> points;
private LineString line;
public int addPoint(AreaPoint ponit) {
try {
this.points.add(ponit);
return this.points.size();
} catch (NullPointerException ne) {
return -1;
} catch (RuntimeException re) {
return this.points.size();
}
}
public void generatePolygon() {
try {
this.isValid = false;
if (points.size() > 1) {
AreaPoint point = null;
Coordinate[] coords = new Coordinate[points.size()+1];
for (int i = 0; i < points.size(); i++) {
point = points.get(i);
if (point == null) {
return;
}
coords[i] = new Coordinate(point.getLon(), point.getLat());
}
coords[points.size()] = new Coordinate(coords[0].x, coords[0].y);
ConvexHull convexHull = new ConvexHull(coords, gf);
Geometry convexHullGeometry = convexHull.getConvexHull();
Coordinate[] sortedCoordinates = convexHullGeometry.getCoordinates();
this.polygon = gf.createPolygon(sortedCoordinates);
// LinearRing ring = gf.createLinearRing(coords);
// this.polygon = gf.createPolygon(ring);
this.isValid = true;
// logger.info("Generated Polygon ["+ this.name +"] : " + this.polygon);
}
} catch (RuntimeException e) {
logger.error("Polygon generated fail : ["+ this.id +"] "+ name, e);
}
}
public void generateLineToBufferedPolygon(double bufferMeter) {
try {
this.isValid = false;
Coordinate[] coords = this.points.stream()
.map(point -> new Coordinate(point.getLon(), point.getLat()))
.toArray(i -> new Coordinate[i]);
LineString line = gf.createLineString(coords);
this.line = gf.createLineString(coords);
Geometry buffer = BufferOp.bufferOp(line, CommonUtils.meterOnWGS84(bufferMeter), BufferParameters.CAP_SQUARE);
this.polygon = gf.createPolygon(buffer.getCoordinates());
this.isValid = true;
// logger.info("Taxiway buffered polygon info : "+ this.polygon);
} catch (RuntimeException e) {
logger.error("Line to Buffered Polygon generated fail : ["+ this.id +"] "+ name, e);
}
}
public boolean isContains(Point point) throws RuntimeException {
if (this.isValid == false) {
return false;
}
return this.polygon.contains(point);
}
public void generateBufferedPolygon(double bufferMeter) {
try {
generatePolygon();
this.isValid = false;
Geometry buffer = BufferOp.bufferOp(this.polygon, CommonUtils.meterOnWGS84(bufferMeter), BufferParameters.CAP_SQUARE);
this.polygon = gf.createPolygon(buffer.getCoordinates());
this.isValid = true;
} catch (RuntimeException e) {
logger.error("Buffered Polygon generated fail : ["+ this.id +"] "+ name, e);
}
}
}

View File

@ -0,0 +1,17 @@
package kr.gmtc.gw.elastic.vo.AnalyzeArea;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
public class AreaPoint {
private String areaID;
private int sn;
private double lon;
private double lat;
}

View File

@ -1,4 +1,4 @@
package kr.gmtc.gw.elastic.vo;
package kr.gmtc.gw.elastic.vo.ElasticRecv;
import lombok.Getter;
import lombok.Setter;

View File

@ -1,4 +1,4 @@
package kr.gmtc.gw.elastic.vo;
package kr.gmtc.gw.elastic.vo.ElasticRecv;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

View File

@ -1,7 +1,8 @@
package kr.gmtc.gw.elastic.vo;
package kr.gmtc.gw.elastic.vo.ReplayLog;
import java.util.List;
import kr.gmtc.gw.elastic.vo.ElasticRecv.ElasticMsgHeader;
import lombok.Getter;
import lombok.Setter;

View File

@ -11,6 +11,14 @@ spring:
activate:
on-profile: default
database:
db1:
datasource:
driver-class-name: com.tmax.tibero.jdbc.TbDriver
jdbcUrl: jdbc:tibero:thin:@10.200.31.1:8629:sacp
username: ucm
password: ucm
server:
port: 8080

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kr.gmtc.gw.elastic.mapper.AeraMapper">
<resultMap id="area" type="kr.gmtc.gw.elastic.vo.AnalyzeArea.Area" >
<result property="id" column="AREA_ID" />
<result property="name" column="AREA_NM" />
<result property="areatype" column="AREA_TY" />
<collection property="points" resultMap="point" />
</resultMap>
<resultMap id="point" type="kr.gmtc.gw.elastic.vo.AnalyzeArea.AreaPoint" >
<result property="sn" column="SPOT_SN" />
<result property="lon" column="LON" />
<result property="lat" column="LAT" />
</resultMap>
<select id="selectAeraListMap" resultType="hashMap">
SELECT M.AREA_ID, M.AREA_NM, M.AREA_TY,
ROW_NUMBER() OVER (PARTITION BY D.AREA_ID ORDER BY D.SPOT_SN) SPOT_SN ,
D.LON , D.LAT,
TO_CHAR(D.LON) AS LON_STR,
TO_CHAR(D.LAT) AS LAT_STR
FROM UCM.SACP_AREA_MASTR M,
UCM.SACP_AREA_DETAIL D
WHERE AREA_TY = 'AF07001'
AND AREA_NM NOT LIKE 'taxiway%'
AND AREA_NM NOT LIKE 'TaxiLine%'
AND M.AREA_ID = D.AREA_ID (+)
ORDER BY AREA_ID, SPOT_SN
</select>
<select id="selectAeraList" resultMap="area" >
SELECT M.AREA_ID, M.AREA_NM, M.AREA_TY,
ROW_NUMBER() OVER (PARTITION BY D.AREA_ID ORDER BY D.SPOT_SN) SPOT_SN ,
D.LON , D.LAT,
TO_CHAR(D.LON) AS LON_STR,
TO_CHAR(D.LAT) AS LAT_STR
FROM UCM.SACP_AREA_MASTR M,
UCM.SACP_AREA_DETAIL D
WHERE AREA_TY = 'AF07001'
AND AREA_NM NOT LIKE 'taxiway%'
AND AREA_NM NOT LIKE 'TaxiLine%'
AND M.AREA_ID = D.AREA_ID (+)
ORDER BY AREA_ID, SPOT_SN
</select>
</mapper>