shjung il y a 2 ans
Parent
commit
d4527282fa

+ 5 - 5
src/main/java/com/its/pis/entity/TbPisInfr.java

@@ -9,7 +9,7 @@ import com.its.pis.websocket.C2F.message.C2FMessage;
 import com.its.pis.websocket.C2F.message.C2FMessageData;
 import com.its.pis.websocket.C2F.message.C2FMessageRequest;
 import com.its.pis.websocket.C2F.message.PrkPlceRlTimeResponseInfo;
-import com.its.pis.websocket.C2F.server.C2FWebSocketSession;
+import com.its.pis.websocket.PisWebSocketSession;
 import io.netty.channel.Channel;
 import lombok.Getter;
 import lombok.Setter;
@@ -46,7 +46,7 @@ public class TbPisInfr {
 	private boolean                 isDupLogin;
 
 	private TbPisInfrStts 			stts;
-	private C2FWebSocketSession 	session;
+	private PisWebSocketSession session;
 	private Channel 				dupChannel;
 	private long          			syncTime;
 
@@ -103,9 +103,9 @@ public class TbPisInfr {
 		this.syncTime   = 0;
 	}
 
-	public synchronized void channelOpen(C2FWebSocketSession session) {
+	public synchronized void channelOpen(PisWebSocketSession session) {
 		this.netState = NET.LOGIN_REQ;
-		this.session= session;
+		this.session = session;
 		getStts().initStts(true);
 		setConnectTm();
 		MainUI mainUI = MainUI.getInstance();
@@ -114,7 +114,7 @@ public class TbPisInfr {
 		}
 	}
 
-	public synchronized void channelLogin(C2FWebSocketSession session) {
+	public synchronized void channelLogin(PisWebSocketSession session) {
 		this.netState = NET.LOGINED;
 		this.session = session;
 		getStts().initStts(true);

+ 2 - 2
src/main/java/com/its/pis/entity/TbPisInfrStts.java

@@ -25,7 +25,7 @@ public class TbPisInfrStts {
 		
 		this.UPDT_DT       = SysUtils.getSysTime();
 		this.CMNC_STTS_CD  = CMNC_STTS_CD;
-		//this.CONN_DT       = "";
-		//this.DIS_CONN_DT   = "";
+//		if (this.CONN_DT == null) this.CONN_DT = "";
+//		if (this.DIS_CONN_DT == null) this.DIS_CONN_DT = "";
 	}
 }

+ 2 - 0
src/main/java/com/its/pis/global/AppRepository.java

@@ -17,6 +17,7 @@ public class AppRepository {
 
     public ConcurrentHashMap<String, TbPisInfr> pisNmbrMap = null;
     public ConcurrentHashMap<String, TbPisInfr> pisIpAddrMap = null;
+    public ConcurrentHashMap<String, TbPisInfr> pisTokenMap = null;
     public ConcurrentHashMap<String, TbPisInfr> pisIdMap = null;
 
     public ConcurrentHashMap<String, TbPrltCtlr> prltNmbrMap = null;
@@ -36,6 +37,7 @@ public class AppRepository {
 
     public AppRepository() {
         this.pisNmbrMap = new ConcurrentHashMap<>();
+        this.pisTokenMap = new ConcurrentHashMap<>();
         this.pisIpAddrMap = new ConcurrentHashMap<>();
         this.pisIdMap = new ConcurrentHashMap<>();
 

+ 1 - 1
src/main/java/com/its/pis/scheduler/SchedulerTask.java

@@ -24,7 +24,7 @@ public class SchedulerTask {
 
     @Scheduled(cron = "6 * * * * *")  // 1분주기 작업 실행(매분 6초)
     public void UnitSystSchedule() {
-        if (this.processConfig.isStartSchedule()) {
+        if (!this.processConfig.isStartSchedule()) {
             return;
         }
         Elapsed elapsed = new Elapsed();

+ 6 - 0
src/main/java/com/its/pis/service/PisInfrService.java

@@ -63,6 +63,7 @@ public class PisInfrService {
 
             AppRepository.getInstance().getPisNmbrMap().put(obj.getPIS_NMBR(), obj);
             AppRepository.getInstance().getPisIpAddrMap().put(obj.getPIS_IP(), obj);
+            AppRepository.getInstance().getPisTokenMap().put(obj.getPIS_TOKEN(), obj);
             AppRepository.getInstance().getPisIdMap().put(obj.getPIS_ID(), obj);
         }
 
@@ -74,6 +75,10 @@ public class PisInfrService {
         for (Map.Entry<String, TbPisInfr> e : AppRepository.getInstance().getPisIpAddrMap().entrySet()) {
             log.info("  {}", e.toString());
         }
+        log.info("loadPisInfr.PIS TOKEN List............ {} EA.", AppRepository.getInstance().getPisTokenMap().size());
+        for (Map.Entry<String, TbPisInfr> e : AppRepository.getInstance().getPisTokenMap().entrySet()) {
+            log.info("  {}", e.toString());
+        }
         log.info("loadPisInfr.PIS ID List............ {} EA.", AppRepository.getInstance().getPisIdMap().size());
         for (Map.Entry<String, TbPisInfr> e : AppRepository.getInstance().getPisIdMap().entrySet()) {
             log.info("  {}", e.toString());
@@ -90,6 +95,7 @@ public class PisInfrService {
             if (obj == null) {
                 log.error("loadPisInfrStts.PIS Stts Not Found, {}", stts.getPIS_NMBR());
             } else {
+                obj.getStts().setCONN_DT(stts.getCONN_DT());
                 obj.getStts().setCONN_DT(stts.getCONN_DT());
                 obj.getStts().setDIS_CONN_DT(stts.getDIS_CONN_DT());
             }

+ 0 - 1
src/main/java/com/its/pis/webapp/config/WebSecurityConfig.java

@@ -39,7 +39,6 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
                 .antMatchers("/swagger-ui.html", "/swagger/**", "/swagger-resources/**", "/webjars/**", "/v2/api-docs").permitAll()
                 // 웹소켓 권한 설정하지
                 .antMatchers("/ws/**").permitAll()
-
                 .antMatchers(new String[]{"/index"})
                 .hasRole("ADMIN")
                 .antMatchers(new String[]{"/**"})

+ 0 - 38
src/main/java/com/its/pis/websocket/C2F/server/C2FWebSocketConfig.java

@@ -1,38 +0,0 @@
-package com.its.pis.websocket.C2F.server;
-
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.socket.config.annotation.EnableWebSocket;
-import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
-import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
-
-@Slf4j
-@RequiredArgsConstructor
-@Configuration
-@EnableWebSocket
-public class C2FWebSocketConfig implements WebSocketConfigurer {
-
-    public static final String WS_ENDPOINT = "/ws/pis-c2f.do";
-
-    private final C2FWebSocketHandler c2FWebsocketHandler;
-
-    @Override
-    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
-
-        registry.addHandler(this.c2FWebsocketHandler, C2FWebSocketConfig.WS_ENDPOINT)
-                //.setAllowedOrigins("*")
-                .setAllowedOriginPatterns("*")
-                //.addInterceptors(new ItsWebSocketHandshakeInterceptor()).setAllowedOriginPatterns("*")
-                .withSockJS()
-                //.setSessionCookieNeeded(false)
-        ;  // sockjs
-
-        registry.addHandler(this.c2FWebsocketHandler, C2FWebSocketConfig.WS_ENDPOINT)
-                .setAllowedOriginPatterns("*")
-                //.addInterceptors(new ItsWebSocketHandshakeInterceptor()).setAllowedOriginPatterns("*")
-                //.setAllowedOrigins("*")
-        ; // 그냥 websocket 지원
-    }
-
-}

+ 0 - 33
src/main/java/com/its/pis/websocket/C2F/server/C2FWebSocketHandshakeInterceptor.java

@@ -1,33 +0,0 @@
-package com.its.pis.websocket.C2F.server;
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.http.server.ServerHttpRequest;
-import org.springframework.http.server.ServerHttpResponse;
-import org.springframework.http.server.ServletServerHttpRequest;
-import org.springframework.web.socket.WebSocketHandler;
-import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
-
-import java.util.Map;
-
-@Slf4j
-public class C2FWebSocketHandshakeInterceptor extends HttpSessionHandshakeInterceptor {
-    @Override
-    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response,
-                                   WebSocketHandler wsHandler, Map attributes) throws Exception {
-        ServletServerHttpRequest serverRequest = (ServletServerHttpRequest) request;
-        String token = serverRequest.getServletRequest().getParameter("token");
-        log.error("beforeHandshake: {}", token);
-        log.error("beforeHandshake: {}", serverRequest);
-        return super.beforeHandshake(request, response, wsHandler, attributes);
-    }
-
-
-
-    @Override
-    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response,
-                               WebSocketHandler wsHandler, Exception ex) {
-        ServletServerHttpRequest serverRequest = (ServletServerHttpRequest) request;
-        log.error("afterHandshake: {}", serverRequest);
-    }
-
-}

+ 53 - 0
src/main/java/com/its/pis/websocket/PisWebSocketConfig.java

@@ -0,0 +1,53 @@
+package com.its.pis.websocket;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.config.annotation.EnableWebSocket;
+import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
+import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
+
+@Slf4j
+@RequiredArgsConstructor
+@Configuration
+@EnableWebSocket
+public class PisWebSocketConfig implements WebSocketConfigurer {
+
+    public static final String WS_C2F_ENDPOINT = "/ws/pis-c2f.do";
+    public static final String WS_C2C_ENDPOINT = "/ws/pis-c2c.do";
+
+    private final PisWebSocketHandlerC2C pisWebsocketHandlerC2C;
+
+    @Override
+    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
+
+        registry.addHandler(this.pisWebsocketHandlerC2C, PisWebSocketConfig.WS_C2F_ENDPOINT)
+                //.setAllowedOrigins("*")
+                .setAllowedOriginPatterns("*")
+                //.addInterceptors(new ItsWebSocketHandshakeInterceptor()).setAllowedOriginPatterns("*")
+                .withSockJS()
+        //.setSessionCookieNeeded(false)
+        ;  // sockjs
+
+        registry.addHandler(this.pisWebsocketHandlerC2C, PisWebSocketConfig.WS_C2F_ENDPOINT)
+                .setAllowedOriginPatterns("*")
+        //.addInterceptors(new ItsWebSocketHandshakeInterceptor()).setAllowedOriginPatterns("*")
+        //.setAllowedOrigins("*")
+        ; // 그냥 websocket 지원
+
+        registry.addHandler(this.pisWebsocketHandlerC2C, PisWebSocketConfig.WS_C2C_ENDPOINT)
+                //.setAllowedOrigins("*")
+                .setAllowedOriginPatterns("*")
+                //.addInterceptors(new ItsWebSocketHandshakeInterceptor()).setAllowedOriginPatterns("*")
+                .withSockJS()
+        //.setSessionCookieNeeded(false)
+        ;  // sockjs
+
+        registry.addHandler(this.pisWebsocketHandlerC2C, PisWebSocketConfig.WS_C2C_ENDPOINT)
+                .setAllowedOriginPatterns("*")
+        //.addInterceptors(new ItsWebSocketHandshakeInterceptor()).setAllowedOriginPatterns("*")
+        //.setAllowedOrigins("*")
+        ; // 그냥 websocket 지원
+    }
+
+}

+ 132 - 0
src/main/java/com/its/pis/websocket/PisWebSocketHandler.java

@@ -0,0 +1,132 @@
+package com.its.pis.websocket;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.its.app.AppUtils;
+import com.its.app.utils.SysUtils;
+import com.its.pis.entity.TbPisInfr;
+import com.its.pis.entity.TbPisInfrStts;
+import com.its.pis.global.AppRepository;
+import com.its.pis.process.DbmsJobData;
+import com.its.pis.process.DbmsJobProcess;
+import com.its.pis.process.DbmsJobType;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.socket.CloseStatus;
+import org.springframework.web.socket.WebSocketSession;
+import org.springframework.web.socket.handler.TextWebSocketHandler;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+@Slf4j
+public class PisWebSocketHandler extends TextWebSocketHandler {
+
+    protected ObjectMapper mapper;
+    protected DbmsJobProcess dbmsJobProcess;
+
+    public PisWebSocketHandler() {
+
+        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
+            for (Map.Entry<WebSocketSession, PisWebSocketSession> obj : PisWebSocketSessionManager.getInstance().getMap().entrySet()) {
+                if (obj.getValue() != null) {
+                }
+            }
+        }));
+
+        this.mapper = new ObjectMapper();
+        this.dbmsJobProcess = (DbmsJobProcess) AppUtils.getBean(DbmsJobProcess.class);
+
+        log.info("C2FWebSocketHandler() START");
+    }
+
+    @Override
+    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
+        // 클라이언트가 연결되었을때 실행
+        String ipAddr = session.getRemoteAddress().getHostString();
+        String token = null;
+        for (Map.Entry<String, List<String>> l : session.getHandshakeHeaders().entrySet()) {
+            if ("sec-websocket-protocol".equals(l.getKey())) {
+                token = l.getValue().get(0);
+                break;
+            }
+        }
+        if (token == null) {
+            log.error("afterConnectionEstablished: {}, token not found, session will be closed", ipAddr);
+            session.close();
+            return;
+        }
+
+        log.info("afterConnectionEstablished: ipAddr={}, token={}", ipAddr, token);
+
+        TbPisInfr pis = AppRepository.getInstance().getPisTokenMap().get(token);
+        if (pis == null) {
+            log.error("afterConnectionEstablished: ipAddr={}, token={}, not found token, session will be closed", ipAddr, token);
+            session.close();
+            return;
+        }
+
+        if (pis.getSession() != null) {
+            WebSocketSession pisSession = pis.getSession().getSession();
+            if (pisSession != null && pisSession.isOpen()) {
+                log.error("afterConnectionEstablished: ipAddr={}, token={}, session already opened, old session will be closed", ipAddr, token);
+                try {
+                    pisSession.close();
+                } catch(IOException e) {}
+            }
+        }
+
+        PisWebSocketSession vo = new PisWebSocketSession(pis, session);
+        pis.channelOpen(vo);
+        PisWebSocketSessionManager.getInstance().addSession(session, vo);
+
+        session.setBinaryMessageSizeLimit(1*1024*1024);
+        session.setTextMessageSizeLimit(1*1024*1024);
+        super.afterConnectionEstablished(session);
+        log.info("afterConnectionEstablished: connection accept, {}, {}", pis.getPIS_ID(), pis.getPIS_NM());
+
+        // TODO: 주차정보시스템에 연결된 모든 주차장에 대해서 통신상태를 업데이트 해야함
+        List<TbPisInfrStts> pisSttsList = Collections.synchronizedList(new ArrayList<>());
+        String UPDT_DT = SysUtils.getSysTime();
+        pis.getStts().setUPDT_DT(UPDT_DT);
+        pisSttsList.add(pis.getStts());
+        dbmsJobProcess.add(new DbmsJobData(DbmsJobType.DATA_TYPE_PIS_STTS, false, pisSttsList, pis));
+    }
+
+    //클라이언트 연결을 끊었을 때 실행
+    @Override
+    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
+        log.warn("afterConnectionClosed: session={}, URI={}, UUID={}", session.getRemoteAddress(), session.getUri(), session.getId());
+        PisWebSocketSession sessionClient = PisWebSocketSessionManager.getInstance().getSession(session);
+        if (sessionClient != null) {
+            TbPisInfr pis = sessionClient.getObj();
+            if (pis != null) {
+                pis.channelClosed();
+
+                // TODO: 주차정보시스템에 연결된 모든 주차장에 대해서 통신상태를 업데이트 해야함
+                List<TbPisInfrStts> pisSttsList = Collections.synchronizedList(new ArrayList<>());
+                String UPDT_DT = SysUtils.getSysTime();
+                pis.getStts().setUPDT_DT(UPDT_DT);
+                pisSttsList.add(pis.getStts());
+                log.error("{}", pis.getStts());
+                dbmsJobProcess.add(new DbmsJobData(DbmsJobType.DATA_TYPE_PIS_STTS, false, pisSttsList, pis));
+            }
+        }
+        else {
+            log.warn("afterConnectionClosed: Not Found session={}, URI={}, UUID={}", session.getRemoteAddress(), session.getUri(), session.getId());
+        }
+
+        PisWebSocketSessionManager.getInstance().removeSession(session);
+        super.afterConnectionClosed(session, status);
+    }
+
+    @Override
+    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
+        log.error("handleTransportError: {}", exception.getMessage());
+        if (session.isOpen()) {
+            session.close();
+        }
+        super.handleTransportError(session, exception);
+    }
+}

+ 140 - 0
src/main/java/com/its/pis/websocket/PisWebSocketHandlerC2C.java

@@ -0,0 +1,140 @@
+package com.its.pis.websocket;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.its.app.utils.ItsUtils;
+import com.its.pis.entity.TbPisInfr;
+import com.its.pis.process.DbmsJobData;
+import com.its.pis.process.DbmsJobType;
+import com.its.pis.websocket.C2F.message.*;
+import com.its.pis.websocket.common.SubscribeIdentifier;
+import com.its.pis.websocket.common.SubscribeRequest;
+import com.its.pis.websocket.common.SubscribeResponseAccept;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.FileUtils;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.socket.TextMessage;
+import org.springframework.web.socket.WebSocketSession;
+
+import java.io.File;
+import java.util.Base64;
+
+@Slf4j
+@Controller
+@RequestMapping(PisWebSocketConfig.WS_C2C_ENDPOINT)
+public class PisWebSocketHandlerC2C extends PisWebSocketHandler {
+
+    public PisWebSocketHandlerC2C() {
+        super();
+        log.info("C2CWebSocketHandler() START");
+    }
+
+    //클라이언트가 웹소켓 서버로 메시지를 전송했을 때 실행
+    @Override
+    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
+
+        String payloadMessage = message.getPayload();
+        if (payloadMessage == null || payloadMessage.trim().isEmpty()) {
+            log.error("handleTextMessage: Payload data is empty");
+            return;
+        }
+        log.info("handleTextMessage: Payload, RX] {}", payloadMessage);
+
+        PisWebSocketSession sessionClient = PisWebSocketSessionManager.getInstance().getSession(session);
+        if (sessionClient == null) {
+            log.error("handleTextMessage: Request session not found, session will be closed {}", session);
+            session.close();
+            return;
+        }
+
+        TbPisInfr pis = sessionClient.getObj();
+        if (pis == null) {
+            log.error("handleTextMessage: PIS object not found, session will be closed {}", session);
+            session.close();
+            return;
+        }
+
+        C2FMessage<C2FMessagePayload> c2fMessage = this.mapper.readValue(payloadMessage, new TypeReference<C2FMessage<C2FMessagePayload>>(){});
+        if (c2fMessage.getCommand() == null) {
+            log.error("handleTextMessage: C2FMessage, {}", c2fMessage);
+            log.error("handleTextMessage: command data not found, session will be closed {}", session);
+            session.close();
+            return;
+        }
+        if ("subscribe".equals(c2fMessage.getCommand())) {
+            log.info("handleTextMessage: RX] subscribe");
+
+            SubscribeRequest subscribe = this.mapper.readValue(payloadMessage, SubscribeRequest.class);
+            //log.info("handleTextMessage: RX] {}", subscribe);
+            log.info("RX] {}", this.mapper.writeValueAsString(subscribe));
+            pis.channelLogin(pis.getSession());
+
+            SubscribeResponseAccept response = SubscribeResponseAccept.builder()
+                    .identifier(SubscribeIdentifier.builder()
+                            .channel("ParkingLotChannel").build())
+                    .essntl_info("Not Setting Info")
+                    .type("confirm_subscription").build();
+            String strMessage = this.mapper.writeValueAsString(response);
+            sessionClient.sendMessage(response.getType(), new TextMessage(strMessage));
+            log.info("TX] {}", strMessage);
+            return;
+        }
+
+        try {
+            String eventName = c2fMessage.getData().getPayload().getEvent_name();
+            if (C2FConstants.prk_plce_sttus_info.equals(eventName)) {
+                C2FMessage<PrkPlceSttusInfo> sttusInfo = this.mapper.readValue(payloadMessage, new TypeReference<C2FMessage<PrkPlceSttusInfo>>(){});
+                C2FMessage<PrkPlceSttusInfo> sttusTemp = sttusInfo;
+                sttusTemp.getData().getPayload().getPrk_place_image().setPrk_plce_image_data("base64 image data string");
+                log.info("handleTextMessage: RX] prk_plce_sttus_info");
+                log.info("RX] {}", this.mapper.writeValueAsString(sttusTemp));
+
+                if (sttusInfo.getData().getPayload().getPrk_place_image() != null) {
+                    int imageType = sttusInfo.getData().getPayload().getPrk_place_image().getPrk_plce_image_type();
+                    String imageStringData = sttusInfo.getData().getPayload().getPrk_place_image().getPrk_plce_image_data();
+                    byte[] decodedBytes = Base64.getDecoder().decode(imageStringData);
+                    String saveDir = ItsUtils.createUserDir("/images/");
+                    String outputFileName = saveDir + sttusInfo.getData().getPayload().getPrk_plce_manage_no();
+                    switch(imageType) {
+                        case 0: outputFileName += ".bmp"; break;
+                        case 1: outputFileName += ".gif"; break;
+                        case 2: outputFileName += ".jpg"; break;
+                        case 3: outputFileName += ".png"; break;
+                        default: outputFileName += ""; break;
+                    }
+
+                    FileUtils.writeByteArrayToFile(new File(outputFileName), decodedBytes);
+                }
+//                byte[] decodedBytes = Base64.getDecoder().decode(encodedString);
+//                FileUtils.writeByteArrayToFile(new File(outputFileName), decodedBytes);
+//                byte[] fileContent = FileUtils.readFileToByteArray(new File(filePath));
+//                String encodedString = Base64.getEncoder().encodeToString(fileContent);
+
+            } else if (C2FConstants.prk_plce_opr_info.equals(eventName)) {
+                C2FMessage<PrkPlceOprInfo> oprInfo = this.mapper.readValue(payloadMessage, new TypeReference<C2FMessage<PrkPlceOprInfo>>(){});
+                log.info("handleTextMessage: RX] prk_plce_opr_info");
+                log.info("RX] {}", this.mapper.writeValueAsString(oprInfo));
+            } else if (C2FConstants.prk_plce_rl_time_info.equals(eventName) || C2FConstants.prk_plce_rl_time_info_cycle.equals(eventName)) {
+                C2FMessage<PrkPlceRlTimeResponseInfo> rlTimeInfo = this.mapper.readValue(payloadMessage, new TypeReference<C2FMessage<PrkPlceRlTimeResponseInfo>>(){});
+                pis.setRlTimeInfo(rlTimeInfo);
+                dbmsJobProcess.add(new DbmsJobData(DbmsJobType.DATA_TYPE_RL_TIME, false, rlTimeInfo, pis));
+                log.info("handleTextMessage: RX] prk_plce_rl_time_info");
+                log.info("RX] {}", this.mapper.writeValueAsString(rlTimeInfo));
+            } else if (C2FConstants.prk_plce_reservation_response_info.equals(eventName)) {
+                C2FMessage<PrkPlceReservationResponseInfo> reservationInfo = this.mapper.readValue(payloadMessage, new TypeReference<C2FMessage<PrkPlceReservationResponseInfo>>(){});
+                log.info("handleTextMessage: RX] prk_plce_reservation_response_info");
+                log.info("RX] {}", this.mapper.writeValueAsString(reservationInfo));
+            } else if (C2FConstants.prk_plce_vhcl_location_response_info.equals(eventName)) {
+                C2FMessage<PrkPlceVhclLocationResponseInfo> locationInfo = this.mapper.readValue(payloadMessage, new TypeReference<C2FMessage<PrkPlceVhclLocationResponseInfo>>(){});
+                log.info("handleTextMessage: RX] prk_plce_vhcl_location_response_info");
+                log.info("RX] {}", this.mapper.writeValueAsString(locationInfo));
+            } else {
+                log.error("handleTextMessage: RX] Unknown event name, {}", eventName);
+                log.error("RX] Payload, {}", payloadMessage);
+            }
+        } catch(NullPointerException e) {
+            log.error("handleTextMessage: RX] NullPointerException, Payload data null, {}", payloadMessage);
+        }
+    }
+
+}

+ 7 - 108
src/main/java/com/its/pis/websocket/C2F/server/C2FWebSocketHandler.java → src/main/java/com/its/pis/websocket/PisWebSocketHandlerC2F.java

@@ -1,15 +1,9 @@
-package com.its.pis.websocket.C2F.server;
+package com.its.pis.websocket;
 
 import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.its.app.AppUtils;
 import com.its.app.utils.ItsUtils;
-import com.its.app.utils.SysUtils;
 import com.its.pis.entity.TbPisInfr;
-import com.its.pis.entity.TbPisInfrStts;
-import com.its.pis.global.AppRepository;
 import com.its.pis.process.DbmsJobData;
-import com.its.pis.process.DbmsJobProcess;
 import com.its.pis.process.DbmsJobType;
 import com.its.pis.websocket.C2F.message.*;
 import com.its.pis.websocket.common.SubscribeIdentifier;
@@ -19,82 +13,22 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.io.FileUtils;
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.socket.CloseStatus;
 import org.springframework.web.socket.TextMessage;
 import org.springframework.web.socket.WebSocketSession;
-import org.springframework.web.socket.handler.TextWebSocketHandler;
 
 import java.io.File;
-import java.util.*;
+import java.util.Base64;
 
 @Slf4j
 @Controller
-@RequestMapping(C2FWebSocketConfig.WS_ENDPOINT)
-public class C2FWebSocketHandler extends TextWebSocketHandler {
-
-    private ObjectMapper mapper;
-    private DbmsJobProcess dbmsJobProcess;
-
-    public C2FWebSocketHandler() {
-
-        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
-            for (Map.Entry<org.springframework.web.socket.WebSocketSession, C2FWebSocketSession> obj : C2FWebSocketSessionManager.getInstance().getMap().entrySet()) {
-                if (obj.getValue() != null) {
-                }
-            }
-        }));
-
-        this.mapper = new ObjectMapper();
-        this.dbmsJobProcess = (DbmsJobProcess) AppUtils.getBean(DbmsJobProcess.class);
+@RequestMapping(PisWebSocketConfig.WS_C2F_ENDPOINT)
+public class PisWebSocketHandlerC2F extends PisWebSocketHandler {
 
+    public PisWebSocketHandlerC2F() {
+        super();
         log.info("C2FWebSocketHandler() START");
     }
 
-    @Override
-    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
-        // 클라이언트가 연결되었을때 실행
-        String ipAddr = session.getRemoteAddress().getHostString();
-        String token = null;
-        for (Map.Entry<String, List<String>> l : session.getHandshakeHeaders().entrySet()) {
-            if ("sec-websocket-protocol".equals(l.getKey())) {
-                token = l.getValue().get(0);
-                break;
-            }
-        }
-        if (token == null) {
-            log.error("afterConnectionEstablished: {}, token not found, session will be closed", ipAddr);
-            session.close();
-            return;
-        }
-
-        log.info("afterConnectionEstablished: ipAddr={}, token={}", ipAddr, token);
-
-        for (Map.Entry<String, TbPisInfr> e : AppRepository.getInstance().getPisNmbrMap().entrySet()) {
-            TbPisInfr pis = e.getValue();
-            if (token.equals(pis.getPIS_TOKEN())) {
-                C2FWebSocketSession vo = new C2FWebSocketSession(pis, this, session);
-                pis.channelOpen(vo);
-                C2FWebSocketSessionManager.getInstance().addSession(session, vo);
-
-                session.setBinaryMessageSizeLimit(1*1024*1024);
-                session.setTextMessageSizeLimit(1*1024*1024);
-                super.afterConnectionEstablished(session);
-                log.info("afterConnectionEstablished: connection accept, {}, {}", pis.getPIS_ID(), pis.getPIS_NM());
-
-                // TODO: 주차정보시스템에 연결된 모든 주차장에 대해서 통신상태를 업데이트 해야함
-                List<TbPisInfrStts> pisSttsList = Collections.synchronizedList(new ArrayList<>());
-                String UPDT_DT = SysUtils.getSysTime();
-                pis.getStts().setUPDT_DT(UPDT_DT);
-                pisSttsList.add(pis.getStts());
-                dbmsJobProcess.add(new DbmsJobData(DbmsJobType.DATA_TYPE_PIS_STTS, false, pisSttsList, pis));
-                return;
-            }
-        }
-
-        log.error("afterConnectionEstablished: ipAddr={}, token={}, not found token, session will be closed", ipAddr, token);
-        session.close();
-    }
-
     //클라이언트가 웹소켓 서버로 메시지를 전송했을 때 실행
     @Override
     protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
@@ -106,7 +40,7 @@ public class C2FWebSocketHandler extends TextWebSocketHandler {
         }
         log.info("handleTextMessage: Payload, RX] {}", payloadMessage);
 
-        C2FWebSocketSession sessionClient = C2FWebSocketSessionManager.getInstance().getSession(session);
+        PisWebSocketSession sessionClient = PisWebSocketSessionManager.getInstance().getSession(session);
         if (sessionClient == null) {
             log.error("handleTextMessage: Request session not found, session will be closed {}", session);
             session.close();
@@ -203,39 +137,4 @@ public class C2FWebSocketHandler extends TextWebSocketHandler {
         }
     }
 
-    //클라이언트 연결을 끊었을 때 실행
-    @Override
-    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
-        log.warn("afterConnectionClosed: session={}, URI={}, UUID={}", session.getRemoteAddress(), session.getUri(), session.getId());
-        C2FWebSocketSession sessionClient = C2FWebSocketSessionManager.getInstance().getSession(session);
-        if (sessionClient != null) {
-            TbPisInfr pis = sessionClient.getObj();
-            if (pis != null) {
-                pis.channelClosed();
-
-                // TODO: 주차정보시스템에 연결된 모든 주차장에 대해서 통신상태를 업데이트 해야함
-                List<TbPisInfrStts> pisSttsList = Collections.synchronizedList(new ArrayList<>());
-                String UPDT_DT = SysUtils.getSysTime();
-                pis.getStts().setUPDT_DT(UPDT_DT);
-                pisSttsList.add(pis.getStts());
-                log.error("{}", pis.getStts());
-                dbmsJobProcess.add(new DbmsJobData(DbmsJobType.DATA_TYPE_PIS_STTS, false, pisSttsList, pis));
-            }
-        }
-        else {
-            log.warn("afterConnectionClosed: Not Found session={}, URI={}, UUID={}", session.getRemoteAddress(), session.getUri(), session.getId());
-        }
-
-        C2FWebSocketSessionManager.getInstance().removeSession(session);
-        super.afterConnectionClosed(session, status);
-    }
-
-    @Override
-    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
-        log.error("handleTransportError: {}", exception.getMessage());
-        if (session.isOpen()) {
-            session.close();
-        }
-        super.handleTransportError(session, exception);
-    }
 }

+ 6 - 5
src/main/java/com/its/pis/websocket/C2F/server/C2FWebSocketSession.java → src/main/java/com/its/pis/websocket/PisWebSocketSession.java

@@ -1,4 +1,4 @@
-package com.its.pis.websocket.C2F.server;
+package com.its.pis.websocket;
 
 import com.its.pis.entity.TbPisInfr;
 import lombok.Data;
@@ -10,16 +10,14 @@ import java.io.IOException;
 
 @Slf4j
 @Data
-public class C2FWebSocketSession {
+public class PisWebSocketSession {
 
-    private C2FWebSocketHandler c2FWebsocketHandler;
     private WebSocketSession session;
     private TbPisInfr obj;
     private String groupId;
 
-    public C2FWebSocketSession(TbPisInfr obj, C2FWebSocketHandler c2FWebsocketHandler, org.springframework.web.socket.WebSocketSession session) {
+    public PisWebSocketSession(TbPisInfr obj, WebSocketSession session) {
         this.obj = obj;
-        this.c2FWebsocketHandler = c2FWebsocketHandler;
         this.session = session;
     }
 
@@ -34,5 +32,8 @@ public class C2FWebSocketSession {
                 }
             }
         }
+        else {
+            log.error("Websocket Session is null or already closed, command={}, message={}", command, message);
+        }
     }
 }

+ 11 - 11
src/main/java/com/its/pis/websocket/C2F/server/C2FWebSocketSessionManager.java → src/main/java/com/its/pis/websocket/PisWebSocketSessionManager.java

@@ -1,4 +1,4 @@
-package com.its.pis.websocket.C2F.server;
+package com.its.pis.websocket;
 
 import com.its.app.utils.Counter;
 import lombok.extern.slf4j.Slf4j;
@@ -8,30 +8,30 @@ import org.springframework.web.socket.WebSocketSession;
 import java.util.concurrent.ConcurrentHashMap;
 
 @Slf4j
-public class C2FWebSocketSessionManager {
+public class PisWebSocketSessionManager {
 
-    private static C2FWebSocketSessionManager _instance = null;
+    private static PisWebSocketSessionManager _instance = null;
 
     private volatile boolean serverRun;
     private Counter sessions;
-    private ConcurrentHashMap<WebSocketSession, C2FWebSocketSession> sessionMap;
+    private ConcurrentHashMap<WebSocketSession, PisWebSocketSession> sessionMap;
 
-    public static C2FWebSocketSessionManager getInstance() {
+    public static PisWebSocketSessionManager getInstance() {
         if (_instance == null) {
-            synchronized (C2FWebSocketSessionManager.class) {
+            synchronized (PisWebSocketSessionManager.class) {
                 if (_instance == null)
-                    _instance = new C2FWebSocketSessionManager();
+                    _instance = new PisWebSocketSessionManager();
             }
         }
         return _instance;
     }
 
-    private C2FWebSocketSessionManager() {
+    private PisWebSocketSessionManager() {
         this.sessions = new Counter();
         this.sessionMap = new ConcurrentHashMap<>();
     }
 
-    public ConcurrentHashMap<WebSocketSession, C2FWebSocketSession> getMap() {
+    public ConcurrentHashMap<WebSocketSession, PisWebSocketSession> getMap() {
         return this.sessionMap;
     }
 
@@ -45,13 +45,13 @@ public class C2FWebSocketSessionManager {
         return (int) this.sessions.get();
     }
 
-    public void addSession(WebSocketSession session, C2FWebSocketSession vo) {
+    public void addSession(WebSocketSession session, PisWebSocketSession vo) {
         this.sessionMap.put(session, vo);
     }
     public void removeSession(WebSocketSession session) {
         this.sessionMap.remove(session);
     }
-    public C2FWebSocketSession getSession(WebSocketSession session) {
+    public PisWebSocketSession getSession(WebSocketSession session) {
         return this.sessionMap.get(session);
     }
 

+ 8 - 8
src/main/resources/mybatis/mapper/PisInfrMapper.xml

@@ -24,14 +24,14 @@
     <select id="selectPisInfrStts" resultType="com.its.pis.entity.TbPisInfrStts">
     <![CDATA[
         SELECT A.PIS_NMBR AS PIS_NMBR,
-               A.UPDT_DT AS UPDT_DT,
-               A.CMNC_STTS_CD AS CMNC_STTS_CD,
-               A.CONN_DT AS CONN_DT,
-               A.DIS_CONN_DT AS DIS_CONN_DT
-        FROM TB_PIS_INFR_STTS A,
-             TB_PIS_INFR      B
-        WHERE B.DEL_YN = 'N'
-          AND A.PIS_NMBR = B.PIS_NMBR
+               NVL(B.UPDT_DT,      '19700101000000') AS UPDT_DT,
+               NVL(B.CMNC_STTS_CD, 'CMS1')           AS CMNC_STTS_CD,
+               NVL(B.CONN_DT,      '19700101000000') AS CONN_DT,
+               NVL(B.DIS_CONN_DT,  '19700101000000') AS DIS_CONN_DT
+        FROM TB_PIS_INFR A
+        LEFT OUTER JOIN TB_PIS_INFR_STTS B
+                     ON A.DEL_YN = 'N'
+                    AND A.PIS_NMBR = B.PIS_NMBR
     ]]>
     </select>