From 7f0a159b9e483b82c51de5348d4b44bcb23599c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?dhji=28=EC=A7=80=EB=8C=80=ED=95=9C=29?= Date: Thu, 14 Mar 2024 13:34:01 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20websocket=20client=20drone=20data=20?= =?UTF-8?q?=EC=A0=84=EC=86=A1=20=EB=B0=A9=EC=8B=9D=20=EB=B3=80=EA=B2=BD(sc?= =?UTF-8?q?heduled=20->=20call)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://www.notion.so/PAV-KAC-websocket-client-schedule-call-25d5df23be114f8997aee9b2b51697f4?pvs=4 --- .../command/impl/SandboxDroneCommandImpl.java | 2 +- .../kac/socket/core/handler/DroneHandler.java | 1 - .../kac/socket/core/socket/SocketServer.java | 2 - .../kac/socket/service/ScheduledService.java | 3 -- .../src/main/resources/application.yml | 40 +++++++-------- .../websocket/core/codec/ControlDecoder.java | 49 +++++++++++++++++++ .../core/handler/WebSocketHandler.java | 44 +++++++++++++++-- .../core/model/BoundaryCoordinates.java | 15 ++++++ .../kac/websocket/core/model/ControlRq.java | 19 +++++++ .../kac/websocket/core/model/ErrorRs.java | 15 ++++++ .../core/socket/ChannelInitializer.java | 2 + .../kac/websocket/service/ControlService.java | 13 +++++ .../websocket/service/ScheduledService.java | 2 +- .../src/main/resources/application.yml | 33 ++++++------- http-client/http/ws.http | 17 +++++++ .../security/filter/JwtCheckFilter.java | 1 - 16 files changed, 204 insertions(+), 54 deletions(-) create mode 100644 app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/codec/ControlDecoder.java create mode 100644 app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/model/BoundaryCoordinates.java create mode 100644 app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/model/ControlRq.java create mode 100644 app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/model/ErrorRs.java 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 2eb999c..0423eae 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 @@ -107,7 +107,7 @@ public class SandboxDroneCommandImpl implements DroneCommand { } Long end = System.currentTimeMillis(); - log.debug(">>> during time : {} - {}", drone.getObjectId(), end - start); +// log.debug(">>> during time : {} - {}", drone.getObjectId(), end - start); } else { log.error("좌표 정보가 존재하지 않습니다."); 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 f68d310..7cc2377 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 @@ -65,7 +65,6 @@ public class DroneHandler extends SimpleChannelInboundHandler { return; } - log.debug(">>> rq : {}", rq); DroneCommand commandService = commandMap.get(rq.getCommand().trim()); if (commandService == null) { diff --git a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/socket/SocketServer.java b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/socket/SocketServer.java index bf3b449..82e7a71 100644 --- a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/socket/SocketServer.java +++ b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/socket/SocketServer.java @@ -19,7 +19,6 @@ public class SocketServer { private Channel serverChannel; public void start() { - log.debug(">>>>> start <<<<<"); try { // ChannelFuture: I/O operation의 결과나 상태를 제공하는 객체 // 지정한 host, port로 소켓을 바인딩하고 incoming connections을 받도록 준비함 @@ -36,7 +35,6 @@ public class SocketServer { // Bean을 제거하기 전에 해야할 작업이 있을 때 설정 @PreDestroy public void stop() { - log.debug(">>>>> stop <<<<<"); if (serverChannel != null) { serverChannel.close(); serverChannel.parent().closeFuture(); diff --git a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/service/ScheduledService.java b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/service/ScheduledService.java index 29febe2..bb7ba81 100644 --- a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/service/ScheduledService.java +++ b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/service/ScheduledService.java @@ -104,10 +104,7 @@ public class ScheduledService { // 사용을 다한 데이터 제거 @Scheduled(fixedDelay = 30 * 1000) public void removeDrone() { - log.info(">>>> removeDrone <<<<<"); DroneStorage droneStorage = DroneStorage.getInstance(); - Map> all = droneStorage.getAll(); - droneStorage.removeByCondition(); } diff --git a/app/kac-socket-app/src/main/resources/application.yml b/app/kac-socket-app/src/main/resources/application.yml index 9f3b94f..6dba782 100644 --- a/app/kac-socket-app/src/main/resources/application.yml +++ b/app/kac-socket-app/src/main/resources/application.yml @@ -1,3 +1,8 @@ +spring: + threads: + virtual: + enabled: true + netty: socket: tcp-port: 8003 @@ -6,6 +11,9 @@ netty: tcp-nodelay: false backlog: 3000 +server: + port: 8004 + app: kac-app: host: http://127.0.0.1:8000 @@ -14,14 +22,6 @@ app: web-socket-web: host: http://127.0.0.1:8002 -server: - port: 8004 - -spring: - threads: - virtual: - enabled: true - logging: level: kr.co.palnet: debug @@ -33,9 +33,17 @@ spring: activate: on-profile: local +app: + kac-app: + host: http://127.0.0.1:8000 + web-socket: + host: http://127.0.0.1:8001 + web-socket-web: + host: http://127.0.0.1:8002 + logging: level: - kr.co.palnet: info + kr.co.palnet: debug --- @@ -43,17 +51,6 @@ 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: @@ -63,9 +60,6 @@ app: web-socket-web: host: http://kac-websocket-app:8002 -server: - port: 8004 - logging: level: kr.co.palnet: info diff --git a/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/codec/ControlDecoder.java b/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/codec/ControlDecoder.java new file mode 100644 index 0000000..8ea7e7a --- /dev/null +++ b/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/codec/ControlDecoder.java @@ -0,0 +1,49 @@ +package kr.co.palnet.kac.websocket.core.codec; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; +import io.netty.handler.codec.http.websocketx.WebSocketFrame; +import io.netty.handler.codec.http.websocketx.extensions.WebSocketExtensionDecoder; +import kr.co.palnet.kac.util.ObjectMapperUtil; +import kr.co.palnet.kac.websocket.core.model.BoundaryCoordinates; +import kr.co.palnet.kac.websocket.core.model.ControlRq; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import java.util.List; + + +@Slf4j +@RequiredArgsConstructor +public class ControlDecoder extends WebSocketExtensionDecoder { + + private final ObjectMapper objectMapper = ObjectMapperUtil.getObjectMapper(); + + @Override + protected void decode(ChannelHandlerContext ctx, WebSocketFrame msg, List out) throws Exception { + try { + if (msg instanceof TextWebSocketFrame textWebSocketFrame) { + String json = textWebSocketFrame.text(); + JsonNode jsonNode = objectMapper.readTree(json); + String type = jsonNode.get("type").asText(); + switch (type) { + case "CURRENT_DRONE": + ControlRq> controlRq = objectMapper.readValue(json, new TypeReference<>() { + }); + out.add(controlRq); + break; + default: + log.warn("decode type is empty."); + break; + } + } + } catch (Exception e) { + log.warn("decode parsing error : {}\ndata in : {}", e.getMessage(), msg); + } + } + + +} diff --git a/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/handler/WebSocketHandler.java b/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/handler/WebSocketHandler.java index 59d5556..8ad014a 100644 --- a/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/handler/WebSocketHandler.java +++ b/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/handler/WebSocketHandler.java @@ -1,23 +1,57 @@ package kr.co.palnet.kac.websocket.core.handler; +import com.fasterxml.jackson.databind.ObjectMapper; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.handler.codec.http.websocketx.WebSocketFrame; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; +import kr.co.palnet.kac.util.ObjectMapperUtil; +import kr.co.palnet.kac.websocket.core.model.BoundaryCoordinates; +import kr.co.palnet.kac.websocket.core.model.ControlRq; +import kr.co.palnet.kac.websocket.core.model.ErrorRs; import kr.co.palnet.kac.websocket.core.storage.ChannelStorage; +import kr.co.palnet.kac.websocket.service.ControlService; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; +import java.util.List; + @Slf4j +@RequiredArgsConstructor @ChannelHandler.Sharable @Component -public class WebSocketHandler extends SimpleChannelInboundHandler { +public class WebSocketHandler extends SimpleChannelInboundHandler> { - public WebSocketHandler() { - } + private final ControlService controlService; + private final ObjectMapper objectMapper = ObjectMapperUtil.getObjectMapper(); @Override - protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame msg) throws Exception { + protected void channelRead0(ChannelHandlerContext ctx, ControlRq rq) throws Exception { + log.info("read :: {}", rq); + Object result = null; + switch (rq.getType()) { + case "CURRENT_DRONE": + if (rq.getBody() == null) { +// BoundaryCoordinates + log.warn("CURRENT_DRONE::boundary coordinates is null"); + return; + } + log.info(">>class {}", rq.getBody().getClass().getName()); + List list = (List) rq.getBody(); + result = controlService.getList(list); + break; + default: + log.warn("type is not supported."); + result = ErrorRs.builder() + .code("-400") + .message("bad request : type error") + .build(); + break; + } + + String json = objectMapper.writeValueAsString(result); + ctx.channel().writeAndFlush(new TextWebSocketFrame(json)); } @Override diff --git a/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/model/BoundaryCoordinates.java b/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/model/BoundaryCoordinates.java new file mode 100644 index 0000000..6a9354a --- /dev/null +++ b/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/model/BoundaryCoordinates.java @@ -0,0 +1,15 @@ +package kr.co.palnet.kac.websocket.core.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class BoundaryCoordinates { + private double lat; + private double lon; +} diff --git a/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/model/ControlRq.java b/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/model/ControlRq.java new file mode 100644 index 0000000..136d176 --- /dev/null +++ b/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/model/ControlRq.java @@ -0,0 +1,19 @@ +package kr.co.palnet.kac.websocket.core.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class ControlRq { + + private String type; + private T body; + +} diff --git a/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/model/ErrorRs.java b/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/model/ErrorRs.java new file mode 100644 index 0000000..3d5beea --- /dev/null +++ b/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/model/ErrorRs.java @@ -0,0 +1,15 @@ +package kr.co.palnet.kac.websocket.core.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class ErrorRs { + private String code; + private String message; +} diff --git a/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/socket/ChannelInitializer.java b/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/socket/ChannelInitializer.java index 9deddcc..84aa521 100644 --- a/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/socket/ChannelInitializer.java +++ b/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/socket/ChannelInitializer.java @@ -7,6 +7,7 @@ import io.netty.handler.codec.http.HttpServerCodec; import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketServerCompressionHandler; import io.netty.handler.timeout.IdleStateHandler; +import kr.co.palnet.kac.websocket.core.codec.ControlDecoder; import kr.co.palnet.kac.websocket.core.handler.WebSocketHandler; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -29,6 +30,7 @@ public class ChannelInitializer extends io.netty.channel.ChannelInitializer getList(List coordinatesList) { + ControlStorage controlStorage = ControlStorage.getInstance(); + List controlDtoList = controlStorage.getList(); + + if (controlDtoList == null || controlDtoList.isEmpty()) return new ArrayList<>(); + + controlDtoList.sort(Comparator.reverseOrder()); + + + return controlDtoList; + + } public DroneControlDto dronDtoToControlDtoConvert(DroneDto dronDto) { ControlStorage controlCache = ControlStorage.getInstance(); 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 b5457a2..3b583df 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 @@ -25,7 +25,7 @@ public class ScheduledService { // 접속한 모든 채널에 데이터 전송 - @Scheduled(fixedDelay = 10 * 1000) // 10초 +// @Scheduled(fixedDelay = 10 * 1000) // 10초 public void sendAllChannel() { // 채널 가져오기 ChannelStorage channelStorage = ChannelStorage.getInstance(); diff --git a/app/kac-websocket-app/src/main/resources/application.yml b/app/kac-websocket-app/src/main/resources/application.yml index b07431a..9a1ce90 100644 --- a/app/kac-websocket-app/src/main/resources/application.yml +++ b/app/kac-websocket-app/src/main/resources/application.yml @@ -1,3 +1,8 @@ +spring: + threads: + virtual: + enabled: true + netty: socket: tcp-port: 8001 @@ -6,36 +11,30 @@ netty: tcp-nodelay: true backlog: 3000 +--- + +spring: + config: + activate: + on-profile: local app: kac-app: - host: http://127.0.0.1:8000 - -spring: - threads: - virtual: - enabled: true + host: http://kac-app:8000 server: port: 8002 +logging: + level: + kr.co.palnet: debug + --- spring: config: activate: 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: diff --git a/http-client/http/ws.http b/http-client/http/ws.http index ea9cb57..9024aa6 100644 --- a/http-client/http/ws.http +++ b/http-client/http/ws.http @@ -1,5 +1,20 @@ ### 신규 websocket WEBSOCKET {{wsHost}}/ws +#Content-Type: application-json + +{ + "type": "CURRENT_DRONE", + "body": [ + { + "lat": 111.000, + "lon": 222.22 + } + ] +} + +=== + + ### 신규 websocket WEBSOCKET {{wsHost}}/ws ### 신규 websocket @@ -15,6 +30,7 @@ WEBSOCKET ws://localhost:18001/ws ### 기존 websocket WEBSOCKET ws://localhost:8081/ws + #Content-Type: application-json # #{"test": "test"} @@ -22,3 +38,4 @@ WEBSOCKET ws://localhost:8081/ws #{"test2": "test2"} #=== wait-for-server #{"test3": "test3"} + diff --git a/web/security/src/main/java/kr/co/palnet/kac/config/security/filter/JwtCheckFilter.java b/web/security/src/main/java/kr/co/palnet/kac/config/security/filter/JwtCheckFilter.java index 3e8a27e..db145e1 100644 --- a/web/security/src/main/java/kr/co/palnet/kac/config/security/filter/JwtCheckFilter.java +++ b/web/security/src/main/java/kr/co/palnet/kac/config/security/filter/JwtCheckFilter.java @@ -53,7 +53,6 @@ public class JwtCheckFilter extends BasicAuthenticationFilter { } catch (TokenExpiredException e) { throw new BaseAuthenticationException(BaseAuthErrorCode.EXPIRED_TOKEN); } catch (Exception e) { - log.debug(">>> e : {}", e.getClass().getName()); throw new BaseAuthenticationException(BaseAuthErrorCode.INVALID_TOKEN); }