지대한
7 months ago
22 changed files with 1023 additions and 42 deletions
@ -0,0 +1,16 @@
|
||||
package kr.co.palnet.kac.socket; |
||||
|
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.web.bind.annotation.GetMapping; |
||||
import org.springframework.web.bind.annotation.RequestMapping; |
||||
import org.springframework.web.bind.annotation.RestController; |
||||
|
||||
@RestController |
||||
@RequestMapping("/test") |
||||
public class TestController { |
||||
|
||||
@GetMapping("/ping") |
||||
public String test() { |
||||
return "pong"; |
||||
} |
||||
} |
@ -0,0 +1,8 @@
|
||||
package kr.co.palnet.kac.socket.core.command; |
||||
|
||||
import kr.co.palnet.kac.socket.core.model.DronRQ; |
||||
|
||||
public interface DronCommand { |
||||
void command(final DronRQ rq); |
||||
String getCommandName(); |
||||
} |
@ -0,0 +1,161 @@
|
||||
package kr.co.palnet.kac.socket.core.command.impl; |
||||
|
||||
import kr.co.palnet.kac.socket.core.model.ControlDto; |
||||
import kr.co.palnet.kac.socket.core.model.DronDTO; |
||||
import kr.co.palnet.kac.socket.core.model.DronHistoryDTO; |
||||
import kr.co.palnet.kac.socket.core.model.DronRQ; |
||||
import kr.co.palnet.kac.socket.core.command.DronCommand; |
||||
import kr.co.palnet.kac.socket.core.util.ControlCacheUtil; |
||||
import kr.co.palnet.kac.socket.core.util.DronCacheUtil; |
||||
import kr.co.palnet.kac.socket.core.util.DronUtil; |
||||
import kr.co.palnet.kac.socket.service.KacAppService; |
||||
import kr.co.palnet.kac.socket.service.WebSocketService; |
||||
import kr.co.palnet.kac.util.ObjectMapperUtils; |
||||
import lombok.RequiredArgsConstructor; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.beans.factory.annotation.Value; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
import java.io.IOException; |
||||
import java.net.URI; |
||||
import java.net.http.HttpClient; |
||||
import java.net.http.HttpRequest; |
||||
import java.net.http.HttpResponse; |
||||
import java.time.Instant; |
||||
import java.util.*; |
||||
|
||||
@Slf4j |
||||
@RequiredArgsConstructor |
||||
@Component |
||||
public class AdsbDronCommandImpl implements DronCommand { |
||||
|
||||
private final WebSocketService webSocketService; |
||||
private final KacAppService kacAppService; |
||||
|
||||
@Value("${app.kac-app.host}") |
||||
private String kacAppHost; |
||||
|
||||
|
||||
@Override |
||||
public String getCommandName() { |
||||
return "ADS-B"; |
||||
} |
||||
|
||||
@Override |
||||
public void command(DronRQ rq) { |
||||
log.info(">>>> AdsbCommandServiceImpl <<<<<"); |
||||
List<DronDTO> resultList = rq.getBody(); |
||||
|
||||
/** 전문 설정 ***/ |
||||
final String messageType = "LTEM"; |
||||
final String objectType = "DRON"; |
||||
|
||||
/** 데이터 모델링 **/ |
||||
for (DronDTO dron : resultList) { |
||||
// 위,경도 좌표가 0으로 들어오는 것은 무시 처리
|
||||
if (DronUtil.latlonCheck(dron.getLat(), dron.getLon())) { |
||||
|
||||
dron.setObjectType(objectType); |
||||
dron.setMessageType(messageType); |
||||
dron.setTerminalId(rq.getTerminalId()); |
||||
dron.setRegDt(Instant.now()); |
||||
|
||||
// 서버 수신 시간 정보
|
||||
dron.setServerRcvDt(Instant.now()); |
||||
|
||||
// 관제 이력 정보
|
||||
List<DronHistoryDTO> hisList; |
||||
|
||||
DronHistoryDTO history = DronHistoryDTO.builder() |
||||
.objectId(dron.getObjectId()) |
||||
.lat(dron.getLat()) |
||||
.lon(dron.getLon()) |
||||
.build(); |
||||
|
||||
if (dron.getPostionHistory() != null) { |
||||
hisList = dron.getPostionHistory(); |
||||
} else { |
||||
hisList = new ArrayList<>(); |
||||
} |
||||
|
||||
hisList.add(history); |
||||
dron.setPostionHistory(hisList); |
||||
|
||||
|
||||
// STEP 1. 전에 내부 메모리에서 controlId 조회
|
||||
ControlCacheUtil controlCacheUtil = ControlCacheUtil.getInstance(); |
||||
ControlDto dronCacheDTO = controlCacheUtil.get(dron.getObjectId()); |
||||
|
||||
if (dronCacheDTO == null) { |
||||
// STEP 1. Control ID 발급 -> Application Server Http 통신
|
||||
try { |
||||
// TODO 분리
|
||||
HttpRequest request = HttpRequest.newBuilder() |
||||
.uri(new URI( |
||||
kacAppHost + "/api/ctr/cntrl/id/" + dron.getObjectId() |
||||
)) |
||||
.version(HttpClient.Version.HTTP_2) |
||||
.GET() |
||||
.build(); |
||||
|
||||
HttpResponse<String> response = HttpClient |
||||
.newHttpClient() |
||||
.send(request, HttpResponse.BodyHandlers.ofString()); |
||||
|
||||
log.debug("CONTROL ID RESPONSE : {}", response.body()); |
||||
|
||||
Map body = ObjectMapperUtils.getObjectMapper().readValue(response.body(), HashMap.class); |
||||
|
||||
Map data = (Map) body.get("data"); |
||||
dron.setControlId((String) data.get("controlId")); |
||||
dron.setTypeCd((String) data.get("typeCd")); |
||||
dron.setAreaTrnsYn((String) data.get("areaTrnsYn")); |
||||
dron.setControlStartDt(Instant.now()); |
||||
|
||||
ControlDto controlDto = new ControlDto(); |
||||
controlDto.setControlId((String) data.get("controlId")); |
||||
controlDto.setTypeCd((String) data.get("typeCd")); |
||||
controlDto.setAreaTrnsYn((String) data.get("areaTrnsYn")); |
||||
controlDto.setRegTime(System.currentTimeMillis()); |
||||
|
||||
ControlDto newDronCacheDTO = ControlDto.builder().build(); |
||||
controlCacheUtil.set(dron.getObjectId(), newDronCacheDTO); |
||||
|
||||
} catch (IOException e) { |
||||
log.error("요청한 URL 정보가 잘못되었습니다.", e.getMessage()); |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
} |
||||
|
||||
} else { |
||||
dron.setControlId(dronCacheDTO.getControlId()); |
||||
dron.setTypeCd("02"); |
||||
dron.setAreaTrnsYn(dronCacheDTO.getAreaTrnsYn()); |
||||
dron.setControlWarnCd(dronCacheDTO.isControlWarnCd()); |
||||
dronCacheDTO.setRegTime(System.currentTimeMillis()); |
||||
|
||||
controlCacheUtil.set(dron.getObjectId(), dronCacheDTO); |
||||
} |
||||
// STEP 2. 이력 생성할 전문 전달 -> DRON의 대한 식별정보만 이력 관리
|
||||
try { |
||||
// 저장 해 놓았다가 한거번에 전송
|
||||
DronCacheUtil dronCacheUtil = DronCacheUtil.getInstance(); |
||||
dronCacheUtil.set(dron); |
||||
} catch (Exception e) { |
||||
log.error("ERROR : {}\n{}", e.getMessage(), e.getStackTrace()); |
||||
} |
||||
|
||||
// STEP 3. 화면에 표출할 정보 WebSocket 전달
|
||||
if ("PA".equals(dron.getObjectId().substring(0, 2))) { |
||||
webSocketService.sendData(dron); |
||||
} |
||||
|
||||
} else { |
||||
log.error("좌표 정보가 존재하지 않습니다."); |
||||
throw new IllegalArgumentException("좌표 정보가 존재하지 않습니다."); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,159 @@
|
||||
package kr.co.palnet.kac.socket.core.command.impl; |
||||
|
||||
import kr.co.palnet.kac.socket.core.model.ControlDto; |
||||
import kr.co.palnet.kac.socket.core.model.DronDTO; |
||||
import kr.co.palnet.kac.socket.core.model.DronHistoryDTO; |
||||
import kr.co.palnet.kac.socket.core.model.DronRQ; |
||||
import kr.co.palnet.kac.socket.core.command.DronCommand; |
||||
import kr.co.palnet.kac.socket.core.util.ControlCacheUtil; |
||||
import kr.co.palnet.kac.socket.core.util.DronCacheUtil; |
||||
import kr.co.palnet.kac.socket.core.util.DronUtil; |
||||
import kr.co.palnet.kac.socket.service.KacAppService; |
||||
import kr.co.palnet.kac.socket.service.WebSocketService; |
||||
import kr.co.palnet.kac.util.ObjectMapperUtils; |
||||
import lombok.RequiredArgsConstructor; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.beans.factory.annotation.Value; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
import java.io.IOException; |
||||
import java.net.URI; |
||||
import java.net.http.HttpClient; |
||||
import java.net.http.HttpRequest; |
||||
import java.net.http.HttpResponse; |
||||
import java.time.Instant; |
||||
import java.util.*; |
||||
|
||||
@Slf4j |
||||
@RequiredArgsConstructor |
||||
@Component |
||||
public class AntosDronCommandImpl implements DronCommand { |
||||
|
||||
private final WebSocketService webSocketService; |
||||
private final KacAppService kacAppService; |
||||
|
||||
@Value("${app.kac-app.host}") |
||||
private String kacAppHost; |
||||
|
||||
@Override |
||||
public String getCommandName() { |
||||
return "ANTOS"; |
||||
} |
||||
|
||||
@Override |
||||
public void command(DronRQ rq) { |
||||
log.info(">>>> AntosCommandServiceImpl <<<<<"); |
||||
List<DronDTO> resultList = rq.getBody(); |
||||
|
||||
/** 전문 설정 ***/ |
||||
final String messageType = "LTEM"; |
||||
final String objectType = "DRON"; |
||||
|
||||
/** 데이터 모델링 **/ |
||||
for (DronDTO dron : resultList) { |
||||
// 위,경도 좌표가 0으로 들어오는 것은 무시 처리
|
||||
if (DronUtil.latlonCheck(dron.getLat(), dron.getLon())) { |
||||
|
||||
dron.setObjectType(objectType); |
||||
dron.setMessageType(messageType); |
||||
dron.setTerminalId(rq.getTerminalId()); |
||||
dron.setRegDt(Instant.now()); |
||||
|
||||
// 서버 수신 시간 정보
|
||||
dron.setServerRcvDt(Instant.now()); |
||||
|
||||
// 관제 이력 정보
|
||||
List<DronHistoryDTO> hisList; |
||||
|
||||
DronHistoryDTO history = DronHistoryDTO.builder() |
||||
.objectId(dron.getObjectId()) |
||||
.lat(dron.getLat()) |
||||
.lon(dron.getLon()) |
||||
.build(); |
||||
|
||||
if (dron.getPostionHistory() != null) { |
||||
hisList = dron.getPostionHistory(); |
||||
} else { |
||||
hisList = new ArrayList<>(); |
||||
} |
||||
|
||||
hisList.add(history); |
||||
dron.setPostionHistory(hisList); |
||||
|
||||
|
||||
// STEP 1. 전에 내부 메모리에서 controlId 조회
|
||||
ControlCacheUtil controlCacheUtil = ControlCacheUtil.getInstance(); |
||||
ControlDto dronCacheDTO = controlCacheUtil.get(dron.getObjectId()); |
||||
|
||||
if (dronCacheDTO == null) { |
||||
// STEP 1. Control ID 발급 -> Application Server Http 통신
|
||||
try { |
||||
HttpRequest request = HttpRequest.newBuilder() |
||||
.uri(new URI( |
||||
kacAppHost + "/api/ctr/cntrl/id/" + dron.getObjectId() |
||||
)) |
||||
.version(HttpClient.Version.HTTP_2) |
||||
.GET() |
||||
.build(); |
||||
|
||||
HttpResponse<String> response = HttpClient |
||||
.newHttpClient() |
||||
.send(request, HttpResponse.BodyHandlers.ofString()); |
||||
|
||||
log.debug("CONTROL ID RESPONSE : {}", response.body()); |
||||
|
||||
Map body = ObjectMapperUtils.getObjectMapper().readValue(response.body(), HashMap.class); |
||||
|
||||
Map data = (Map) body.get("data"); |
||||
dron.setControlId((String) data.get("controlId")); |
||||
dron.setTypeCd((String) data.get("typeCd")); |
||||
dron.setAreaTrnsYn((String) data.get("areaTrnsYn")); |
||||
dron.setControlStartDt(Instant.now()); |
||||
|
||||
ControlDto controlDto = new ControlDto(); |
||||
controlDto.setControlId((String) data.get("controlId")); |
||||
controlDto.setTypeCd((String) data.get("typeCd")); |
||||
controlDto.setAreaTrnsYn((String) data.get("areaTrnsYn")); |
||||
controlDto.setRegTime(System.currentTimeMillis()); |
||||
|
||||
ControlDto newDronCacheDTO = ControlDto.builder().build(); |
||||
controlCacheUtil.set(dron.getObjectId(), newDronCacheDTO); |
||||
|
||||
} catch (IOException e) { |
||||
log.error("요청한 URL 정보가 잘못되었습니다.", e.getMessage()); |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
} |
||||
|
||||
} else { |
||||
dron.setControlId(dronCacheDTO.getControlId()); |
||||
dron.setTypeCd("02"); |
||||
dron.setAreaTrnsYn(dronCacheDTO.getAreaTrnsYn()); |
||||
dron.setControlWarnCd(dronCacheDTO.isControlWarnCd()); |
||||
dronCacheDTO.setRegTime(System.currentTimeMillis()); |
||||
|
||||
controlCacheUtil.set(dron.getObjectId(), dronCacheDTO); |
||||
} |
||||
// STEP 2. 이력 생성할 전문 전달 -> DRON의 대한 식별정보만 이력 관리
|
||||
try { |
||||
// 저장 해 놓았다가 한거번에 전송
|
||||
DronCacheUtil dronCacheUtil = DronCacheUtil.getInstance(); |
||||
dronCacheUtil.set(dron); |
||||
} catch (Exception e) { |
||||
log.error("ERROR : {}\n{}", e.getMessage(), e.getStackTrace()); |
||||
} |
||||
|
||||
|
||||
|
||||
// STEP 3. 화면에 표출할 정보 WebSocket 전달
|
||||
if ("PA".equals(dron.getObjectId().substring(0, 2))) { |
||||
webSocketService.sendData(dron); |
||||
} |
||||
|
||||
} else { |
||||
log.error("좌표 정보가 존재하지 않습니다."); |
||||
throw new IllegalArgumentException("좌표 정보가 존재하지 않습니다."); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,166 @@
|
||||
package kr.co.palnet.kac.socket.core.command.impl; |
||||
|
||||
import kr.co.palnet.kac.socket.core.command.DronCommand; |
||||
import kr.co.palnet.kac.socket.core.model.ControlDto; |
||||
import kr.co.palnet.kac.socket.core.model.DronDTO; |
||||
import kr.co.palnet.kac.socket.core.model.DronHistoryDTO; |
||||
import kr.co.palnet.kac.socket.core.model.DronRQ; |
||||
import kr.co.palnet.kac.socket.core.util.ControlCacheUtil; |
||||
import kr.co.palnet.kac.socket.core.util.DronCacheUtil; |
||||
import kr.co.palnet.kac.socket.core.util.DronUtil; |
||||
import kr.co.palnet.kac.socket.service.KacAppService; |
||||
import kr.co.palnet.kac.socket.service.WebSocketService; |
||||
import kr.co.palnet.kac.util.ObjectMapperUtils; |
||||
import lombok.RequiredArgsConstructor; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.beans.factory.annotation.Value; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
import java.io.IOException; |
||||
import java.net.URI; |
||||
import java.net.http.HttpClient; |
||||
import java.net.http.HttpRequest; |
||||
import java.net.http.HttpResponse; |
||||
import java.time.Instant; |
||||
import java.util.ArrayList; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
@Slf4j |
||||
@RequiredArgsConstructor |
||||
@Component |
||||
public class SandboxDronCommandImpl implements DronCommand { |
||||
|
||||
private final WebSocketService webSocketService; |
||||
private final KacAppService kacAppService; |
||||
|
||||
@Value("${app.kac-app.host}") |
||||
private String kacAppHost; |
||||
|
||||
@Override |
||||
public String getCommandName() { |
||||
return "SANDBOX"; |
||||
} |
||||
|
||||
@Override |
||||
public void command(DronRQ rq) { |
||||
log.info(">>>> SandboxCommandServiceImpl <<<<<"); |
||||
List<DronDTO> resultList = rq.getBody(); |
||||
/** 전문 설정 ***/ |
||||
final String messageType = "LTEM"; |
||||
final String objectType = "DRON"; |
||||
|
||||
/** 데이터 모델링 **/ |
||||
for (DronDTO dron : resultList) { |
||||
// 위,경도 좌표가 0으로 들어오는 것은 무시 처리
|
||||
if (DronUtil.latlonCheck(dron.getLat(), dron.getLon())) { |
||||
|
||||
dron.setObjectType(objectType); |
||||
dron.setMessageType(messageType); |
||||
dron.setTerminalId(rq.getTerminalId()); |
||||
dron.setRegDt(Instant.now()); |
||||
|
||||
// 서버 수신 시간 정보
|
||||
dron.setServerRcvDt(Instant.now()); |
||||
|
||||
// 관제 이력 정보
|
||||
List<DronHistoryDTO> hisList; |
||||
|
||||
DronHistoryDTO history = DronHistoryDTO.builder() |
||||
.objectId(dron.getObjectId()) |
||||
.lat(dron.getLat()) |
||||
.lon(dron.getLon()) |
||||
.build(); |
||||
|
||||
if (dron.getPostionHistory() != null) { |
||||
hisList = dron.getPostionHistory(); |
||||
} else { |
||||
hisList = new ArrayList<>(); |
||||
} |
||||
|
||||
hisList.add(history); |
||||
dron.setPostionHistory(hisList); |
||||
|
||||
Long start = System.currentTimeMillis(); |
||||
|
||||
// STEP 1. 전에 내부 메모리에서 controlId 조회
|
||||
ControlCacheUtil controlCacheUtil = ControlCacheUtil.getInstance(); |
||||
ControlDto dronCacheDTO = controlCacheUtil.get(dron.getObjectId()); |
||||
|
||||
if (dronCacheDTO == null) { |
||||
// STEP 1. Control ID 발급 -> Application Server Http 통신
|
||||
try { |
||||
// TODO 분리
|
||||
HttpRequest request = HttpRequest.newBuilder() |
||||
.uri(new URI( |
||||
kacAppHost + "/api/ctr/cntrl/id/" + dron.getObjectId() |
||||
)) |
||||
.version(HttpClient.Version.HTTP_2) |
||||
.GET() |
||||
.build(); |
||||
|
||||
HttpResponse<String> response = HttpClient |
||||
.newHttpClient() |
||||
.send(request, HttpResponse.BodyHandlers.ofString()); |
||||
|
||||
log.debug("CONTROL ID RESPONSE : {}", response.body()); |
||||
|
||||
Map body = ObjectMapperUtils.getObjectMapper().readValue(response.body(), HashMap.class); |
||||
|
||||
Map data = (Map) body.get("data"); |
||||
dron.setControlId((String) data.get("controlId")); |
||||
dron.setTypeCd((String) data.get("typeCd")); |
||||
dron.setAreaTrnsYn((String) data.get("areaTrnsYn")); |
||||
dron.setControlStartDt(Instant.now()); |
||||
|
||||
ControlDto controlDto = new ControlDto(); |
||||
controlDto.setControlId((String) data.get("controlId")); |
||||
controlDto.setTypeCd((String) data.get("typeCd")); |
||||
controlDto.setAreaTrnsYn((String) data.get("areaTrnsYn")); |
||||
controlDto.setRegTime(System.currentTimeMillis()); |
||||
|
||||
ControlDto newDronCacheDTO = ControlDto.builder().build(); |
||||
controlCacheUtil.set(dron.getObjectId(), newDronCacheDTO); |
||||
|
||||
} catch (IOException e) { |
||||
log.error("요청한 URL 정보가 잘못되었습니다.", e.getMessage()); |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
} |
||||
|
||||
} else { |
||||
dron.setControlId(dronCacheDTO.getControlId()); |
||||
dron.setTypeCd("02"); |
||||
dron.setAreaTrnsYn(dronCacheDTO.getAreaTrnsYn()); |
||||
dron.setControlWarnCd(dronCacheDTO.isControlWarnCd()); |
||||
dronCacheDTO.setRegTime(System.currentTimeMillis()); |
||||
|
||||
controlCacheUtil.set(dron.getObjectId(), dronCacheDTO); |
||||
} |
||||
|
||||
|
||||
|
||||
// STEP 2. 이력 생성할 전문 전달 -> DRON의 대한 식별정보만 이력 관리
|
||||
try { |
||||
// 저장 해 놓았다가 한거번에 전송
|
||||
DronCacheUtil dronCacheUtil = DronCacheUtil.getInstance(); |
||||
// dronCacheUtil.set(dron);
|
||||
} catch (Exception e) { |
||||
log.error("ERROR : {}\n{}", e.getMessage(), e.getStackTrace()); |
||||
} |
||||
|
||||
// STEP 3. 화면에 표출할 정보 WebSocket 전달
|
||||
// webSocketService.sendData(dron);
|
||||
|
||||
Long end = System.currentTimeMillis(); |
||||
log.info(">>> during time : {}::{}", dron.getObjectId(),end - start); |
||||
|
||||
} else { |
||||
log.error("좌표 정보가 존재하지 않습니다."); |
||||
throw new IllegalArgumentException("좌표 정보가 존재하지 않습니다."); |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
@ -1,44 +1,109 @@
|
||||
package kr.co.palnet.kac.socket.core.handler; |
||||
|
||||
import io.netty.buffer.ByteBuf; |
||||
import io.netty.channel.*; |
||||
import kr.co.palnet.kac.socket.core.codec.DronPayload; |
||||
import lombok.RequiredArgsConstructor; |
||||
import io.netty.channel.ChannelHandler; |
||||
import io.netty.channel.ChannelHandlerContext; |
||||
import io.netty.channel.SimpleChannelInboundHandler; |
||||
import kr.co.palnet.kac.socket.core.command.DronCommand; |
||||
import kr.co.palnet.kac.socket.core.model.DronRQ; |
||||
import kr.co.palnet.kac.socket.core.model.DronRS; |
||||
import kr.co.palnet.kac.socket.core.util.AuthKeyUtil; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
@Slf4j |
||||
@RequiredArgsConstructor |
||||
@ChannelHandler.Sharable |
||||
@Component |
||||
public class DronSocketHandler extends SimpleChannelInboundHandler<DronPayload> { |
||||
public class DronSocketHandler extends SimpleChannelInboundHandler<DronRQ> { |
||||
|
||||
@Override |
||||
protected void channelRead0(ChannelHandlerContext ctx, DronPayload msg) throws Exception { |
||||
log.info(">>>> channelRead0 <<<<<"); |
||||
log.info("Received0 JSON: " + msg.toString()); |
||||
ctx.writeAndFlush(msg); |
||||
private final Map<String, DronCommand> commandMap; |
||||
|
||||
|
||||
public DronSocketHandler(List<DronCommand> commandList) { |
||||
commandMap = new HashMap<>(); |
||||
for (DronCommand command : commandList) { |
||||
commandMap.put(command.getCommandName(), command); |
||||
} |
||||
} |
||||
|
||||
// 클라이언트와 연결되어 트래픽을 생성할 준비가 되었을 때 호출되는 메소드
|
||||
//
|
||||
@Override |
||||
public void channelActive(ChannelHandlerContext ctx) { |
||||
log.info(">>>> channelActive <<<<<"); |
||||
String remoteAddress = ctx.channel().remoteAddress().toString(); |
||||
log.info("Remote Address: " + remoteAddress); |
||||
// ctx.writeAndFlush("success");
|
||||
} |
||||
protected void channelRead0(ChannelHandlerContext ctx, DronRQ rq) throws Exception { |
||||
log.info(">>>> channelRead0 <<<<<"); |
||||
// key 검사
|
||||
if (rq == null) { |
||||
ctx.writeAndFlush(DronRS.builder() |
||||
.code("-1000") |
||||
.message("data is empty.") |
||||
.build()); |
||||
return; |
||||
} |
||||
|
||||
if (rq.getCommand() == null || rq.getCommand().isEmpty()) { |
||||
ctx.writeAndFlush(DronRS.builder() |
||||
.code("-1001") |
||||
.message("command is empty.") |
||||
.build()); |
||||
return; |
||||
} |
||||
|
||||
if (rq.getAuthKey() == null || rq.getAuthKey().isEmpty()) { |
||||
ctx.writeAndFlush(DronRS.builder() |
||||
.code("-2000") |
||||
.message("auth key is empty.") |
||||
.build()); |
||||
return; |
||||
} |
||||
|
||||
if (AuthKeyUtil.getInstance().checkAuthKey(rq.getCommand())) { |
||||
ctx.writeAndFlush(DronRS.builder() |
||||
.code("-2000") |
||||
.message("Invalid auth key.") |
||||
.build()); |
||||
return; |
||||
} |
||||
|
||||
log.info(">>> rq : {}", rq); |
||||
DronCommand commandService = commandMap.get(rq.getCommand().trim()); |
||||
if (commandService == null) { |
||||
ctx.writeAndFlush(DronRS.builder() |
||||
.code("-2100") |
||||
.message("this command is not exist.") |
||||
.build()); |
||||
return; |
||||
} |
||||
try { |
||||
commandService.command(rq); |
||||
} catch (Exception e) { |
||||
ctx.writeAndFlush(DronRS.builder() |
||||
.code("-500") |
||||
.message("server error - execute command") |
||||
.build()); |
||||
return; |
||||
} |
||||
ctx.writeAndFlush(DronRS.builder() |
||||
.code("0") |
||||
.message("success") |
||||
.build()); |
||||
} |
||||
|
||||
// 에러 처리
|
||||
@Override |
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { |
||||
log.info(">>>> exceptionCaught <<<<<"); |
||||
DronRS rs = DronRS.builder() |
||||
.code("-9999") |
||||
.message("error - etc") |
||||
.build(); |
||||
|
||||
ctx.writeAndFlush(rs); |
||||
// Close the connection when an exception is raised.
|
||||
ctx.close(); |
||||
cause.printStackTrace(); |
||||
log.error("ERROR: {}\n{}", cause.getMessage(), cause.getStackTrace()); |
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
} |
||||
|
@ -0,0 +1,18 @@
|
||||
package kr.co.palnet.kac.socket.core.model; |
||||
|
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Builder; |
||||
import lombok.Data; |
||||
import lombok.NoArgsConstructor; |
||||
|
||||
@Data |
||||
@NoArgsConstructor |
||||
@AllArgsConstructor |
||||
@Builder |
||||
public class ControlDto { |
||||
private String controlId; |
||||
private String typeCd; |
||||
private String areaTrnsYn; |
||||
private boolean controlWarnCd; |
||||
private Long regTime; |
||||
} |
@ -0,0 +1,97 @@
|
||||
package kr.co.palnet.kac.socket.core.model; |
||||
|
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Builder; |
||||
import lombok.Data; |
||||
import lombok.NoArgsConstructor; |
||||
|
||||
import java.time.Instant; |
||||
import java.time.LocalDateTime; |
||||
import java.util.List; |
||||
|
||||
@Data |
||||
@NoArgsConstructor |
||||
@AllArgsConstructor |
||||
@Builder |
||||
public class DronDTO { |
||||
private String typeCd; // 01 : 최초 들어온 데이터 , 99 : 종료 시킬 데이터
|
||||
|
||||
private String messageType; |
||||
|
||||
private String terminalId; |
||||
|
||||
@Builder.Default |
||||
private Double moveDistance = 0.0; |
||||
|
||||
private String moveDistanceType; |
||||
|
||||
private String controlId; // 처음 위치 데이터가 들어 왔을때 생성 함
|
||||
|
||||
private String objectType; |
||||
|
||||
private String objectId; |
||||
|
||||
@Builder.Default |
||||
private Double lat = 0.0; |
||||
|
||||
@Builder.Default |
||||
private Double lon = 0.0; |
||||
|
||||
private String elevType; |
||||
|
||||
@Builder.Default |
||||
private Double elev = 0.0; |
||||
|
||||
private String speedType; |
||||
|
||||
@Builder.Default |
||||
private Double speed = 0.0; |
||||
|
||||
@Builder.Default |
||||
private Double betteryLevel = 0.0; |
||||
|
||||
@Builder.Default |
||||
private Double betteryVoltage = 0.0; |
||||
|
||||
private String dronStatus; |
||||
|
||||
@Builder.Default |
||||
private Double heading = 0.0; |
||||
|
||||
private String terminalRcvDt; |
||||
|
||||
private Instant serverRcvDt; |
||||
|
||||
private Instant controlStartDt; |
||||
|
||||
private Instant controlEndDt; |
||||
|
||||
private String areaTrnsYn; |
||||
|
||||
// 환경센서 필드
|
||||
@Builder.Default |
||||
private Double sensorCo = 0.0; |
||||
@Builder.Default |
||||
private Double sensorSo2 = 0.0; |
||||
@Builder.Default |
||||
private Double sensorNo2 = 0.0; |
||||
@Builder.Default |
||||
private Double sensorO3 = 0.0; |
||||
@Builder.Default |
||||
private Double sensorDust = 0.0; |
||||
|
||||
//최근 5건만 저장
|
||||
private List<DronHistoryDTO> recentPositionHistory; |
||||
|
||||
// 전체 히스토리 저장
|
||||
private List<DronHistoryDTO> postionHistory; |
||||
|
||||
// 비정상 상황 식별 코드
|
||||
private boolean controlWarnCd; |
||||
|
||||
// 큐가 Socket서버에 도착한 시간
|
||||
private Instant regDt; |
||||
// 큐가 Socket서버에 도착한 시간
|
||||
private boolean sendUtm; // 불법드론 전송 여부
|
||||
|
||||
} |
@ -0,0 +1,20 @@
|
||||
package kr.co.palnet.kac.socket.core.model; |
||||
|
||||
|
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Builder; |
||||
import lombok.Data; |
||||
import lombok.NoArgsConstructor; |
||||
|
||||
@Data |
||||
@NoArgsConstructor |
||||
@AllArgsConstructor |
||||
@Builder |
||||
public class DronHistoryDTO { |
||||
private String objectId; |
||||
|
||||
@Builder.Default |
||||
private Double lat = 0.0; |
||||
@Builder.Default |
||||
private Double lon = 0.0; |
||||
} |
@ -0,0 +1,15 @@
|
||||
package kr.co.palnet.kac.socket.core.model; |
||||
|
||||
import lombok.AllArgsConstructor; |
||||
import lombok.Builder; |
||||
import lombok.Data; |
||||
import lombok.NoArgsConstructor; |
||||
|
||||
@Data |
||||
@NoArgsConstructor |
||||
@AllArgsConstructor |
||||
@Builder |
||||
public class DronRS { |
||||
private String code; |
||||
private String message; |
||||
} |
@ -0,0 +1,59 @@
|
||||
package kr.co.palnet.kac.socket.core.util; |
||||
|
||||
import lombok.Getter; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
|
||||
import java.util.HashSet; |
||||
import java.util.Set; |
||||
|
||||
@Slf4j |
||||
public class AuthKeyUtil { |
||||
|
||||
private Set<String> keys = new HashSet<>(); |
||||
|
||||
private AuthKeyUtil() { |
||||
log.debug("AuthKeyUtil : init keys"); |
||||
initKey(); |
||||
} |
||||
|
||||
public static AuthKeyUtil getInstance() { |
||||
return LazyHolder.INSTANCE; |
||||
} |
||||
|
||||
public static class LazyHolder { |
||||
private static final AuthKeyUtil INSTANCE = new AuthKeyUtil(); |
||||
} |
||||
|
||||
private void initKey() { |
||||
keys.add("1cc2e08e-0c5c-43b2-8d4d-cddd3de558e3");// 지텔인증키
|
||||
keys.add("35ea4080-a3f2-4e34-8361-78db06bac6fc");// PAL 인증키
|
||||
keys.add("4d244c0a-6cf5-4d57-ae48-331a71010c3d");// ADS-B
|
||||
} |
||||
|
||||
public boolean checkAuthKey(String authKey) { |
||||
// keys에서 authKey와 동일한 값이 잇으면 true반환
|
||||
return keys.contains(authKey); |
||||
} |
||||
|
||||
public boolean addKey(String authKey) { |
||||
try { |
||||
return keys.add(authKey); |
||||
} catch (Exception e) { |
||||
log.debug("fail add key."); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
public boolean removeKey(String authKey) { |
||||
try { |
||||
if (keys.contains(authKey)) { |
||||
return keys.remove(authKey); |
||||
} |
||||
} catch (Exception e) { |
||||
log.debug("fail remove key."); |
||||
return false; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,53 @@
|
||||
package kr.co.palnet.kac.socket.core.util; |
||||
|
||||
import kr.co.palnet.kac.socket.core.model.ControlDto; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.scheduling.annotation.Scheduled; |
||||
|
||||
import java.util.Map; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
|
||||
@Slf4j |
||||
public class ControlCacheUtil { |
||||
|
||||
private final Map<String, ControlDto> controlMap; |
||||
|
||||
private final int REMOVE_TIME = 1000 * 10; |
||||
|
||||
private ControlCacheUtil() { |
||||
controlMap = new ConcurrentHashMap<>(); |
||||
} |
||||
|
||||
public static ControlCacheUtil getInstance() { |
||||
return LazyHolder.INSTANCE; |
||||
} |
||||
|
||||
public static class LazyHolder { |
||||
private static final ControlCacheUtil INSTANCE = new ControlCacheUtil(); |
||||
} |
||||
|
||||
public ControlDto get(String objectId) { |
||||
return controlMap.get(objectId); |
||||
} |
||||
|
||||
public ControlDto set(String objectId, ControlDto control) { |
||||
return controlMap.put(objectId, control); |
||||
} |
||||
|
||||
public ControlDto remove(String objectId) { |
||||
return controlMap.remove(objectId); |
||||
} |
||||
|
||||
// TODO scheduler 테스트 필요(현재 Bean등록 안함)
|
||||
@Scheduled(fixedDelay = 1000 * 10) |
||||
public void remove() { |
||||
for (String key : controlMap.keySet()) { |
||||
ControlDto dronCacheDTO = controlMap.get(key); |
||||
long diff = System.currentTimeMillis() - dronCacheDTO.getRegTime(); |
||||
if(diff > REMOVE_TIME){ |
||||
remove(key); |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,84 @@
|
||||
package kr.co.palnet.kac.socket.core.util; |
||||
|
||||
import kr.co.palnet.kac.socket.core.model.ControlDto; |
||||
import kr.co.palnet.kac.socket.core.model.DronDTO; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.scheduling.annotation.Scheduled; |
||||
|
||||
import java.time.Instant; |
||||
import java.util.ArrayList; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
|
||||
@Slf4j |
||||
public class DronCacheUtil { |
||||
|
||||
private final Map<String, List<DronDTO>> dronMap; |
||||
|
||||
private final int REMOVE_TIME = 1000 * 10; |
||||
|
||||
private DronCacheUtil() { |
||||
dronMap = new ConcurrentHashMap<>(); |
||||
} |
||||
|
||||
public static DronCacheUtil getInstance() { |
||||
return LazyHolder.INSTANCE; |
||||
} |
||||
|
||||
public static class LazyHolder { |
||||
private static final DronCacheUtil INSTANCE = new DronCacheUtil(); |
||||
} |
||||
|
||||
public Map<String, List<DronDTO>> getAll() { |
||||
if (dronMap.keySet().isEmpty()) { |
||||
return null; |
||||
} |
||||
return dronMap; |
||||
} |
||||
|
||||
public List<DronDTO> get(String objectId) { |
||||
if (objectId == null || objectId.isEmpty()) { |
||||
return null; |
||||
} |
||||
if (dronMap.get(objectId) == null) { |
||||
return null; |
||||
} |
||||
return dronMap.get(objectId); |
||||
} |
||||
|
||||
public void set(DronDTO dron) { |
||||
if (dron == null || dron.getObjectId() == null || dron.getObjectId().isEmpty()) { |
||||
return; |
||||
} |
||||
|
||||
List<DronDTO> list = dronMap.get(dron.getObjectId()); |
||||
|
||||
if (list == null) { |
||||
list = new ArrayList<>(); |
||||
} |
||||
list.add(dron); |
||||
dronMap.put(dron.getObjectId(), list); |
||||
} |
||||
|
||||
|
||||
public void removeScheduled() { |
||||
log.info("removeScheduled start - dronMap size : {}", dronMap.size()); |
||||
for (String key : dronMap.keySet()) { |
||||
List<DronDTO> list = dronMap.get(key); |
||||
if (list == null || list.isEmpty()) { |
||||
continue; |
||||
} |
||||
DronDTO dron = list.get(list.size() - 1); |
||||
// 1분 이상된 데이터 삭제
|
||||
Instant compareTime = Instant.now().minusSeconds(60); |
||||
if (compareTime.isAfter(dron.getRegDt())) { |
||||
// log.info("remove data - 1 munite over : {}", key);
|
||||
dronMap.remove(key); |
||||
} |
||||
} |
||||
log.info("removeScheduled end - dronMap size : {}", dronMap.size()); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,10 @@
|
||||
package kr.co.palnet.kac.socket.core.util; |
||||
|
||||
public class DronUtil { |
||||
public static boolean latlonCheck(double lat, double lon) { |
||||
if (lat > 32 && lat < 44 && lon > 124 && lon < 133) { |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
} |
@ -0,0 +1,15 @@
|
||||
package kr.co.palnet.kac.socket.service; |
||||
|
||||
import kr.co.palnet.kac.socket.core.model.DronDTO; |
||||
import lombok.RequiredArgsConstructor; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.stereotype.Service; |
||||
|
||||
@Slf4j |
||||
@RequiredArgsConstructor |
||||
@Service |
||||
public class KacAppService { |
||||
public void sendData(DronDTO dto) { |
||||
|
||||
} |
||||
} |
@ -0,0 +1,17 @@
|
||||
package kr.co.palnet.kac.socket.service; |
||||
|
||||
import kr.co.palnet.kac.socket.core.model.DronDTO; |
||||
import lombok.RequiredArgsConstructor; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.stereotype.Service; |
||||
|
||||
@Slf4j |
||||
@RequiredArgsConstructor |
||||
@Service |
||||
public class WebSocketService { |
||||
|
||||
public void sendData(DronDTO dto) { |
||||
|
||||
} |
||||
|
||||
} |
@ -1,15 +1,24 @@
|
||||
netty: |
||||
socket: |
||||
tcp-port: 8090 |
||||
tcp-port: 8200 |
||||
boss-count: 1 |
||||
worker-count: 10 |
||||
keep-alive: false |
||||
backlog: 100 |
||||
|
||||
app: |
||||
kac-app: |
||||
host: http://127.0.0.1:8000 |
||||
web-socket: |
||||
host: http://127.0.0.1:8100 |
||||
|
||||
|
||||
--- |
||||
|
||||
spring: |
||||
config: |
||||
activate: |
||||
on-profile: local |
||||
on-profile: local |
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in new issue