diff --git a/src/main/java/com/palnet/Application.java b/src/main/java/com/palnet/Application.java index 7d0da43..4ba405e 100644 --- a/src/main/java/com/palnet/Application.java +++ b/src/main/java/com/palnet/Application.java @@ -4,7 +4,9 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; +import org.springframework.scheduling.annotation.EnableScheduling; +@EnableScheduling @SpringBootApplication public class Application { public static void main(String[] args) { diff --git a/src/main/java/com/palnet/comn/model/ControlCacheModel.java b/src/main/java/com/palnet/comn/model/ControlCacheModel.java new file mode 100644 index 0000000..e76d49e --- /dev/null +++ b/src/main/java/com/palnet/comn/model/ControlCacheModel.java @@ -0,0 +1,12 @@ +package com.palnet.comn.model; + +import lombok.Data; + +@Data +public class ControlCacheModel { + private String controlId; + private String typeCd; + private String areaTrnsYn; + private boolean controlWarnCd; + private Long regTime; +} diff --git a/src/main/java/com/palnet/comn/utils/ControlCacheUtils.java b/src/main/java/com/palnet/comn/utils/ControlCacheUtils.java new file mode 100644 index 0000000..f1a229d --- /dev/null +++ b/src/main/java/com/palnet/comn/utils/ControlCacheUtils.java @@ -0,0 +1,43 @@ +package com.palnet.comn.utils; + +import com.palnet.comn.model.ControlCacheModel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import javax.naming.ldap.Control; +import java.util.HashMap; +import java.util.Map; + +@Component +public class ControlCacheUtils { + private Logger logger = LoggerFactory.getLogger(getClass()); + private static Map controls = new HashMap<>(); + private Integer removeTime = 1000 * 10; // 10초 + + public static void setControl(String objectId, ControlCacheModel control) { + controls.put(objectId, control); + } + + public static void removeControl(String objectId) { + controls.remove(objectId); + } + + public static ControlCacheModel getControl(String objectId) { + return controls.get(objectId); + } + + // 일정 시간마다 오랜된 데이터 삭제 + @Scheduled(fixedDelay = 1000 * 10) + public void remove() { + logger.info("controls keys : {}",controls.keySet().size()); + for (String key : controls.keySet()) { + ControlCacheModel model = controls.get(key); + Long diff = System.currentTimeMillis() - model.getRegTime(); + if(diff > (1000 * 10)){ + removeControl(key); + } + } + } +} diff --git a/src/main/java/com/palnet/server/SocketServer.java b/src/main/java/com/palnet/server/SocketServer.java index a902c59..f12fb56 100644 --- a/src/main/java/com/palnet/server/SocketServer.java +++ b/src/main/java/com/palnet/server/SocketServer.java @@ -48,7 +48,7 @@ public class SocketServer { public void start(){ try { - bossGroup = new NioEventLoopGroup(2); + bossGroup = new NioEventLoopGroup(10); workerGroup =new NioEventLoopGroup(); b.group(bossGroup , workerGroup) // bossGroup과 workerGroup은 NioEventLoopGroup의 인스턴스입니다.이 때 스레드 개수를 설정할 수 있음 각각 1, Runtime.getRuntime().availableProcessors() * 2로 설정했습니다. diff --git a/src/main/java/com/palnet/server/command/SocketCommand.java b/src/main/java/com/palnet/server/command/SocketCommand.java index f4fd41f..89759f0 100644 --- a/src/main/java/com/palnet/server/command/SocketCommand.java +++ b/src/main/java/com/palnet/server/command/SocketCommand.java @@ -1,185 +1,210 @@ package com.palnet.server.command; import com.palnet.comn.collection.GPCollection; +import com.palnet.comn.model.ControlCacheModel; import com.palnet.comn.model.GPHistoryModel; import com.palnet.comn.model.GPModel; import com.palnet.comn.utils.ContextUtils; +import com.palnet.comn.utils.ControlCacheUtils; import com.palnet.comn.utils.DateUtils; import com.palnet.comn.utils.JsonUtils; import com.palnet.process.message.producer.MessageProducer; import com.palnet.server.codec.SocketPayload; -import com.palnet.server.collection.ChannelCollection; -import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.env.Environment; import java.io.IOException; -import java.io.OutputStream; import java.net.*; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; -import java.nio.charset.StandardCharsets; import java.util.*; public class SocketCommand { - private Logger logger = LoggerFactory.getLogger(getClass()); - private MessageProducer messageProducer; - private Environment env; - - public SocketCommand() { - this.messageProducer = (MessageProducer) ContextUtils.getBean("messageProducer"); - this.env = (Environment) ContextUtils.getBean("environment") ; - } - - GPCollection collection = new GPCollection(); - - public void openSkyCollectionPut(SocketPayload payload) { - /** Socket Body **/ - List> resultList = (ArrayList)payload.getBody(); - - /** 전문 설정 ***/ - final String messageType = "OPENSKY"; - final String objectType = "FLIGHT"; - - List dataList = new ArrayList(); - - for(LinkedHashMap obj : resultList) { - GPModel model = new GPModel(); - - model.setObjectType(objectType); - model.setMessageType(messageType); - model.setObjectId(obj.get("objectId").toString().trim()); - model.setTerminalId(obj.get("terminalId").toString().trim()); - model.setLat((Double)obj.get("lat")); - model.setLng((Double)obj.get("lng")); - model.setElev((Double)obj.get("elev")); - model.setTerminalRcvDt(obj.get("terminalRcvDt").toString().trim()); - model.setSpeed((Double)obj.get("speed")); - model.setHeading((Double)obj.get("heading")); - model.setSpeedType((String)obj.get("speedType")); - model.setElevType((String)obj.get("elevType")); - model.setMoveDistanceType((String)obj.get("moveDistanceType")); - model.setMoveDistance((Double)obj.get("moveDistance")); - - model.setBetteryLevel((Double)obj.get("betteryLevel")); - model.setBetteryVoltage((Double)obj.get("betteryVoltage")); - model.setDronStatus((String)obj.get("dronStatus")); - - dataList.add(model); - } - - collection.putData(dataList); - } - - - /** - * 들어온 데이터를 collection넣는 작업을 한다. - * @param payload - */ - public void sandboxCollectionPut(SocketPayload payload) { - List> resultList = (ArrayList)payload.getBody(); - - /** 전문 설정 ***/ - final String messageType = "LTEM"; - final String objectType = "DRON"; + private Logger logger = LoggerFactory.getLogger(getClass()); + private MessageProducer messageProducer; + private Environment env; -// List dataList = new ArrayList(); + public SocketCommand() { + this.messageProducer = (MessageProducer) ContextUtils.getBean("messageProducer"); + this.env = (Environment) ContextUtils.getBean("environment"); + } - /** 데이터 모델링 **/ - for(LinkedHashMap obj : resultList) { - //위,경도 좌표가 0으로 들어오는 것은 무시 처리 - if((Double)obj.get("lat") > 0 && (Double)obj.get("lon") > 0) { - GPModel model = new GPModel(); - - model.setObjectType(objectType); - model.setMessageType(messageType); - model.setObjectId(obj.get("objectId").toString().trim()); - model.setTerminalId(payload.getTerminalId()); - model.setTerminalRcvDt(obj.get("terminalRcvDt").toString().trim()); - model.setSpeedType((String)obj.get("speedType")); - model.setElevType((String)obj.get("elevType")); - model.setMoveDistanceType((String)obj.get("moveDistanceType")); - model.setDronStatus((String)obj.get("dronStatus")); - - if(obj.get("lat") != null) model.setLat(Double.valueOf(obj.get("lat").toString())); - if(obj.get("lon") != null) model.setLng(Double.valueOf(obj.get("lon").toString())); - if(obj.get("elev") != null) model.setElev(Double.valueOf(obj.get("elev").toString())); - if(obj.get("speed") != null) model.setSpeed(Double.valueOf(obj.get("speed").toString())); - if(obj.get("heading") != null) model.setHeading(Double.valueOf(obj.get("heading").toString())); - if(obj.get("moveDistance") != null) model.setMoveDistance(Double.valueOf(obj.get("moveDistance").toString())); - if(obj.get("betteryLevel") != null) model.setBetteryLevel(Double.valueOf(obj.get("betteryLevel").toString())); - if(obj.get("betteryVoltage") != null) model.setBetteryVoltage(Double.valueOf(obj.get("betteryVoltage").toString())); - - // 환경 데이터 필드 추가 - if(obj.get("sensorCo") != null) model.setSensorCo(Double.valueOf(obj.get("sensorCo").toString())); - if(obj.get("sensorSo2") != null) model.setSensorSo2(Double.valueOf(obj.get("sensorSo2").toString())); - if(obj.get("sensorNo2") != null) model.setSensorNo2(Double.valueOf(obj.get("sensorNo2").toString())); - if(obj.get("sensorO3") != null) model.setSensorO3(Double.valueOf(obj.get("sensorO3").toString())); - if(obj.get("sensorDust") != null) model.setSensorDust(Double.valueOf(obj.get("sensorDust").toString())); - - // 서버 수신 시간 정보 - model.setServerRcvDt(DateUtils.getCurrentTime()); - - // 관제 이력 정보 - List hisList; - - GPHistoryModel history = new GPHistoryModel(); - history.setObjectId(model.getObjectId()); - history.setLat(model.getLat()); - history.setLng(model.getLng()); - - if(model.getPostionHistory() != null) { - hisList = model.getPostionHistory(); - } else { - hisList = new ArrayList<>(); - } - - hisList.add(history); - model.setPostionHistory(hisList); - - // STEP 1. Control ID 발급 -> Application Server Http 통신 - try { - HttpRequest request = HttpRequest.newBuilder() - .uri(new URI( -// "http://211.253.38.218:8080/api/ctr/cntrl/id/" + model.getObjectId() - env.getProperty("app.host") + "api/ctr/cntrl/id/" + model.getObjectId() - + "/" + model.getLat() - + "/" + model.getLng() + GPCollection collection = new GPCollection(); + + public void openSkyCollectionPut(SocketPayload payload) { + /** Socket Body **/ + List> resultList = (ArrayList) payload.getBody(); + + /** 전문 설정 ***/ + final String messageType = "OPENSKY"; + final String objectType = "FLIGHT"; + + List dataList = new ArrayList(); - )) - .version(HttpClient.Version.HTTP_2) - .GET() - .build(); + for (LinkedHashMap obj : resultList) { + GPModel model = new GPModel(); - HttpResponse response = HttpClient - .newHttpClient() - .send(request, HttpResponse.BodyHandlers.ofString()); + model.setObjectType(objectType); + model.setMessageType(messageType); + model.setObjectId(obj.get("objectId").toString().trim()); + model.setTerminalId(obj.get("terminalId").toString().trim()); + model.setLat((Double) obj.get("lat")); + model.setLng((Double) obj.get("lng")); + model.setElev((Double) obj.get("elev")); + model.setTerminalRcvDt(obj.get("terminalRcvDt").toString().trim()); + model.setSpeed((Double) obj.get("speed")); + model.setHeading((Double) obj.get("heading")); + model.setSpeedType((String) obj.get("speedType")); + model.setElevType((String) obj.get("elevType")); + model.setMoveDistanceType((String) obj.get("moveDistanceType")); + model.setMoveDistance((Double) obj.get("moveDistance")); - logger.debug("CONTROL ID RESPONSE : {}", response.body()); + model.setBetteryLevel((Double) obj.get("betteryLevel")); + model.setBetteryVoltage((Double) obj.get("betteryVoltage")); + model.setDronStatus((String) obj.get("dronStatus")); - Map body = JsonUtils.fromJson(response.body(), HashMap.class); + dataList.add(model); + } - Map data = (Map) body.get("data"); - model.setControlId((String) data.get("controlId")); - model.setTypeCd((String) data.get("typeCd")); - model.setAreaTrnsYn((String) data.get("areaTrnsYn")); - model.setControlWarnCd("Y".equals(data.get("controlWarnCd")) ? true : false); - model.setControlStartDt(DateUtils.getCurrentTime()); + collection.putData(dataList); + } - } catch (IOException e) { - logger.error("요청한 URL 정보가 잘못되었습니다.", e.getMessage()); - } catch (Exception e) { - e.printStackTrace(); - } - // STEP 2. 이력 생성할 전문 전달 -// messageProducer.sendControlHistoryMessage(model); + /** + * 들어온 데이터를 collection넣는 작업을 한다. + * + * @param payload + */ + public void sandboxCollectionPut(SocketPayload payload) { + List> resultList = (ArrayList) payload.getBody(); - // STEP 3. 화면에 표출할 정보 WebSocket 전달 -// messageProducer.sendControlMessage(model); + /** 전문 설정 ***/ + final String messageType = "LTEM"; + final String objectType = "DRON"; + +// List dataList = new ArrayList(); + + /** 데이터 모델링 **/ + for (LinkedHashMap obj : resultList) { + //위,경도 좌표가 0으로 들어오는 것은 무시 처리 + if ((Double) obj.get("lat") > 0 && (Double) obj.get("lon") > 0) { + GPModel model = new GPModel(); + + model.setObjectType(objectType); + model.setMessageType(messageType); + model.setObjectId(obj.get("objectId").toString().trim()); + model.setTerminalId(payload.getTerminalId()); + model.setTerminalRcvDt(obj.get("terminalRcvDt").toString().trim()); + model.setSpeedType((String) obj.get("speedType")); + model.setElevType((String) obj.get("elevType")); + model.setMoveDistanceType((String) obj.get("moveDistanceType")); + model.setDronStatus((String) obj.get("dronStatus")); + + if (obj.get("lat") != null) model.setLat(Double.valueOf(obj.get("lat").toString())); + if (obj.get("lon") != null) model.setLng(Double.valueOf(obj.get("lon").toString())); + if (obj.get("elev") != null) model.setElev(Double.valueOf(obj.get("elev").toString())); + if (obj.get("speed") != null) model.setSpeed(Double.valueOf(obj.get("speed").toString())); + if (obj.get("heading") != null) model.setHeading(Double.valueOf(obj.get("heading").toString())); + if (obj.get("moveDistance") != null) + model.setMoveDistance(Double.valueOf(obj.get("moveDistance").toString())); + if (obj.get("betteryLevel") != null) + model.setBetteryLevel(Double.valueOf(obj.get("betteryLevel").toString())); + if (obj.get("betteryVoltage") != null) + model.setBetteryVoltage(Double.valueOf(obj.get("betteryVoltage").toString())); + + // 환경 데이터 필드 추가 + if (obj.get("sensorCo") != null) model.setSensorCo(Double.valueOf(obj.get("sensorCo").toString())); + if (obj.get("sensorSo2") != null) model.setSensorSo2(Double.valueOf(obj.get("sensorSo2").toString())); + if (obj.get("sensorNo2") != null) model.setSensorNo2(Double.valueOf(obj.get("sensorNo2").toString())); + if (obj.get("sensorO3") != null) model.setSensorO3(Double.valueOf(obj.get("sensorO3").toString())); + if (obj.get("sensorDust") != null) + model.setSensorDust(Double.valueOf(obj.get("sensorDust").toString())); + + // 서버 수신 시간 정보 + model.setServerRcvDt(DateUtils.getCurrentTime()); + + // 관제 이력 정보 + List hisList; + + GPHistoryModel history = new GPHistoryModel(); + history.setObjectId(model.getObjectId()); + history.setLat(model.getLat()); + history.setLng(model.getLng()); + + if (model.getPostionHistory() != null) { + hisList = model.getPostionHistory(); + } else { + hisList = new ArrayList<>(); + } + + hisList.add(history); + model.setPostionHistory(hisList); + + Long start = System.currentTimeMillis(); + // STEP 1. 전에 내부 메모리에서 controlId 조회 + ControlCacheModel control = ControlCacheUtils.getControl(model.getObjectId()); + + if (control == null) { + // STEP 1. Control ID 발급 -> Application Server Http 통신 + try { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI( +// "http://211.253.38.218:8080/api/ctr/cntrl/id/" + model.getObjectId() + env.getProperty("app.host") + "api/ctr/cntrl/id/" + model.getObjectId() + + "/" + model.getLat() + + "/" + model.getLng() + + )) + .version(HttpClient.Version.HTTP_2) + .GET() + .build(); + + HttpResponse response = HttpClient + .newHttpClient() + .send(request, HttpResponse.BodyHandlers.ofString()); + + logger.debug("CONTROL ID RESPONSE : {}", response.body()); + + Map body = JsonUtils.fromJson(response.body(), HashMap.class); + + Map data = (Map) body.get("data"); + model.setControlId((String) data.get("controlId")); + model.setTypeCd((String) data.get("typeCd")); + model.setAreaTrnsYn((String) data.get("areaTrnsYn")); + model.setControlWarnCd("Y".equals(data.get("controlWarnCd")) ? true : false); + model.setControlStartDt(DateUtils.getCurrentTime()); + + ControlCacheModel ccm = new ControlCacheModel(); + ccm.setControlId((String) data.get("controlId")); + ccm.setTypeCd((String) data.get("typeCd")); + ccm.setAreaTrnsYn((String) data.get("areaTrnsYn")); + ccm.setControlWarnCd("Y".equals(data.get("controlWarnCd")) ? true : false); + ccm.setRegTime(System.currentTimeMillis()); + ControlCacheUtils.setControl(model.getObjectId(),ccm); + + } catch (IOException e) { + logger.error("요청한 URL 정보가 잘못되었습니다.", e.getMessage()); + } catch (Exception e) { + e.printStackTrace(); + } + + } else { + model.setControlId(control.getControlId()); + model.setTypeCd("2"); + model.setAreaTrnsYn(control.getAreaTrnsYn()); + model.setControlWarnCd(control.isControlWarnCd()); + control.setRegTime(System.currentTimeMillis()); + } + Long end = System.currentTimeMillis(); + logger.info(">>> during time : {}::{}", model.getObjectId(),end - start); + // STEP 2. 이력 생성할 전문 전달 + messageProducer.sendControlHistoryMessage(model); + + // STEP 3. 화면에 표출할 정보 WebSocket 전달 + messageProducer.sendControlMessage(model); // try { // Socket socket = new Socket(); @@ -201,10 +226,10 @@ public class SocketCommand { // logger.error(""); // } - } else { - logger.error("좌표 정보가 존재하지 않습니다."); - throw new IllegalArgumentException("좌표 정보가 존재하지 않습니다."); - } - } - } + } else { + logger.error("좌표 정보가 존재하지 않습니다."); + throw new IllegalArgumentException("좌표 정보가 존재하지 않습니다."); + } + } + } }