From 264d26d133e04505b35c5bc5586b109f37ad1710 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?dhji=28=EC=A7=80=EB=8C=80=ED=95=9C=29?= Date: Tue, 5 Mar 2024 21:23:56 +0900 Subject: [PATCH] feat: kac-app <-> socket <-> websocket --- .../controller/InnerSocketController.java | 7 +- .../socket/service/InnerSocketService.java | 51 +++++++++++++- .../co/palnet/kac/app/config/JsonConfig.java | 22 +++++++ .../exception/ServerExceptionHandler.java | 10 +-- .../app/core/security/AppSecurityConfig.java | 1 + .../ping/controller/TestErrorContoller.java | 11 ++-- .../command/impl/AdsbDroneCommandImpl.java | 6 +- .../command/impl/AntosDroneCommandImpl.java | 6 +- .../command/impl/SandboxDroneCommandImpl.java | 7 +- .../kac/socket/core/config/JsonConfig.java | 30 +++++++++ .../kac/socket/core/handler/DroneHandler.java | 2 +- .../kac/socket/service/ExternalService.java | 10 ++- .../kac/socket/service/KacAppService.java | 11 +++- .../kac/socket/service/WebSocketService.java | 15 ++++- .../src/main/resources/application.yml | 35 ++++++++++ .../controller/SocketReceiverController.java | 8 +-- .../kac/websocket/core/config/JsonConfig.java | 30 +++++++++ .../websocket/service/ScheduledService.java | 4 +- .../src/main/resources/application.yml | 22 ++++++- .../co/palnet/kac/config/db/KacJpaConfig.java | 7 ++ .../src/main/resources/application-db.yml | 20 +++++- common/model/build.gradle | 2 +- .../kac/common/model/common/DroneDto.java | 5 +- .../model/core/convert/InstantConvert.java | 66 +++++++++++++++++++ .../co/palnet/kac/util/ObjectMapperUtil.java | 25 ++++--- .../com/repository/ComIdntBasRepository.java | 6 +- .../com/repository/ComIdntfBasRepository.java | 8 --- socket-test/pav-100-dron.js | 7 +- socket-test/pav-warning.js | 9 +-- 29 files changed, 366 insertions(+), 77 deletions(-) create mode 100644 app/kac-app/src/main/java/kr/co/palnet/kac/app/config/JsonConfig.java create mode 100644 app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/config/JsonConfig.java create mode 100644 app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/config/JsonConfig.java create mode 100644 common/model/src/main/java/kr/co/palnet/kac/common/model/core/convert/InstantConvert.java delete mode 100644 data/com/src/main/java/kr/co/palnet/kac/data/com/repository/ComIdntfBasRepository.java diff --git a/app/kac-app/src/main/java/kr/co/palnet/kac/app/api/v1/inner/socket/controller/InnerSocketController.java b/app/kac-app/src/main/java/kr/co/palnet/kac/app/api/v1/inner/socket/controller/InnerSocketController.java index a206c34..1bfba62 100644 --- a/app/kac-app/src/main/java/kr/co/palnet/kac/app/api/v1/inner/socket/controller/InnerSocketController.java +++ b/app/kac-app/src/main/java/kr/co/palnet/kac/app/api/v1/inner/socket/controller/InnerSocketController.java @@ -24,11 +24,12 @@ public class InnerSocketController { SimpleControlDto simpleControlDto = innerSocketService.getControlId(objectId); return ResponseEntity.ok(simpleControlDto); } + // dron 정보 저장 - @PostMapping("/receiver/dron") - public ResponseEntity receiverDronData(@RequestBody DroneDto dronDto) { + @PostMapping("/receiver/drone") + public ResponseEntity receiverDronData(@RequestBody DroneDto droneDto) { log.debug(">>>>> receiver <<<<<"); - innerSocketService.setDronData(dronDto); + innerSocketService.setDronData(droneDto); return ResponseEntity.ok().build(); } diff --git a/app/kac-app/src/main/java/kr/co/palnet/kac/app/api/v1/inner/socket/service/InnerSocketService.java b/app/kac-app/src/main/java/kr/co/palnet/kac/app/api/v1/inner/socket/service/InnerSocketService.java index 16a38c9..b0eadf2 100644 --- a/app/kac-app/src/main/java/kr/co/palnet/kac/app/api/v1/inner/socket/service/InnerSocketService.java +++ b/app/kac-app/src/main/java/kr/co/palnet/kac/app/api/v1/inner/socket/service/InnerSocketService.java @@ -123,7 +123,7 @@ public class InnerSocketService { FltPlanCtrCntrlRel fltPlanCtrCntrlRel = new FltPlanCtrCntrlRel(); // 1. 식별 번호의 소유자 정보 저장. - ComIdntfBas comIdntfBas = comIdntBasRepository.findById(droneDto.getObjectId()).orElse(null); + ComIdntfBas comIdntfBas = comIdntBasRepository.findFirstByIdntfNumOrderByCreateDtAsc(droneDto.getObjectId()).orElse(null); // 1-1. 식별 번호의 모델 정보 조회 // PAV-KAC에서는 기초데이터가 필수가 아니여서 idntBas가 null일 수 있음. @@ -162,6 +162,55 @@ public class InnerSocketService { if (fltPlanCtrCntrlRel.getCntrlId() != null && !fltPlanCtrCntrlRel.getCntrlId().isEmpty() && fltPlanCtrCntrlRel.getPlanSno() != null) { fltPlanCtrCntrlRelRepository.save(fltPlanCtrCntrlRel); } + + } + + // history 생성 + CtrCntrlHstry ctrCntrlHstry = CtrCntrlHstry.builder() + .cntrlId(droneDto.getControlId()) + .trmnlId(droneDto.getTerminalId()) + .mvDstnc(droneDto.getMoveDistance()) + .mvDstncType(droneDto.getMoveDistanceType()) + .mssgTypeCd(droneDto.getMessageType()) + .statusCd(droneDto.getDroneStatus()) + .lat(droneDto.getLat()) + .lon(droneDto.getLon()) + .speed(droneDto.getSpeed()) + .speedType(droneDto.getSpeedType()) + .heading(droneDto.getHeading()) + .elev(droneDto.getElev()) + .elevType(droneDto.getElevType()) + .bttrLvl(droneDto.getBetteryLevel()) + .bttrVltg(droneDto.getBetteryVoltage()) + .trmnlRcvDt(droneDto.getTerminalRcvDt()) + .srvrRcvDt(droneDto.getServerRcvDt()) + + .sensorCo(droneDto.getSensorCo()) + .sensorSo2(droneDto.getSensorSo2()) + .sensorNo2(droneDto.getSensorNo2()) + .sensorO3(droneDto.getSensorO3()) + .sensorDust(droneDto.getSensorDust()) + + .build(); + + ctrCntrlHstry = ctrCntrlHstryRepository.save(ctrCntrlHstry); + + if ("01".equals(droneDto.getTypeCd()) || "99".equals(droneDto.getTypeCd())) { + + CtrCntrlHstryArea ctrCntrlHstryArea = CtrCntrlHstryArea.builder() + .cntrlId(droneDto.getControlId()) + .actnType(droneDto.getTypeCd()) + .prcsYn("N") + .lat(droneDto.getLat()) + .lon(droneDto.getLon()) + .hstrySno(ctrCntrlHstry.getHstrySno()) + .createDt(Instant.now()) + .updateDt(Instant.now()) + .build(); + + ctrCntrlHstryAreaRepository.save(ctrCntrlHstryArea); + + } } diff --git a/app/kac-app/src/main/java/kr/co/palnet/kac/app/config/JsonConfig.java b/app/kac-app/src/main/java/kr/co/palnet/kac/app/config/JsonConfig.java new file mode 100644 index 0000000..36c00f9 --- /dev/null +++ b/app/kac-app/src/main/java/kr/co/palnet/kac/app/config/JsonConfig.java @@ -0,0 +1,22 @@ +package kr.co.palnet.kac.app.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import kr.co.palnet.kac.util.ObjectMapperUtil; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; + +@Configuration +public class JsonConfig { + + @Bean + public ObjectMapper objectMapper() { + return ObjectMapperUtil.getObjectMapper(); + } + + @Bean + public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() { + return ObjectMapperUtil.getObjectMapperBuilder(); + } + +} diff --git a/app/kac-app/src/main/java/kr/co/palnet/kac/app/core/exception/ServerExceptionHandler.java b/app/kac-app/src/main/java/kr/co/palnet/kac/app/core/exception/ServerExceptionHandler.java index 4d76447..8cbd2eb 100644 --- a/app/kac-app/src/main/java/kr/co/palnet/kac/app/core/exception/ServerExceptionHandler.java +++ b/app/kac-app/src/main/java/kr/co/palnet/kac/app/core/exception/ServerExceptionHandler.java @@ -103,23 +103,23 @@ public class ServerExceptionHandler { switch (level) { case TRACE: - log.trace("message: {}, params: {}, trace: {}", message, paramArray, e.getStackTrace()); + log.trace("message: {}, params: {}, trace: ", message, paramArray, e); log.trace("", e); break; case DEBUG: - log.debug("message: {}, params: {}, trace: {}", message, paramArray, e.getStackTrace()); + log.debug("message: {}, params: {}, trace: ", message, paramArray, e); log.debug("", e); break; case INFO: - log.info("message: {}, params: {}, trace: {}", message, paramArray, e.getStackTrace()); + log.info("message: {}, params: {}, trace: ", message, paramArray, e); log.info("", e); break; case WARN: - log.warn("message: {}, params: {}, trace: {}", message, paramArray, e.getStackTrace()); + log.warn("message: {}, params: {}, trace: ", message, paramArray, e); log.warn("", e); break; case ERROR: - log.trace("message: {}, params: {}, trace: {}", message, paramArray, e.getStackTrace()); + log.trace("message: {}, params: {}, trace: ", message, paramArray, e); log.error("", e); break; default: diff --git a/app/kac-app/src/main/java/kr/co/palnet/kac/app/core/security/AppSecurityConfig.java b/app/kac-app/src/main/java/kr/co/palnet/kac/app/core/security/AppSecurityConfig.java index 206bf81..6e44e87 100644 --- a/app/kac-app/src/main/java/kr/co/palnet/kac/app/core/security/AppSecurityConfig.java +++ b/app/kac-app/src/main/java/kr/co/palnet/kac/app/core/security/AppSecurityConfig.java @@ -26,6 +26,7 @@ public class AppSecurityConfig extends SecurityConfig { // 시큐리티 적용 안하는 URL 목록 private final String[] IGNORE_URL = { + "/test/**", "/v1/inner/socket/**", "/v1/com/code/**", }; diff --git a/app/kac-app/src/main/java/kr/co/palnet/kac/app/ping/controller/TestErrorContoller.java b/app/kac-app/src/main/java/kr/co/palnet/kac/app/ping/controller/TestErrorContoller.java index 8f01196..377db66 100644 --- a/app/kac-app/src/main/java/kr/co/palnet/kac/app/ping/controller/TestErrorContoller.java +++ b/app/kac-app/src/main/java/kr/co/palnet/kac/app/ping/controller/TestErrorContoller.java @@ -1,5 +1,6 @@ package kr.co.palnet.kac.app.ping.controller; +import kr.co.palnet.kac.common.model.common.DroneDto; import kr.co.palnet.kac.core.exception.BaseErrorCode; import kr.co.palnet.kac.core.exception.BaseException; import kr.co.palnet.kac.util.EncryptUtil; @@ -10,10 +11,7 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.MessageSource; import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.context.support.MessageSourceAccessor; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.util.HashMap; import java.util.Locale; @@ -31,6 +29,11 @@ public class TestErrorContoller { @Qualifier("errorMessageSourceAccessor") private final MessageSourceAccessor errorMessageSourceAccessor; + @PostMapping("/json/parse") + public DroneDto jsonTest(@RequestBody DroneDto dto){ + return dto; + } + @GetMapping("/encrypt/{plainText}") public String ecrypt(@PathVariable String plainText) { String encrypt = KisaEncryptUtil.CbcEncrypt.encrypt(plainText); diff --git a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/command/impl/AdsbDroneCommandImpl.java b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/command/impl/AdsbDroneCommandImpl.java index ff06d97..7f6347a 100644 --- a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/command/impl/AdsbDroneCommandImpl.java +++ b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/command/impl/AdsbDroneCommandImpl.java @@ -98,7 +98,7 @@ public class AdsbDroneCommandImpl implements DroneCommand { controlDto.setRegTime(System.currentTimeMillis()); } catch (Exception e) { - log.error("ERROR : {}\n{}", e.getMessage(), e.getStackTrace()); + log.error("ERROR : {}", e.getMessage(), e); } } else { @@ -119,7 +119,7 @@ public class AdsbDroneCommandImpl implements DroneCommand { */ kacAppService.sendData(drone); } catch (Exception e) { - log.error("ERROR : {}\n{}", e.getMessage(), e.getStackTrace()); + log.error("ERROR : {}", e.getMessage(), e); } // STEP 3. 화면에 표출할 정보 WebSocket 전달 @@ -129,7 +129,7 @@ public class AdsbDroneCommandImpl implements DroneCommand { webSocketService.sendData(drone); } } catch (Exception e) { - log.error("ERROR : {}\n{}", e.getMessage(), e.getStackTrace()); + log.error("ERROR : {}", e.getMessage(), e); } } else { diff --git a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/command/impl/AntosDroneCommandImpl.java b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/command/impl/AntosDroneCommandImpl.java index 68e0418..a604014 100644 --- a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/command/impl/AntosDroneCommandImpl.java +++ b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/command/impl/AntosDroneCommandImpl.java @@ -99,7 +99,7 @@ public class AntosDroneCommandImpl implements DroneCommand { controlStorage.put(drone.getObjectId(), controlDto); } catch (Exception e) { - log.error("ERROR : {}\n{}", e.getMessage(), e.getStackTrace()); + log.error("ERROR : {}", e.getMessage(), e); } } else { @@ -120,7 +120,7 @@ public class AntosDroneCommandImpl implements DroneCommand { */ kacAppService.sendData(drone); } catch (Exception e) { - log.error("ERROR : {}\n{}", e.getMessage(), e.getStackTrace()); + log.error("ERROR : {}", e.getMessage(), e); } @@ -130,7 +130,7 @@ public class AntosDroneCommandImpl implements DroneCommand { webSocketService.sendData(drone); } } catch (Exception e) { - log.error("ERROR : {}\n{}", e.getMessage(), e.getStackTrace()); + log.error("ERROR : {}", e.getMessage(), e); } } else { diff --git a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/command/impl/SandboxDroneCommandImpl.java b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/command/impl/SandboxDroneCommandImpl.java index e6eda14..72b0e5b 100644 --- a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/command/impl/SandboxDroneCommandImpl.java +++ b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/command/impl/SandboxDroneCommandImpl.java @@ -47,7 +47,6 @@ public class SandboxDroneCommandImpl implements DroneCommand { for (DroneDto drone : resultList) { // 위,경도 좌표가 0으로 들어오는 것은 무시 처리 if (DroneUtil.checkCoordinates(drone.getLat(), drone.getLon())) { - drone.setObjectType(objectType); drone.setMessageType(messageType); drone.setTerminalId(rq.getTerminalId()); @@ -99,7 +98,7 @@ public class SandboxDroneCommandImpl implements DroneCommand { controlStorage.put(drone.getObjectId(), controlDto); } catch (Exception e) { - log.error("ERROR : {}\n{}", e.getMessage(), e.getStackTrace()); + log.error("ERROR : {}", e.getMessage(), e); } } else { @@ -122,14 +121,14 @@ public class SandboxDroneCommandImpl implements DroneCommand { */ kacAppService.sendData(drone); } catch (Exception e) { - log.error("ERROR : {}\n{}", e.getMessage(), e.getStackTrace()); + log.error("ERROR : {}", e.getMessage(), e); } // STEP 3. 화면에 표출할 정보 WebSocket 전달 try { webSocketService.sendData(drone); } catch (Exception e) { - log.error("ERROR : {}\n{}", e.getMessage(), e.getStackTrace()); + log.error("ERROR : {}", e.getMessage(), e); } Long end = System.currentTimeMillis(); diff --git a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/config/JsonConfig.java b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/config/JsonConfig.java new file mode 100644 index 0000000..779a4c5 --- /dev/null +++ b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/config/JsonConfig.java @@ -0,0 +1,30 @@ +package kr.co.palnet.kac.socket.core.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import kr.co.palnet.kac.util.ObjectMapperUtil; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; + +@Configuration +public class JsonConfig { + + + @Bean + public ObjectMapper objectMapper() { + return ObjectMapperUtil.getObjectMapper(); + } + + + @Bean + public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() { + return ObjectMapperUtil.getObjectMapperBuilder(); + } + + @Bean + public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() { + return new MappingJackson2HttpMessageConverter(objectMapper()); + } + +} diff --git a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/handler/DroneHandler.java b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/handler/DroneHandler.java index c1d58bd..d9829ae 100644 --- a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/handler/DroneHandler.java +++ b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/handler/DroneHandler.java @@ -104,7 +104,7 @@ public class DroneHandler extends SimpleChannelInboundHandler { ctx.writeAndFlush(rs); // Close the connection when an exception is raised. ctx.close(); - log.error("ERROR: {}\n{}", cause.getMessage(), cause.getStackTrace()); + log.error("ERROR: {}", cause.getMessage(), cause); } diff --git a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/service/ExternalService.java b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/service/ExternalService.java index 9d15ded..76336dc 100644 --- a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/service/ExternalService.java +++ b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/service/ExternalService.java @@ -1,10 +1,14 @@ package kr.co.palnet.kac.socket.service; import kr.co.palnet.kac.socket.core.model.UtmDto; +import kr.co.palnet.kac.util.ObjectMapperUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.stereotype.Service; import org.springframework.web.client.RestClient; @@ -21,13 +25,17 @@ public class ExternalService { RestClient client = RestClient.builder() .baseUrl(UTM_HOST) - .defaultHeader("Content-Type", "application/json") + .messageConverters(converts -> { + converts.removeIf(converter -> converter instanceof MappingJackson2HttpMessageConverter); + converts.add(new MappingJackson2HttpMessageConverter(ObjectMapperUtil.getObjectMapper())); + }) .build(); try { ResponseEntity res = client.post() .uri(UTM_REALTIME_URI) + .contentType(MediaType.APPLICATION_JSON) .body(utmDto) .retrieve() .toEntity(Void.class); diff --git a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/service/KacAppService.java b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/service/KacAppService.java index 15a47b6..b49a7c2 100644 --- a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/service/KacAppService.java +++ b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/service/KacAppService.java @@ -2,14 +2,15 @@ package kr.co.palnet.kac.socket.service; import kr.co.palnet.kac.common.model.common.DroneDto; import kr.co.palnet.kac.common.model.common.SimpleControlDto; +import kr.co.palnet.kac.util.ObjectMapperUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.stereotype.Service; import org.springframework.web.client.RestClient; -import org.springframework.web.util.UriComponentsBuilder; @Slf4j @RequiredArgsConstructor @@ -19,7 +20,7 @@ public class KacAppService { private String kacAppHost; private final String GET_CONTROL_ID = "/v1/inner/socket/control"; - private final String SEND_ALL = "/v1/inner/socket/receiver/dron"; + private final String SEND_ALL = "/v1/inner/socket/receiver/drone"; // control id 가져오기 public SimpleControlDto getControlId(String objectId) { @@ -36,7 +37,7 @@ public class KacAppService { // drone 데이터 전송 public void sendData(DroneDto dto) { RestClient client = getRestClient(); - ResponseEntity resp = client.post() + client.post() .uri(SEND_ALL) .contentType(MediaType.APPLICATION_JSON) .body(dto) @@ -47,6 +48,10 @@ public class KacAppService { private RestClient getRestClient() { return RestClient.builder() .baseUrl(kacAppHost) + .messageConverters(converts -> { + converts.removeIf(converter -> converter instanceof MappingJackson2HttpMessageConverter); + converts.add(new MappingJackson2HttpMessageConverter(ObjectMapperUtil.getObjectMapper())); + }) .build(); } diff --git a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/service/WebSocketService.java b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/service/WebSocketService.java index 3295014..d7a11f1 100644 --- a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/service/WebSocketService.java +++ b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/service/WebSocketService.java @@ -1,10 +1,13 @@ package kr.co.palnet.kac.socket.service; import kr.co.palnet.kac.common.model.common.DroneDto; +import kr.co.palnet.kac.util.ObjectMapperUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.MediaType; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.stereotype.Service; import org.springframework.web.client.RestClient; @@ -15,12 +18,18 @@ public class WebSocketService { @Value("${app.web-socket-web.host}") private String webSocketWebHost; - private final String SEND_DRONE_DATA = "/v1/api/ws/dron"; + private final String SEND_DRONE_DATA = "/v1/api/ws/drone"; public void sendData(DroneDto dto) { - RestClient client = RestClient.create(); + RestClient client = RestClient.builder() + .baseUrl(webSocketWebHost) + .messageConverters(converts -> { + converts.removeIf(converter -> converter instanceof MappingJackson2HttpMessageConverter); + converts.add(new MappingJackson2HttpMessageConverter(ObjectMapperUtil.getObjectMapper())); + }) + .build(); client.post() - .uri(webSocketWebHost + SEND_DRONE_DATA) + .uri(SEND_DRONE_DATA) .contentType(MediaType.APPLICATION_JSON) .body(dto) .retrieve() diff --git a/app/kac-socket-app/src/main/resources/application.yml b/app/kac-socket-app/src/main/resources/application.yml index 8a672c1..44c61d9 100644 --- a/app/kac-socket-app/src/main/resources/application.yml +++ b/app/kac-socket-app/src/main/resources/application.yml @@ -22,6 +22,10 @@ spring: virtual: enabled: true +logging: + level: + kr.co.palnet: debug + --- spring: @@ -30,4 +34,35 @@ spring: on-profile: local +--- + +spring: + config: + activate: + on-profile: docker + threads: + virtual: + enabled: true + +netty: + socket: + tcp-port: 8003 + boss-count: 1 + keep-alive: false + tcp-nodelay: false + backlog: 3000 + +app: + kac-app: + host: http://kac-app:8000 + web-socket: + host: http://kac-websocket-app:8001 + web-socket-web: + host: http://kac-websocket-app:8002 + +server: + port: 8004 + + + diff --git a/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/controller/SocketReceiverController.java b/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/controller/SocketReceiverController.java index 1c49a1a..2f04909 100644 --- a/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/controller/SocketReceiverController.java +++ b/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/controller/SocketReceiverController.java @@ -22,10 +22,10 @@ public class SocketReceiverController { private final ControlService controlService; @PostMapping("/drone") - public ResponseEntity receiver(@RequestBody DroneDto dronDTO) { - log.info("websocket message receiver : {}", dronDTO); - - DroneControlDto history = controlService.dronDtoToControlDtoConvert(dronDTO); + public ResponseEntity receiver(@RequestBody DroneDto droneDto) { + log.info("websocket message receiver : {}", droneDto); + + DroneControlDto history = controlService.dronDtoToControlDtoConvert(droneDto); // DRON의 대한 식별정보만 이력 관리 ControlStorage controlCache = ControlStorage.getInstance(); diff --git a/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/config/JsonConfig.java b/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/config/JsonConfig.java new file mode 100644 index 0000000..e768595 --- /dev/null +++ b/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/config/JsonConfig.java @@ -0,0 +1,30 @@ +package kr.co.palnet.kac.websocket.core.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import kr.co.palnet.kac.util.ObjectMapperUtil; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; + +@Configuration +public class JsonConfig { + + + @Bean + public ObjectMapper objectMapper() { + return ObjectMapperUtil.getObjectMapper(); + } + + + @Bean + public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() { + return ObjectMapperUtil.getObjectMapperBuilder(); + } + + @Bean + public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() { + return new MappingJackson2HttpMessageConverter(objectMapper()); + } + +} diff --git a/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/service/ScheduledService.java b/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/service/ScheduledService.java index d24a07e..2878885 100644 --- a/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/service/ScheduledService.java +++ b/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/service/ScheduledService.java @@ -42,9 +42,9 @@ public class ScheduledService { channel.writeAndFlush(new TextWebSocketFrame(json)); }); } catch (JsonProcessingException e) { - log.warn("send fail to all channel. : json parsing error : {}\n{}", e.getMessage(), e.getStackTrace()); + log.warn("send fail to all channel. : json parsing error : {}", e.getMessage(), e); } catch (Exception e) { - log.warn("send fail to all channel. : {}\n{}", e.getMessage(), e.getStackTrace()); + log.warn("send fail to all channel. : {}", e.getMessage(), e); } log.info("done send to all channel"); } diff --git a/app/kac-websocket-app/src/main/resources/application.yml b/app/kac-websocket-app/src/main/resources/application.yml index 5120d4d..5dd3e99 100644 --- a/app/kac-websocket-app/src/main/resources/application.yml +++ b/app/kac-websocket-app/src/main/resources/application.yml @@ -9,7 +9,7 @@ netty: app: kac-app: - host: http://127.0.0.1:8080 + host: http://127.0.0.1:8000 spring: threads: @@ -24,7 +24,25 @@ server: spring: config: activate: - on-profile: local + on-profile: docker + threads: + virtual: + enabled: true + +netty: + socket: + tcp-port: 8001 + boss-count: 1 + keep-alive: true + tcp-nodelay: true + backlog: 3000 + +app: + kac-app: + host: http://kac-app:8000 + +server: + port: 8002 diff --git a/common/config-db/src/main/java/kr/co/palnet/kac/config/db/KacJpaConfig.java b/common/config-db/src/main/java/kr/co/palnet/kac/config/db/KacJpaConfig.java index 55e5414..f551819 100644 --- a/common/config-db/src/main/java/kr/co/palnet/kac/config/db/KacJpaConfig.java +++ b/common/config-db/src/main/java/kr/co/palnet/kac/config/db/KacJpaConfig.java @@ -1,5 +1,6 @@ package kr.co.palnet.kac.config.db; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties; import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings; import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties; @@ -34,10 +35,16 @@ public class KacJpaConfig { this.hibernateProperties = hibernateProperties; } + @Value("${spring.datasource.pav-kac.jdbc-url}") + private String test; + @Bean(name = "kacDataSource") @Primary @ConfigurationProperties(prefix = "spring.datasource.pav-kac") public DataSource kacDataSource() { + System.out.println("==========================="); + System.out.println(test); + System.out.println("==========================="); return DataSourceBuilder.create().build(); } diff --git a/common/config-db/src/main/resources/application-db.yml b/common/config-db/src/main/resources/application-db.yml index 4085bd1..2e691a4 100644 --- a/common/config-db/src/main/resources/application-db.yml +++ b/common/config-db/src/main/resources/application-db.yml @@ -9,4 +9,22 @@ spring: driver-class-name: net.sf.log4jdbc.sql.jdbcapi.DriverSpy jdbc-url: jdbc:log4jdbc:mysql://localhost:13306/PAV_KAC?characterEncoding=UTF-8&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true username: kac - password: palnet!234 \ No newline at end of file + password: palnet!234 + +--- + +spring: + config: + activate: + on-profile: docker + jpa: + hibernate: + ddl-auto: none + naming: + physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl + datasource: + pav-kac: + driver-class-name: net.sf.log4jdbc.sql.jdbcapi.DriverSpy + jdbc-url: jdbc:log4jdbc:mysql://database:3306/PAV_KAC?characterEncoding=UTF-8&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true + username: kac + password: palnet!234 diff --git a/common/model/build.gradle b/common/model/build.gradle index 46754e9..fdb9c2a 100644 --- a/common/model/build.gradle +++ b/common/model/build.gradle @@ -1,4 +1,4 @@ dependencies { - + implementation project(":common:util") } diff --git a/common/model/src/main/java/kr/co/palnet/kac/common/model/common/DroneDto.java b/common/model/src/main/java/kr/co/palnet/kac/common/model/common/DroneDto.java index 5a40dad..b330ea0 100644 --- a/common/model/src/main/java/kr/co/palnet/kac/common/model/common/DroneDto.java +++ b/common/model/src/main/java/kr/co/palnet/kac/common/model/common/DroneDto.java @@ -1,5 +1,7 @@ package kr.co.palnet.kac.common.model.common; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import kr.co.palnet.kac.common.model.core.convert.InstantConvert; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -57,7 +59,8 @@ public class DroneDto { @Builder.Default private Double heading = 0.0; - private String terminalRcvDt; + @JsonDeserialize(using = InstantConvert.Deserializer.class) + private Instant terminalRcvDt; private Instant serverRcvDt; diff --git a/common/model/src/main/java/kr/co/palnet/kac/common/model/core/convert/InstantConvert.java b/common/model/src/main/java/kr/co/palnet/kac/common/model/core/convert/InstantConvert.java new file mode 100644 index 0000000..0828d3f --- /dev/null +++ b/common/model/src/main/java/kr/co/palnet/kac/common/model/core/convert/InstantConvert.java @@ -0,0 +1,66 @@ +package kr.co.palnet.kac.common.model.core.convert; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.databind.*; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import kr.co.palnet.kac.common.model.common.DroneDto; +import kr.co.palnet.kac.util.ObjectMapperUtil; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; + +import java.io.IOException; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; + +@Slf4j +public class InstantConvert { + private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); + + public static class Serializer extends JsonSerializer { + @Override + public void serialize(Instant value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeString(formatter.format(LocalDateTime.ofInstant(value, ZoneId.systemDefault()))); + } + } + + public static class Deserializer extends JsonDeserializer { + @Override + public Instant deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { + try { + + JsonToken currentToken = p.getCurrentToken(); + if (currentToken.equals(JsonToken.VALUE_NUMBER_INT)) { + long timestamp = p.getLongValue(); + return Instant.ofEpochMilli(timestamp); + } else if (currentToken.equals(JsonToken.VALUE_NUMBER_FLOAT)) { + String[] parts = p.getText().split("\\."); + long integerPart = Long.parseLong(parts[0]); + long decimalPart = Long.parseLong(parts[1]); + return Instant.ofEpochSecond(integerPart, decimalPart); + } else { + String str = p.getText(); + try { + return Instant.parse(str); + } catch (DateTimeParseException pe) { + return LocalDateTime.parse(str, formatter).atZone(ZoneId.systemDefault()).toInstant(); + } + } + } catch (Exception e) { + log.warn("WARN : fail parsing instant type : {}", e.getMessage()); + return null; + } + } + } + +} diff --git a/common/util/src/main/java/kr/co/palnet/kac/util/ObjectMapperUtil.java b/common/util/src/main/java/kr/co/palnet/kac/util/ObjectMapperUtil.java index 628cb9d..5de4e2f 100644 --- a/common/util/src/main/java/kr/co/palnet/kac/util/ObjectMapperUtil.java +++ b/common/util/src/main/java/kr/co/palnet/kac/util/ObjectMapperUtil.java @@ -1,7 +1,9 @@ package kr.co.palnet.kac.util; -import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; public class ObjectMapperUtil { @@ -11,19 +13,14 @@ public class ObjectMapperUtil { public static Jackson2ObjectMapperBuilder getObjectMapperBuilder() { Jackson2ObjectMapperBuilder jacksonBuilder = new Jackson2ObjectMapperBuilder(); - jacksonBuilder.serializationInclusion(JsonInclude.Include.NON_NULL); - jacksonBuilder.serializationInclusion(JsonInclude.Include.NON_EMPTY); -// jacksonBuilder.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); -// jacksonBuilder.featuresToDisable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); -// jacksonBuilder.featuresToDisable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE); -// jacksonBuilder.featuresToDisable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES); -// jacksonBuilder.modulesToInstall(new JavaTimeModule()); -// jacksonBuilder.timeZone(TimeZone.getTimeZone("UTC")); -// jacksonBuilder.simpleDateFormat("yyyy-MM-dd HH:mm:ss"); -// jacksonBuilder.serializers(new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); -// jacksonBuilder.serializers(new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); -// jacksonBuilder.deserializers(new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); -// jacksonBuilder.deserializers(new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + jacksonBuilder.modulesToInstall(new JavaTimeModule()); // java 8의 새로운 api 지원 +// jacksonBuilder.serializationInclusion(JsonInclude.Include.NON_NULL); // null 제외 +// jacksonBuilder.serializationInclusion(JsonInclude.Include.NON_EMPTY); // 빈 속성 무시 + jacksonBuilder.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); // 날짜 타임스탬프x > ISO-8601 형식o + jacksonBuilder.featuresToDisable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); //알수없는 속성 무시 +// jacksonBuilder.featuresToDisable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE); // 컨텍스트의 시간대로 조정하지 않도록 방지 +// jacksonBuilder.featuresToDisable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES); // 대소문자 무시 +// jacksonBuilder.timeZone(TimeZone.getTimeZone("UTC")); // 기본 시간대 설정 return jacksonBuilder; } diff --git a/data/com/src/main/java/kr/co/palnet/kac/data/com/repository/ComIdntBasRepository.java b/data/com/src/main/java/kr/co/palnet/kac/data/com/repository/ComIdntBasRepository.java index 04dd382..cd31bf1 100644 --- a/data/com/src/main/java/kr/co/palnet/kac/data/com/repository/ComIdntBasRepository.java +++ b/data/com/src/main/java/kr/co/palnet/kac/data/com/repository/ComIdntBasRepository.java @@ -3,6 +3,10 @@ package kr.co.palnet.kac.data.com.repository; import kr.co.palnet.kac.data.com.domain.ComIdntfBas; import org.springframework.data.jpa.repository.JpaRepository; -public interface ComIdntBasRepository extends JpaRepository { +import java.util.Optional; + +public interface ComIdntBasRepository extends JpaRepository { + + Optional findFirstByIdntfNumOrderByCreateDtAsc(String idntfNum); } diff --git a/data/com/src/main/java/kr/co/palnet/kac/data/com/repository/ComIdntfBasRepository.java b/data/com/src/main/java/kr/co/palnet/kac/data/com/repository/ComIdntfBasRepository.java deleted file mode 100644 index 73bd842..0000000 --- a/data/com/src/main/java/kr/co/palnet/kac/data/com/repository/ComIdntfBasRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package kr.co.palnet.kac.data.com.repository; - -import kr.co.palnet.kac.data.com.domain.ComIdntfBas; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface ComIdntfBasRepository extends JpaRepository { - -} diff --git a/socket-test/pav-100-dron.js b/socket-test/pav-100-dron.js index a424ce3..22ec3fa 100644 --- a/socket-test/pav-100-dron.js +++ b/socket-test/pav-100-dron.js @@ -1,13 +1,10 @@ const { getConnection, writeData } = require('./pav-client'); const { dumyData } = require('./pav-utils'); -// const host = "192.168.0.24" const host = "localhost" -// const host = '211.253.38.218'; -// const port = 8082; -const port = 8888; +const port = 8003; -const prefix = 'TEST-DRON-'; +const prefix = 'PA-DRON-'; const severalDrones = cnt => { // 클라이언트 정보 저장공간 const clients = []; diff --git a/socket-test/pav-warning.js b/socket-test/pav-warning.js index 11a9bf5..c49f537 100644 --- a/socket-test/pav-warning.js +++ b/socket-test/pav-warning.js @@ -1,16 +1,11 @@ const {getConnection, writeData} = require('./pav-client'); const {getCoordsFormBetweenCoord, dumyData} = require('./pav-utils'); -// const host = "192.168.0.24" const host = 'localhost'; -// const host = '192.168.0.34'; const port = 8003; -// const port = 8082; -// const host = '121.190.193.50'; -// const port = 6083; // 기본정보 -const prefix = 'PA0001'; +const prefix = 'PA'; const terminalId = ''; const pathSampleCoord = [ @@ -47,7 +42,7 @@ const getCoords = coords => { }; const getClient = () => { - const dronName = prefix + 'trmnlId'; + const dronName = prefix + '001'; const client = {}; client.dronName = dronName;