Quellcode durchsuchen

vms edit update

shjung vor 3 Jahren
Ursprung
Commit
409e521736
24 geänderte Dateien mit 426 neuen und 124 gelöschten Zeilen
  1. 6 6
      pom.xml
  2. 20 1
      src/main/java/com/its/api/ItsOpServerApplication.java
  3. 7 0
      src/main/java/com/its/api/its/model/entity/vms/TbVmsMsgDsplSch.java
  4. 2 4
      src/main/java/com/its/api/its/model/entity/vms/TbVmsMsgDsplSchKey.java
  5. 1 1
      src/main/java/com/its/api/its/service/vds/VdsControlService.java
  6. 11 3
      src/main/java/com/its/api/its/service/vms/TbVmsMsgDsplSchService.java
  7. 4 4
      src/main/java/com/its/api/scheduler/ItsApiScheduler.java
  8. 71 0
      src/main/java/com/its/api/utils/HexUtils.java
  9. 53 0
      src/main/java/com/its/api/utils/NettyUtils.java
  10. 40 0
      src/main/java/com/its/api/utils/StringUtils.java
  11. 11 0
      src/main/java/com/its/api/utils/thread/NamedScheduleExecutor.java
  12. 24 0
      src/main/java/com/its/api/utils/thread/NamedThreadFactory.java
  13. 0 58
      src/main/java/com/its/api/xnettcp/client/NettyTcpClient.java
  14. 103 0
      src/main/java/com/its/api/xnettcp/client/NettyTcpClientVds.java
  15. 5 4
      src/main/java/com/its/api/xnettcp/client/NettyTcpClientVdsBootstrapFactory.java
  16. 18 17
      src/main/java/com/its/api/xnettcp/client/VdsCommClientService.java
  17. 12 1
      src/main/java/com/its/api/xnettcp/client/codec/NettyTcpClientDecoder.java
  18. 4 6
      src/main/java/com/its/api/xnettcp/client/handler/NettyTcpClientIdleHandler.java
  19. 1 6
      src/main/java/com/its/api/xnettcp/client/handler/NettyTcpClientInboundHandler.java
  20. 20 0
      src/main/java/com/its/api/xnettcp/client/handler/NettyTcpClientOutboundHandler.java
  21. 2 2
      src/main/java/com/its/api/xnettcp/client/listener/NettyTcpClientCloseListener.java
  22. 2 2
      src/main/java/com/its/api/xnettcp/client/listener/NettyTcpClientConnectListener.java
  23. 4 4
      src/main/java/com/its/api/xnetudp/service/VmsServerRequestSender.java
  24. 5 5
      src/main/java/com/its/api/xnetudp/thread/CenterCommServerReceiver.java

+ 6 - 6
pom.xml

@@ -243,13 +243,13 @@
         <dependency>
             <groupId>io.netty</groupId>
             <artifactId>netty-all</artifactId>
-            <version>4.1.72.Final</version>
-        </dependency>
-        <dependency>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-transport</artifactId>
-            <version>4.1.72.Final</version>
+<!--            <version>4.1.72.Final</version>-->
         </dependency>
+<!--        <dependency>-->
+<!--            <groupId>io.netty</groupId>-->
+<!--            <artifactId>netty-transport</artifactId>-->
+<!--&lt;!&ndash;            <version>4.1.72.Final</version>&ndash;&gt;-->
+<!--        </dependency>-->
 
         <dependency>
             <groupId>org.apache.commons</groupId>

+ 20 - 1
src/main/java/com/its/api/ItsOpServerApplication.java

@@ -2,7 +2,7 @@ package com.its.api;
 
 import com.its.api.config.AppUtils;
 import com.its.api.config.ProcessConfig;
-import com.its.api.xnettcp.client.service.VdsCommClientService;
+import com.its.api.xnettcp.client.VdsCommClientService;
 import com.its.api.xnetudp.CenterCommUdpServer;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.DisposableBean;
@@ -75,10 +75,29 @@ public class ItsOpServerApplication implements CommandLineRunner, ApplicationLis
 
         VdsCommClientService vdsCommClientService = (VdsCommClientService)AppUtils.getBean(VdsCommClientService.class);
         vdsCommClientService.run();
+
+//        Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
+//            private volatile boolean hasShutdown = false;
+//            private AtomicInteger shutdownTimes = new AtomicInteger(0);
+//
+//            @Override
+//            public void run() {
+//                synchronized (this) {
+//                    log.info("shutdown hook was invoked, " + this.shutdownTimes.incrementAndGet());
+//                    if (!this.hasShutdown) {
+//                        this.hasShutdown = true;
+//                        long beginTime = System.currentTimeMillis();
+//                        long consumingTimeTotal = System.currentTimeMillis() - beginTime;
+//                        log.info("shutdown hook over, consuming time total(ms): " + consumingTimeTotal);
+//                    }
+//                }
+//            }
+//        }, "ShutdownHook"));
     }
 
     @Override
     public void onApplicationEvent(ContextClosedEvent contextClosedEvent) {
+        // shutdown.....
         SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
         log.error("Application Terminated: {}, {}", sdfDate.format(new Date()), contextClosedEvent.toString());
     }

+ 7 - 0
src/main/java/com/its/api/its/model/entity/vms/TbVmsMsgDsplSch.java

@@ -102,6 +102,13 @@ public class TbVmsMsgDsplSch implements Serializable {
     @NotFound(action = NotFoundAction.IGNORE)
     private TbVmsForm form = new TbVmsForm();
 
+    public void setEditInfo(TbVmsMsgDsplSchDto.TbVmsTrfcInfrDsplSchUpdReq dto) {
+        this.dsplStrtHh = dto.getDsplStrtHh();
+        this.dsplEndHh = dto.getDsplEndHh();
+        this.dsplHh = dto.getDsplHh();
+        this.useYn = dto.getUseYn();
+    }
+
     public void setPhase(int phase) {
         this.phase = phase;
     }

+ 2 - 4
src/main/java/com/its/api/its/model/entity/vms/TbVmsMsgDsplSchKey.java

@@ -1,9 +1,6 @@
 package com.its.api.its.model.entity.vms;
 
-import lombok.Data;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import lombok.AllArgsConstructor;
+import lombok.*;
 
 import java.io.Serializable;
 
@@ -11,6 +8,7 @@ import java.io.Serializable;
  * VMS 교통 정보 표출 일정 Key Class
  */
 @Data
+@ToString
 @NoArgsConstructor(access = AccessLevel.PROTECTED)
 @AllArgsConstructor
 public class TbVmsMsgDsplSchKey implements Serializable {

+ 1 - 1
src/main/java/com/its/api/its/service/vds/VdsControlService.java

@@ -4,7 +4,7 @@ import com.its.api.its.model.dto.vds.VdsControlDto;
 import com.its.api.its.model.entity.vds.TbVdsCtlr;
 import com.its.api.its.repository.vds.TbVdsCtlrRepository;
 import com.its.api.utils.SysUtils;
-import com.its.api.xnettcp.client.service.VdsCommClientService;
+import com.its.api.xnettcp.client.VdsCommClientService;
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelFuture;
 import lombok.RequiredArgsConstructor;

+ 11 - 3
src/main/java/com/its/api/its/service/vms/TbVmsMsgDsplSchService.java

@@ -447,9 +447,17 @@ public class TbVmsMsgDsplSchService {
     public List<TbVmsMsgDsplSchDto> batchMergeInfoList(List<TbVmsMsgDsplSchDto.TbVmsTrfcInfrDsplSchUpdReq> reqList) {
         List<TbVmsMsgDsplSchDto> result = new ArrayList<>();
         for (TbVmsMsgDsplSchDto.TbVmsTrfcInfrDsplSchUpdReq req : reqList) {
-            TbVmsMsgDsplSch obj = req.toEntity();
-            this.repo.save(obj);    // INSERT or UPDATE
-            result.add(obj.toDto());
+
+            TbVmsMsgDsplSchKey key = new TbVmsMsgDsplSchKey(req.getVmsCtlrNmbr(), req.getTrfcSituTypeCd(), req.getPhase());
+            try {
+                TbVmsMsgDsplSch obj = requireOne(key);
+                obj.setEditInfo(req);
+                this.repo.save(obj);    // INSERT or UPDATE
+                result.add(obj.toDto());
+            }
+            catch (Exception e) {
+                log.error("batchMergeInfoList: Not Found, {}", key.toString());
+            }
         }
         return result;
     }

+ 4 - 4
src/main/java/com/its/api/scheduler/ItsApiScheduler.java

@@ -37,7 +37,7 @@ public class ItsApiScheduler {
     @Scheduled(cron = "0 * * * * *")  // 1분 주기 작업 실행
     public void jobCctvPsetScnr() {
         if (this.jobConfig.isCctvPreset()) {
-            this.cctvPsetScnrThread.run();
+            //this.cctvPsetScnrThread.run();
         }
     }
 
@@ -47,7 +47,7 @@ public class ItsApiScheduler {
     @Async
     @Scheduled(cron = "5 * * * * *")  // 60초 주기 작업 실행
     public void pollingBaseDbms() {
-        this.baseDbmsJobThread.run();
+        //this.baseDbmsJobThread.run();
     }
 
     /**
@@ -56,7 +56,7 @@ public class ItsApiScheduler {
     @Async
     @Scheduled(cron = "20 * * * * *")  // 60초 주기 작업 실행
     public void pollingFcltStts() {
-        this.fcltSttsJobThread.run();
+        //this.fcltSttsJobThread.run();
     }
 
     /**
@@ -65,7 +65,7 @@ public class ItsApiScheduler {
     @Async
     @Scheduled(cron = "10 * * * * *")  // 60초 주기 작업 실행
     public void pollingUnitStts() {
-        this.unitSttsJobThread.run();
+        //this.unitSttsJobThread.run();
     }
 
     /*@Async

+ 71 - 0
src/main/java/com/its/api/utils/HexUtils.java

@@ -0,0 +1,71 @@
+package com.its.api.utils;
+
+public class HexUtils {
+    static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+
+    public static byte[] intToBytes(int n) {
+        byte[] b = new byte[4];
+
+        for (int ii = 0; ii < 4; ii++) {
+            b[ii] = (byte) (n >> (24 - ii * 8));
+
+        }
+        return b;
+    }
+
+    public static String toHex(int value) {
+        byte[] bytes = intToBytes(value);
+        return toHex(bytes);
+    }
+
+    public static String toHex(byte[] bytes) {
+        if (bytes == null || bytes.length == 0)
+            return "";
+        char[] result = new char[bytes.length * 2];
+
+        for (int ii = 0; ii < bytes.length; ii++) {
+            result[ii * 2] = HEX_DIGITS[(bytes[ii] >> 4) & 0xf];
+            result[ii * 2 + 1] = HEX_DIGITS[bytes[ii] & 0xf];
+        }
+        return new String(result);
+    }
+
+    public static byte[] decodeHex(String hex) {
+        if (hex == null)
+            throw new IllegalArgumentException("hex == null");
+        if (hex.length() % 2 != 0)
+            throw new IllegalArgumentException("Unexpected hex string: " + hex);
+
+        byte[] result = new byte[hex.length() / 2];
+        for (int ii = 0; ii < result.length; ii++) {
+            int d1 = decodeHexDigit(hex.charAt(ii * 2)) << 4;
+            int d2 = decodeHexDigit(hex.charAt(ii * 2 + 1));
+            result[ii] = (byte) (d1 + d2);
+        }
+        return result;
+    }
+
+    private static int decodeHexDigit(char c) {
+        if (c >= '0' && c <= '9')
+            return c - '0';
+        if (c >= 'a' && c <= 'f')
+            return c - 'a' + 10;
+        if (c >= 'A' && c <= 'F')
+            return c - 'A' + 10;
+        throw new IllegalArgumentException("Unexpected hex digit: " + c);
+    }
+
+    public static String bytes2Hex(byte[] bytes) {
+        StringBuilder builder = new StringBuilder();
+        String tmp = "";
+        for (int n = 0; (bytes != null) && (n < bytes.length); ++n) {
+            tmp = Integer.toHexString(bytes[n] & 0xFF);
+            if (tmp.length() == 1)
+                builder.append("0").append(tmp);
+            else {
+                builder.append(tmp);
+            }
+        }
+        return builder.toString().toLowerCase();
+    }
+}

+ 53 - 0
src/main/java/com/its/api/utils/NettyUtils.java

@@ -1,6 +1,17 @@
 package com.its.api.utils;
 
 import io.netty.channel.Channel;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.epoll.Epoll;
+import io.netty.channel.epoll.EpollEventLoopGroup;
+import io.netty.channel.epoll.EpollServerSocketChannel;
+import io.netty.channel.epoll.EpollSocketChannel;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.ServerSocketChannel;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.channel.socket.nio.NioServerSocketChannel;
+import io.netty.channel.socket.nio.NioSocketChannel;
+import io.netty.util.concurrent.DefaultThreadFactory;
 
 import java.net.*;
 import java.util.ArrayList;
@@ -71,6 +82,48 @@ public final class NettyUtils {
             port = inetAddr.getPort();
         return port;
     }
+    public static boolean isEpollAvailable() {
+        // Netty epoll transport does not work with WSL (Windows Sybsystem for Linux) yet.
+/*
+        boolean HAS_WSLENV = System.getenv("WSLENV") != null;
+        return Epoll.isAvailable() && !HAS_WSLENV;
+*/
+        return Epoll.isAvailable();
+    }
+
+    public static EventLoopGroup newEventLoopGroup(int nThreads, String threadPoolName) {
+        if (isEpollAvailable()) {
+            if (threadPoolName.equals("")) {
+                return new EpollEventLoopGroup(nThreads);
+            }
+            else {
+                return new EpollEventLoopGroup(nThreads, new DefaultThreadFactory("epo"+threadPoolName));
+            }
+        } else {
+            if (threadPoolName.equals("")) {
+                return new NioEventLoopGroup(nThreads);
+            }
+            else {
+                return new NioEventLoopGroup(nThreads, new DefaultThreadFactory("nio" + threadPoolName));
+            }
+        }
+    }
+
+    public static Class<? extends SocketChannel> getSocketChannel() {
+        if (isEpollAvailable()) {
+            return EpollSocketChannel.class;
+        } else {
+            return NioSocketChannel.class;
+        }
+    }
+
+    public static Class<? extends ServerSocketChannel> getServerSocketChannel() {
+        if (isEpollAvailable()) {
+            return EpollServerSocketChannel.class;
+        } else {
+            return NioServerSocketChannel.class;
+        }
+    }
 
     public static final String OS_NAME = System.getProperty("os.name");
     private static boolean isLinuxPlatform = false;

+ 40 - 0
src/main/java/com/its/api/utils/StringUtils.java

@@ -17,4 +17,44 @@ public class StringUtils {
 
         return list;
     }
+
+    public static boolean isBlank(String str) {
+        if (str == null || "".equals(str.trim())) {
+            return true;
+        }
+        return false;
+    }
+
+    public static boolean isNotBlank(String str) {
+        return !isBlank(str);
+    }
+
+    public static String subString(String str, int length) {
+        if (isBlank(str)) {
+            return "";
+        }
+        return str.substring(0, Math.min(str.length(), length));
+    }
+
+    public static String firstUppercase(String str) {
+        char baseChar = str.charAt(0);
+        char updatedChar = Character.toUpperCase(baseChar);
+        if (baseChar == updatedChar) {
+            return str;
+        }
+        char[] chars = str.toCharArray();
+        chars[0] = updatedChar;
+        return new String(chars, 0, chars.length);
+    }
+
+    public static String firstLowercase(String str) {
+        char baseChar = str.charAt(0);
+        char updatedChar = Character.toLowerCase(baseChar);
+        if (baseChar == updatedChar) {
+            return str;
+        }
+        char[] chars = str.toCharArray();
+        chars[0] = updatedChar;
+        return new String(chars, 0, chars.length);
+    }
 }

+ 11 - 0
src/main/java/com/its/api/utils/thread/NamedScheduleExecutor.java

@@ -0,0 +1,11 @@
+package com.its.api.utils.thread;
+
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+
+public class NamedScheduleExecutor extends ScheduledThreadPoolExecutor {
+
+    public NamedScheduleExecutor(int poolSize, final String name) {
+        super(poolSize, new NamedThreadFactory(name));
+    }
+
+}

+ 24 - 0
src/main/java/com/its/api/utils/thread/NamedThreadFactory.java

@@ -0,0 +1,24 @@
+package com.its.api.utils.thread;
+
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class NamedThreadFactory implements ThreadFactory {
+
+    private final AtomicInteger threadNumber = new AtomicInteger(1);
+    private final ThreadGroup group;
+    private final String namePrefix;
+
+    public NamedThreadFactory(String name) {
+        this.group = new ThreadGroup(name);
+        this.namePrefix = (group.getName() + "-");
+    }
+
+    public Thread newThread(Runnable r) {
+        return new Thread(this.group, r, this.namePrefix + this.threadNumber.getAndIncrement(), 0L);
+    }
+
+    public Thread newThread(Runnable r, String title) {
+        return new Thread(this.group, r, this.namePrefix + this.threadNumber.getAndIncrement() + title, 0L);
+    }
+}

+ 0 - 58
src/main/java/com/its/api/xnettcp/client/NettyTcpClient.java

@@ -1,58 +0,0 @@
-package com.its.api.xnettcp.client;
-
-import com.its.api.xnettcp.client.listener.NettyTcpClientCloseListener;
-import com.its.api.xnettcp.client.listener.NettyTcpClientConnectListener;
-import io.netty.bootstrap.Bootstrap;
-import io.netty.channel.Channel;
-import io.netty.channel.ChannelFuture;
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-import lombok.Setter;
-import lombok.extern.slf4j.Slf4j;
-
-import java.net.InetSocketAddress;
-import java.util.concurrent.Callable;
-
-@Slf4j
-@Getter
-@Setter
-@RequiredArgsConstructor
-public class NettyTcpClient implements Callable<Object> {
-
-    private final String ipAddress;
-    private final int    port;
-    private final int    reconnectTime;
-    private final NettyTcpClientVdsBootstrapFactory bootstrapFactory;
-    private Channel channel = null;
-    private Bootstrap clientBootstrap = null;
-    private NettyTcpClientConnectListener connectListener = null;
-    private NettyTcpClientCloseListener closeListener = null;
-
-    @Override
-    public Object call() throws Exception {
-        log.info("NettyTcpClient start: {}, {}", this.ipAddress, this.port);
-        try {
-            if (this.clientBootstrap == null) {
-                this.clientBootstrap = this.bootstrapFactory.createBootstrap();
-            }
-            if (this.connectListener == null) {
-                this.connectListener = new NettyTcpClientConnectListener(this);
-            }
-            if (this.closeListener == null) {
-                this.closeListener = new NettyTcpClientCloseListener(this);
-            }
-            ChannelFuture channelFuture = this.clientBootstrap.connect(new InetSocketAddress(this.ipAddress, this.port));
-            this.channel = channelFuture
-                    .addListener(this.connectListener)
-                    .channel()
-                    .closeFuture()
-                    .addListener(this.closeListener)
-                    .channel();
-            //this.bootstrapFactory.addChannelFuture(channelFuture);
-        } catch (Exception e) {
-            log.error("Exception: {}", e.getMessage());
-            throw e;
-        }
-        return null;
-    }
-}

+ 103 - 0
src/main/java/com/its/api/xnettcp/client/NettyTcpClientVds.java

@@ -0,0 +1,103 @@
+package com.its.api.xnettcp.client;
+
+import com.its.api.xnettcp.client.listener.NettyTcpClientCloseListener;
+import com.its.api.xnettcp.client.listener.NettyTcpClientConnectListener;
+import io.netty.bootstrap.Bootstrap;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelFutureListener;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+
+import java.net.InetSocketAddress;
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+
+@Slf4j
+@Getter
+@Setter
+@RequiredArgsConstructor
+public class NettyTcpClientVds implements Callable<Object> {
+
+    private final String ipAddress;
+    private final int    port;
+    private final int    reconnectTime;
+    private final NettyTcpClientVdsBootstrapFactory bootstrapFactory;
+    private Bootstrap clientBootstrap = null;
+    private ChannelFuture channelFuture = null;
+    private NettyTcpClientConnectListener connectListener = null;
+    private NettyTcpClientCloseListener closeListener = null;
+
+    @Override
+    public Object call() throws Exception {
+        log.info("NettyTcpClientVds start: {}, {}", this.ipAddress, this.port);
+        try {
+            if (this.clientBootstrap == null) {
+                this.clientBootstrap = this.bootstrapFactory.createBootstrap();
+            }
+//            if (this.connectListener == null) {
+//                this.connectListener = new NettyTcpClientConnectListener(this);
+//            }
+//            if (this.closeListener == null) {
+//                this.closeListener = new NettyTcpClientCloseListener(this);
+//            }
+//            this.channel = this.channelFuture
+//                    .addListener(this.connectListener)
+//                    .channel()
+//                    .closeFuture()
+//                    .addListener(this.closeListener)
+//                    .channel();
+            connect();
+        } catch (Exception e) {
+            log.error("Exception: {}", e.getMessage());
+            throw e;
+        }
+        return null;
+    }
+
+    public void connect() {
+        log.error("NettyTcpClientVds try connect: {}, {}", this.ipAddress, this.port);
+        if (this.channelFuture != null && this.channelFuture.channel() != null) {
+            this.channelFuture.channel().close();
+            this.channelFuture = null;
+        }
+        this.channelFuture = this.clientBootstrap.connect(new InetSocketAddress(this.ipAddress, this.port));
+        this.channelFuture.addListener(new ChannelFutureListener() {
+            // 연결에 대한 리스터 추가
+            @Override
+            public void operationComplete(ChannelFuture future) throws Exception {
+                if (future.isSuccess()) {
+                    log.error("Channel open");
+                    channelOpen(future.channel());
+                } else {
+                    log.error("Could not connect to server, {}", future.cause().toString());
+                }
+            }
+        });
+        this.channelFuture.channel().closeFuture().addListener(new ChannelFutureListener() {
+            // 종료에 대한 리스너 추가
+            @Override
+            public void operationComplete(ChannelFuture future) throws Exception {
+                log.error("Channel closed, {}", future.toString());
+                channelClosed(future.channel());
+            }
+        });
+    }
+
+    public Channel getChannel() {
+        return this.channelFuture != null ? this.channelFuture.channel() : null;
+    }
+
+    protected void channelOpen(Channel channel) {
+        log.error("channelOpen: channel {}, channelFuture.channel {}", channel, this.channelFuture.channel());
+    }
+
+    protected synchronized void channelClosed(Channel channel) {
+        log.error("channelClosed: channel {}, channelFuture.channel {}", channel, this.channelFuture.channel());
+        this.channelFuture.channel().close();
+        this.channelFuture.channel().eventLoop().schedule(this, this.getReconnectTime(), TimeUnit.SECONDS);
+    }
+
+}

+ 5 - 4
src/main/java/com/its/api/xnettcp/client/NettyTcpClientVdsBootstrapFactory.java

@@ -1,5 +1,6 @@
 package com.its.api.xnettcp.client;
 
+import com.its.api.utils.NettyUtils;
 import com.its.api.xnettcp.client.codec.NettyTcpClientDecoder;
 import com.its.api.xnettcp.client.codec.NettyTcpClientEncoder;
 import com.its.api.xnettcp.client.handler.NettyTcpClientIdleHandler;
@@ -9,7 +10,6 @@ import io.netty.channel.ChannelFuture;
 import io.netty.channel.ChannelInitializer;
 import io.netty.channel.ChannelOption;
 import io.netty.channel.EventLoopGroup;
-import io.netty.channel.nio.NioEventLoopGroup;
 import io.netty.channel.socket.SocketChannel;
 import io.netty.channel.socket.nio.NioSocketChannel;
 import lombok.RequiredArgsConstructor;
@@ -24,11 +24,10 @@ public class NettyTcpClientVdsBootstrapFactory {
     private final int workerThread;
     private final int connectTimeout;
     private EventLoopGroup nioEventLoopGroup = null;
-    //private List<ChannelFuture> channelFutures = new ArrayList<>();
 
     public Bootstrap createBootstrap() {
         if (this.nioEventLoopGroup == null) {
-            this.nioEventLoopGroup = new NioEventLoopGroup(this.workerThread);
+            this.nioEventLoopGroup = NettyUtils.newEventLoopGroup(this.workerThread, "vdsEventGroup");//new NioEventLoopGroup(this.workerThread);  //EpollEventLoopGroup
         }
         Bootstrap bootstrap = new Bootstrap();
         bootstrap.group(this.nioEventLoopGroup);
@@ -44,12 +43,14 @@ public class NettyTcpClientVdsBootstrapFactory {
         bootstrap.option(ChannelOption.SO_KEEPALIVE, false);
         bootstrap.option(ChannelOption.SO_KEEPALIVE, false);
         bootstrap.handler(new ChannelInitializer<SocketChannel>() {
+            // VDS 전송 요청을 먼저하고 데이터를 수신한다.
+            // 핸들러가 실행되는 순서는 추가된 순서에 의해 결정된다.(Inbound: head=>tail, Outbound: tail=>head, name2ctx)
             @Override
             public void initChannel(SocketChannel ch) throws Exception {
                 ch.pipeline().addLast("vdsClientIdleHandler",    new NettyTcpClientIdleHandler(0, 0, 0, TimeUnit.SECONDS));
-                ch.pipeline().addLast("vdsClientEncoder",        new NettyTcpClientEncoder());            // Encoding handler
                 ch.pipeline().addLast("vdsClientDecoder",        new NettyTcpClientDecoder());            // Decoding handler
                 ch.pipeline().addLast("vdsClientInboundHandler", new NettyTcpClientInboundHandler());     // Packet Inbound handler
+                ch.pipeline().addLast("vdsClientEncoder",        new NettyTcpClientEncoder());            // Encoding handler
             }
         });
 

+ 18 - 17
src/main/java/com/its/api/xnettcp/client/service/VdsCommClientService.java → src/main/java/com/its/api/xnettcp/client/VdsCommClientService.java

@@ -1,10 +1,8 @@
-package com.its.api.xnettcp.client.service;
+package com.its.api.xnettcp.client;
 
 import com.its.api.config.VdsServerConfig;
 import com.its.api.its.global.UnitSystManager;
 import com.its.api.its.model.entity.unit.TbUnitSyst;
-import com.its.api.xnettcp.client.NettyTcpClient;
-import com.its.api.xnettcp.client.NettyTcpClientVdsBootstrapFactory;
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -25,13 +23,14 @@ import java.util.concurrent.Future;
 public class VdsCommClientService {
 
     private final VdsServerConfig vdsServerConfig;
-    private NettyTcpClient vdsClient;
+    private NettyTcpClientVdsBootstrapFactory vdsBootstrapFactory;
+    private NettyTcpClientVds vdsClient;
     private ExecutorService executorService= Executors.newFixedThreadPool(1);
-    private List<NettyTcpClient> clientTasks = Collections.synchronizedList(new ArrayList());
+    private List<NettyTcpClientVds> clientTasks = Collections.synchronizedList(new ArrayList());
 
     @PostConstruct
     void init() {
-
+        this.vdsBootstrapFactory = new NettyTcpClientVdsBootstrapFactory(1, 5);
     }
 
     public void run() {
@@ -43,12 +42,19 @@ public class VdsCommClientService {
         }
         log.info("{}", this.vdsServerConfig);
 
-        this.vdsClient = new NettyTcpClient(
-                this.vdsServerConfig.getIpAddress(),
-                this.vdsServerConfig.getPort(),
-                this.vdsServerConfig.getReconnectTime(),
-                new NettyTcpClientVdsBootstrapFactory(1, 5));
-        this.clientTasks.add(this.vdsClient);
+        /**
+         * 클라이언트가 여러개 인 경우 여기서 추가해줌
+         */
+        for (int ii = 0; ii < 1; ii++) {
+            this.vdsClient = new NettyTcpClientVds(
+                    this.vdsServerConfig.getIpAddress(),
+                    this.vdsServerConfig.getPort(),
+                    this.vdsServerConfig.getReconnectTime(),
+                    this.vdsBootstrapFactory
+            );
+            this.clientTasks.add(this.vdsClient);
+        }
+
         try {
             List<Future<Object>> futures = this.executorService.invokeAll(this.clientTasks);
             log.info("VdsCommClientService.run: {}", futures);
@@ -65,9 +71,4 @@ public class VdsCommClientService {
         log.info("VdsCommClientService.run: ..End. {}", toString());
     }
 
-    public boolean isConnected() {
-        return (this.vdsClient.getChannel() != null) && (this.vdsClient.getChannel().isActive());
-    }
-
-
 }

+ 12 - 1
src/main/java/com/its/api/xnettcp/client/codec/NettyTcpClientDecoder.java

@@ -25,7 +25,16 @@ public class NettyTcpClientDecoder extends ByteToMessageDecoder {
             log.error("RECV: {}. byteBuf.readableBytes() == 0.", ipAddress);
             return;
         }
-
+//        CompositeByteBuf messageBuf = Unpooled.compositeBuffer();
+//        CompositeByteBuf messageBuf = Unpooled.compositeBuffer();
+//        ByteBuf headerBuf = ...;
+//        ByteBuf bodyBuf = ...;
+//        messageBuf.addComponents(headerBuf, bodyBuf);
+//...
+//        messageBuf.removeComponent(0);    // 헤더를 제거
+//        for (ByteBuf buf : messageBuf) {
+//            System.out.println(buf.toString());
+//        }
         byteBuf.markReaderIndex();
         byte[] headBuffer = new byte[readableBytes];
         byteBuf.readBytes(headBuffer);
@@ -34,5 +43,7 @@ public class NettyTcpClientDecoder extends ByteToMessageDecoder {
         byteBuf.markReaderIndex();
         byteBuf.discardReadBytes();
         byteBuf.resetReaderIndex();
+
+        //list.add(byteBuf);
     }
 }

+ 4 - 6
src/main/java/com/its/api/xnettcp/client/handler/NettyTcpClientIdleHandler.java

@@ -18,30 +18,28 @@ public class NettyTcpClientIdleHandler extends IdleStateHandler {
     @Override
     protected void channelIdle(ChannelHandlerContext ctx, IdleStateEvent evt) throws Exception {
         String ipAddress = NettyUtils.getRemoteIpAddress(ctx.channel());
-        log.info("channelIdle: {}", ipAddress);
+        log.error("channelIdle: {}", ipAddress);
         // disconnect here
     }
 
     @Override
     public void channelActive(ChannelHandlerContext ctx) throws Exception {
         String ipAddress = NettyUtils.getRemoteIpAddress(ctx.channel());
-        log.info("channelActive: {}", ipAddress);
-
+        log.error("channelActive: {}", ipAddress);
         super.channelActive(ctx);
     }
 
     @Override
     public void channelInactive(ChannelHandlerContext ctx) throws Exception {
         String ipAddress = NettyUtils.getRemoteIpAddress(ctx.channel());
-        log.info("channelInactive: {}", ipAddress);
-
+        log.error("channelInactive: {}", ipAddress);
         super.channelInactive(ctx);
     }
 
     @Override
     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
         String ipAddress = NettyUtils.getRemoteIpAddress(ctx.channel());
-        log.info("exceptionCaught: {}, {}", ipAddress, cause.getMessage());
+        log.error("exceptionCaught: {}, {}", ipAddress, cause.getMessage());
 
         ctx.channel().close();
     }

+ 1 - 6
src/main/java/com/its/api/xnettcp/client/handler/NettyTcpClientInboundHandler.java

@@ -9,12 +9,7 @@ public class NettyTcpClientInboundHandler extends SimpleChannelInboundHandler<Ob
 
     @Override
     protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object msg) throws Exception {
-
+        log.error("channelRead0: {}", msg);
     }
 
-    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception
-    {
-        log.error("exceptionCaught:  {}", ctx.toString());
-        super.exceptionCaught(ctx, cause);
-    }
 }

+ 20 - 0
src/main/java/com/its/api/xnettcp/client/handler/NettyTcpClientOutboundHandler.java

@@ -0,0 +1,20 @@
+package com.its.api.xnettcp.client.handler;
+
+import io.netty.channel.*;
+
+public class NettyTcpClientOutboundHandler extends ChannelOutboundHandlerAdapter {
+
+    @Override
+    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
+        promise.addListener(new ChannelFutureListener() {
+            @Override
+            public void operationComplete(ChannelFuture f) {
+                if (!f.isSuccess()) {
+                    f.cause().printStackTrace();
+                    f.channel().close();
+                }
+            }
+        });
+    }
+
+}

+ 2 - 2
src/main/java/com/its/api/xnettcp/client/listener/NettyTcpClientCloseListener.java

@@ -1,6 +1,6 @@
 package com.its.api.xnettcp.client.listener;
 
-import com.its.api.xnettcp.client.NettyTcpClient;
+import com.its.api.xnettcp.client.NettyTcpClientVds;
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.ChannelFutureListener;
 import lombok.RequiredArgsConstructor;
@@ -12,7 +12,7 @@ import java.util.concurrent.TimeUnit;
 @RequiredArgsConstructor
 public class NettyTcpClientCloseListener implements ChannelFutureListener {
 
-    private final NettyTcpClient client;
+    private final NettyTcpClientVds client;
 
     /**
      * 채널이 종료(close) 되었을 때 발생하는 이벤트 핸들러

+ 2 - 2
src/main/java/com/its/api/xnettcp/client/listener/NettyTcpClientConnectListener.java

@@ -1,6 +1,6 @@
 package com.its.api.xnettcp.client.listener;
 
-import com.its.api.xnettcp.client.NettyTcpClient;
+import com.its.api.xnettcp.client.NettyTcpClientVds;
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.ChannelFutureListener;
 import lombok.RequiredArgsConstructor;
@@ -10,7 +10,7 @@ import lombok.extern.slf4j.Slf4j;
 @RequiredArgsConstructor
 public class NettyTcpClientConnectListener implements ChannelFutureListener {
 
-    private final NettyTcpClient client;
+    private final NettyTcpClientVds client;
 
     /**
      * 최초 서버와 접속이 실패할 경우 이벤트 핸들러

+ 4 - 4
src/main/java/com/its/api/xnetudp/service/VmsServerRequestSender.java

@@ -76,7 +76,7 @@ public class VmsServerRequestSender {
      * @return
      */
     public boolean requestReset(Long id, VmsControlDto.VmsControlReq req) {
-        log.error("requestReset: {}, {}", id, req);
+        log.info("requestReset: {}, {}", id, req);
         CENTER_VMS_REQ_RESET commMsg = new CENTER_VMS_REQ_RESET(id, req.getUserId());
         run(commMsg.getBuffer());
         return true;
@@ -89,7 +89,7 @@ public class VmsServerRequestSender {
      * @return
      */
     public boolean requestPowerControl(Long id, VmsControlDto.VmsControlReq req) {
-        log.error("requestPowerControl: {}, {}", id, req);
+        log.info("requestPowerControl: {}, {}", id, req);
         CENTER_VMS_REQ_POWER commMsg = new CENTER_VMS_REQ_POWER(id, req.getUserId(), (byte)(req.getValue() == 0 ? 0x00 : 0x01));
         run(commMsg.getBuffer());
         return true;
@@ -102,7 +102,7 @@ public class VmsServerRequestSender {
      * @return
      */
     public boolean controlLuminance(Long id, VmsControlDto.VmsControlReq req) {
-        log.error("controlLuminance: {}, {}", id, req);
+        log.info("controlLuminance: {}, {}", id, req);
         CENTER_VMS_REQ_LUMINANCE commMsg = new CENTER_VMS_REQ_LUMINANCE(id, req.getUserId(), (byte)req.getValue().intValue());
         run(commMsg.getBuffer());
         return true;
@@ -115,7 +115,7 @@ public class VmsServerRequestSender {
      * @return
      */
     public boolean controlParam(Long id, VmsControlDto.VmsControlParamReq req) {
-        log.error("controlParam: {}, {}", id, req);
+        log.info("controlParam: {}, {}", id, req);
         CENTER_VMS_REQ_PARAM commMsg = new CENTER_VMS_REQ_PARAM(id, req);
         run(commMsg.getBuffer());
         return true;

+ 5 - 5
src/main/java/com/its/api/xnetudp/thread/CenterCommServerReceiver.java

@@ -59,7 +59,7 @@ public class CenterCommServerReceiver {
         // VMS 통신 서버는 Sender, Receiver 위치가 바뀌었음. ==> 서버 수정했음.
         //if (CENTER_COMM_DEFINE.INT_ID_VMS_OPER == data.getSendId() && CENTER_COMM_DEFINE.INT_ID_VMS_SERVER == data.getRecvId()) {
         if (CENTER_COMM_DEFINE.INT_ID_VMS_SERVER == data.getSendId()) {
-            log.error("RECV VMS Server Message[0xFF]: Length: {} Bytes.", data.getLength());
+            log.info("RECV VMS Server Message[0xFF]: Length: {} Bytes.", data.getLength());
             //log.error("VMS PACKET: {}", SysUtils.byteArrayToHex(data.getBody()));
             if (data.getLength() > 0) {
                 ByteBuffer byteBuffer = ByteBuffer.wrap(data.getBody());
@@ -69,7 +69,7 @@ public class CenterCommServerReceiver {
                 byte count;
                 byte opCode = byteBuffer.get();
                 byte msgSeq = byteBuffer.get();
-                log.error("OP CODE: {}, MsgSeq: {}", opCode, msgSeq);
+                log.info("OP CODE: {}, MsgSeq: {}", opCode, msgSeq);
                 switch(opCode) {
                     case CENTER_COMM_DEFINE.INT_OP_VMS_FORM_SAVE:
                         byte[] saveDt  = new byte[CENTER_COMM_DEFINE.INT_VMS_MAX_DATETIME];
@@ -130,7 +130,7 @@ public class CenterCommServerReceiver {
                         short normal = byteBuffer.getShort();
                         short module = byteBuffer.getShort();
                         count = byteBuffer.get();
-                        log.error("INT_OP_VMS_STATE_RES: total({}), error({}), normal({}), module({}), count: {} EA.", total, error, normal, module, count);
+                        log.info("INT_OP_VMS_STATE_RES: total({}), error({}), normal({}), module({}), count: {} EA.", total, error, normal, module, count);
                         for (int ii = 0; ii < count; ii++) {
                             vmsId = new byte[CENTER_COMM_DEFINE.INT_VMS_MAX_ID];
                             byteBuffer.get(vmsId);
@@ -177,11 +177,11 @@ public class CenterCommServerReceiver {
                                     vmsId[jj] = ' ';
                                 }
                             }
-                            //log.error("{}, VmsId: {}, ModuleHor: {}, ModuleVer: {}", ii+1, new String(vmsId).trim(), ModuleHorizontal, ModuleVertical);
+                            //log.info("{}, VmsId: {}, ModuleHor: {}, ModuleVer: {}", ii+1, new String(vmsId).trim(), ModuleHorizontal, ModuleVertical);
                         }
                         break;
                     default:
-                        log.error("Other opCode: {}", opCode);
+                        log.info("Other opCode: {}", opCode);
                         break;
                 }
             }