Browse Source

add r28 protocol

shjung 1 year ago
parent
commit
31b6158e50

+ 1 - 0
conf/tsi-comm-server.pid

@@ -0,0 +1 @@
+2220

+ 4 - 0
conf/tsi-comm-server.yml

@@ -0,0 +1,4 @@
+# Application Configure
+application:
+  cvim-server:
+    server-id: 1

+ 1 - 1
pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-parent</artifactId>
-        <version>2.3.11.RELEASE</version>
+        <version>2.4.13</version>
         <relativePath/> <!-- lookup parent from repository -->
     </parent>
 

+ 2 - 0
src/main/java/com/tsi/comm/server/config/TsiCvimServerConfig.java

@@ -14,6 +14,7 @@ import javax.annotation.PostConstruct;
 @ConfigurationProperties(prefix = "application.cvim-server")
 public class TsiCvimServerConfig extends NettyServerConfig {
 
+    private int serverId = 0;
     private int maxConnection = 0;
     private boolean loggingThread = false;
     private int packetWorkers = 0;
@@ -45,6 +46,7 @@ public class TsiCvimServerConfig extends NettyServerConfig {
         }
 
         log.info("[{}] -------------------------", this.getClass().getSimpleName());
+        log.info("[{}]              serverId: {}", this.getClass().getSimpleName(), this.serverId);
         log.info("[{}]         maxConnection: {}", this.getClass().getSimpleName(), this.maxConnection);
         log.info("[{}]         loggingThread: {}", this.getClass().getSimpleName(), this.loggingThread);
         log.info("[{}]         packetWorkers: {}", this.getClass().getSimpleName(), this.packetWorkers);

+ 8 - 9
src/main/java/com/tsi/comm/server/kafka/KafkaConsumerService.java

@@ -1,6 +1,8 @@
 package com.tsi.comm.server.kafka;
 
+import com.tsi.comm.server.config.TsiCvimServerConfig;
 import com.tsi.comm.server.config.TsiKafkaProducerConfig;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.kafka.clients.consumer.Consumer;
 import org.apache.kafka.common.TopicPartition;
@@ -15,18 +17,15 @@ import javax.annotation.PostConstruct;
 import java.util.Collection;
 
 @Slf4j
+@RequiredArgsConstructor
 @Service
 public class KafkaConsumerService {
 
-    private final TsiKafkaProducerConfig config;
+    private final TsiCvimServerConfig config;
+    private final TsiKafkaProducerConfig producerConfig;
 
-    //private KafkaConsumer<String, byte[]> consumer;
     private ConcurrentMessageListenerContainer<String, Long> kafkaListenerContainer;
 
-    public KafkaConsumerService(TsiKafkaProducerConfig config) {
-        this.config = config;
-    }
-
     @PostConstruct
     void init() {
         log.info("[{}] ------------------", this.getClass().getSimpleName());
@@ -43,8 +42,8 @@ public class KafkaConsumerService {
             return;
         }
 
-        ContainerProperties containerProperties = new ContainerProperties(TsiKafkaProducerConfig.CVIM_PING);
-        containerProperties.setGroupId(this.config.getGroupId());
+        ContainerProperties containerProperties = new ContainerProperties(TsiKafkaProducerConfig.CVIM_PING+this.config.getServerId());
+        containerProperties.setGroupId(this.producerConfig.getGroupId());
         containerProperties.setPollTimeout(5000);
         //containerProperties.setAckMode(ContainerProperties.AckMode.MANUAL);
         containerProperties.setMessageListener(new TsiKafkaConsumerWorker());
@@ -61,7 +60,7 @@ public class KafkaConsumerService {
             }
         });
 
-        ConsumerFactory<String, Long> consumerFactory = new DefaultKafkaConsumerFactory<>(this.config.getConsumerPropertiesMap());
+        ConsumerFactory<String, Long> consumerFactory = new DefaultKafkaConsumerFactory<>(this.producerConfig.getConsumerPropertiesMap());
         this.kafkaListenerContainer = new ConcurrentMessageListenerContainer<>(consumerFactory, containerProperties);
         this.kafkaListenerContainer.setBeanName("consumer");
         this.kafkaListenerContainer.setConcurrency(1);

+ 25 - 21
src/main/java/com/tsi/comm/server/kafka/KafkaProducerService.java

@@ -2,6 +2,7 @@ package com.tsi.comm.server.kafka;
 
 import com.tsi.app.common.kafka.KafkaProducerFactory;
 import com.tsi.app.common.utils.TimeUtils;
+import com.tsi.comm.server.config.TsiCvimServerConfig;
 import com.tsi.comm.server.config.TsiKafkaProducerConfig;
 import com.tsi.comm.server.mybatis.vo.AbstractDbmsVo;
 import com.tsi.comm.server.mybatis.vo.AlarmOccrVo;
@@ -31,7 +32,8 @@ import java.util.concurrent.TimeUnit;
 @Service
 public class KafkaProducerService {
 
-    private final TsiKafkaProducerConfig config;
+    private final TsiCvimServerConfig config;
+    private final TsiKafkaProducerConfig producerConfig;
     private final TsiCvimDbmsProcess tsiCvimDbmsService;
 
     private KafkaTemplate<String, byte[]> cvimProducer;
@@ -42,8 +44,9 @@ public class KafkaProducerService {
 
     //ProducerResultCallback callback;
 
-    public KafkaProducerService(TsiKafkaProducerConfig config, TsiCvimDbmsProcess tsiCvimDbmsService) {
+    public KafkaProducerService(TsiCvimServerConfig config, TsiKafkaProducerConfig producerConfig, TsiCvimDbmsProcess tsiCvimDbmsService) {
         this.config = config;
+        this.producerConfig = producerConfig;
         this.tsiCvimDbmsService = tsiCvimDbmsService;
     }
 
@@ -51,31 +54,31 @@ public class KafkaProducerService {
     void init() {
         //this.callback = new ProducerResultCallback();
 
-        if (this.config.isMultiConnect()) {
+        if (this.producerConfig.isMultiConnect()) {
             // 각각의 Producer 에 대하여 KafkaTemplate 를 생성해서 사용한다.
-            if (this.config.isEnableCvim()) {
-                this.cvimProducer = KafkaProducerFactory.createByteArrayTemplate(this.config.getCvimServers(), this.config.props);
+            if (this.producerConfig.isEnableCvim()) {
+                this.cvimProducer = KafkaProducerFactory.createByteArrayTemplate(this.producerConfig.getCvimServers(), this.producerConfig.props);
                 this.cvimProducer.setDefaultTopic(TsiKafkaProducerConfig.CVIM_RAW_TOPIC);
             }
-            if (this.config.isEnableNode()) {
-                this.nodeProducer = KafkaProducerFactory.createByteArrayTemplate(this.config.getNodeServers(), this.config.props);
+            if (this.producerConfig.isEnableNode()) {
+                this.nodeProducer = KafkaProducerFactory.createByteArrayTemplate(this.producerConfig.getNodeServers(), this.producerConfig.props);
             }
-            if (this.config.isEnableTest()) {
-                this.testProducer = KafkaProducerFactory.createByteArrayTemplate(this.config.getTestServers(), this.config.props);
+            if (this.producerConfig.isEnableTest()) {
+                this.testProducer = KafkaProducerFactory.createByteArrayTemplate(this.producerConfig.getTestServers(), this.producerConfig.props);
                 this.testProducer.setDefaultTopic(TsiKafkaProducerConfig.TEST_TOPIC);
             }
         }
         else {
             // 하나의 Producer KafkaTemplate 로 데이터를 전송하는 경우
             // 동일한 KafkaTemplate 를 사용한다.
-            KafkaTemplate<String, byte[]> producer = KafkaProducerFactory.createByteArrayTemplate(this.config.getBootstrapServers(), this.config.props);
-            if (this.config.isEnableCvim()) {
+            KafkaTemplate<String, byte[]> producer = KafkaProducerFactory.createByteArrayTemplate(this.producerConfig.getBootstrapServers(), this.producerConfig.props);
+            if (this.producerConfig.isEnableCvim()) {
                 this.cvimProducer = producer;
             }
-            if (this.config.isEnableNode()) {
+            if (this.producerConfig.isEnableNode()) {
                 this.nodeProducer = producer;
             }
-            if (this.config.isEnableTest()) {
+            if (this.producerConfig.isEnableTest()) {
                 this.testProducer = producer;
                 this.testProducer.setDefaultTopic(TsiKafkaProducerConfig.TEST_TOPIC);
             }
@@ -94,8 +97,8 @@ public class KafkaProducerService {
 
     public void createPingProducer() {
         Map<String, Object> props = new HashMap<>();
-        props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, this.config.getBootstrapServers());
-        props.put(ProducerConfig.ACKS_CONFIG, this.config.getConsumerAckConfig());
+        props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, this.producerConfig.getBootstrapServers());
+        props.put(ProducerConfig.ACKS_CONFIG, this.producerConfig.getConsumerAckConfig());
         props.put(ProducerConfig.RETRIES_CONFIG, 0);
         props.put(ProducerConfig.LINGER_MS_CONFIG, 1);
         props.put(ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG, 3000);
@@ -105,7 +108,7 @@ public class KafkaProducerService {
         props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, org.apache.kafka.common.serialization.LongSerializer.class);
 
         this.pingProducer = KafkaProducerFactory.createProducerTemplate(props);
-        this.pingProducer.setDefaultTopic(TsiKafkaProducerConfig.CVIM_PING);
+        this.pingProducer.setDefaultTopic(TsiKafkaProducerConfig.CVIM_PING+this.config.getServerId());
     }
     public void shutdown() {
         try {
@@ -168,7 +171,7 @@ public class KafkaProducerService {
             @Override
             public void onSuccess(SendResult<String, Long> result) {
                 long recvNanoTime = System.nanoTime();
-                long sendTime = TimeUnit.MICROSECONDS.convert(recvNanoTime - sendNanoTime, TimeUnit.NANOSECONDS);
+                long sendTime = TimeUnit.MICROSECONDS.convert(Math.abs(recvNanoTime - sendNanoTime), TimeUnit.NANOSECONDS);
                 TsiTpmsManager.getInstance().getKafkaTransVo().setSendTm(sendTime);
                 log.info("send ping success: {}, {}", sendNanoTime, TimeUtils.elapsedTimeStr(recvNanoTime - sendNanoTime));
 
@@ -178,7 +181,7 @@ public class KafkaProducerService {
                     if (alarmConfig != null && sendTime > alarmConfig.getValue()) {
                         AlarmOccrVo alarm = new AlarmOccrVo(AbstractDbmsVo.DBMS_ALARM_OCCR_HS);
                         alarm.setAlarmCode(TsiAlarmConfigVo.KAFKA_02);
-                        alarm.setAlarmTarget(config.getBootstrapServers());
+                        alarm.setAlarmTarget(producerConfig.getBootstrapServers());
                         alarm.setAlarmValue(Long.toString(sendTime));
                         tsiCvimDbmsService.add(alarm, (int) Thread.currentThread().getId());
                     }
@@ -187,10 +190,11 @@ public class KafkaProducerService {
             @Override
             public void onFailure(Throwable ex) {
                 long recvNanoTime = System.nanoTime();
+                TsiTpmsManager.getInstance().getKafkaTransVo().setSendNanoTime(0);
                 KafkaTransVo stat = new KafkaTransVo(AbstractDbmsVo.DBMS_KAFKA_TRANS_HS);
                 stat.setHostName(TsiTpmsManager.getInstance().getKafkaTransVo().getHostName());
                 stat.setStatus(0);
-                stat.setSendTm(TimeUnit.MICROSECONDS.convert(recvNanoTime - sendNanoTime, TimeUnit.NANOSECONDS));
+                stat.setSendTm(TimeUnit.MICROSECONDS.convert(Math.abs(recvNanoTime - sendNanoTime), TimeUnit.NANOSECONDS));
                 stat.setRecvTm(0);
                 tsiCvimDbmsService.add(stat, (int)Thread.currentThread().getId());
                 log.error("send ping failed: {}, {}, {}", sendNanoTime, TimeUtils.elapsedTimeStr(recvNanoTime - sendNanoTime), ex.getMessage());
@@ -202,7 +206,7 @@ public class KafkaProducerService {
                 }
                 AlarmOccrVo alarm = new AlarmOccrVo(AbstractDbmsVo.DBMS_ALARM_OCCR_HS);
                 alarm.setAlarmCode(TsiAlarmConfigVo.KAFKA_01);
-                alarm.setAlarmTarget(config.getBootstrapServers());
+                alarm.setAlarmTarget(producerConfig.getBootstrapServers());
                 alarm.setAlarmValue(value);
                 tsiCvimDbmsService.add(alarm, (int)Thread.currentThread().getId());
 
@@ -213,7 +217,7 @@ public class KafkaProducerService {
     public void sendCvim(long key, byte[] data) {
         if (this.cvimProducer != null) {
             try {
-                if (this.config.isMultiConnect()) {
+                if (this.producerConfig.isMultiConnect()) {
                     this.cvimProducer.sendDefault(Long.toString(key), data);
                 }
                 else {

+ 2 - 10
src/main/java/com/tsi/comm/server/kafka/TsiKafkaConsumerWorker.java

@@ -31,19 +31,11 @@ public class TsiKafkaConsumerWorker implements MessageListener<String, Long> {
         stat.setHostName(TsiTpmsManager.getInstance().getKafkaTransVo().getHostName());
         stat.setStatus(1);
         if (TsiTpmsManager.getInstance().getKafkaTransVo().getSendNanoTime() == sendNanoTime) {
-            if (TsiTpmsManager.getInstance().getKafkaTransVo().getSendTm() == 0) {
-                try {
-                    log.info("Oops... Receive getting faster.");
-                    Thread.sleep(200);
-                }
-                catch (Exception e) {
-                }
-            }
             stat.setSendTm(TsiTpmsManager.getInstance().getKafkaTransVo().getSendTm());
-            stat.setRecvTm(TimeUnit.MICROSECONDS.convert(recvNanoTime - sendNanoTime, TimeUnit.NANOSECONDS));
+            stat.setRecvTm(TimeUnit.MICROSECONDS.convert(Math.abs(recvNanoTime - sendNanoTime), TimeUnit.NANOSECONDS));
         }
         else {
-            stat.setRecvTm(TimeUnit.MICROSECONDS.convert(recvNanoTime - sendNanoTime, TimeUnit.NANOSECONDS));
+            stat.setRecvTm(TimeUnit.MICROSECONDS.convert(Math.abs(recvNanoTime - sendNanoTime), TimeUnit.NANOSECONDS));
             stat.setSendTm(stat.getRecvTm());
             log.info("recv ping success, sendNanoTime miss match: {}, {}", sendNanoTime, TimeUtils.elapsedTimeStr(recvNanoTime - sendNanoTime));
         }

+ 1 - 0
src/main/java/com/tsi/comm/server/mybatis/vo/CommStatusVo.java

@@ -9,6 +9,7 @@ import lombok.ToString;
 @ToString
 public class CommStatusVo extends AbstractDbmsVo {
 
+    protected int id;
     protected int sessions;
     protected long trans;
     protected long bytes;

+ 24 - 18
src/main/java/com/tsi/comm/server/process/dbms/TsiCvimDbmsWorker.java

@@ -70,25 +70,31 @@ public class TsiCvimDbmsWorker extends AbstractTsiCvimWorker implements Runnable
 
         if (object instanceof AbstractDbmsVo) {
             AbstractDbmsVo dbmsVo = (AbstractDbmsVo)object;
-            if (dbmsVo.getDbmsType() == AbstractDbmsVo.DBMS_TPMS_STAT_1S) {
-                this.tsiDatabaseMapper.insertCommTpsHs((CommStatusVo) dbmsVo);
-                job = "CommTpHs";
-                count = 1;
-            }
-            else if (dbmsVo.getDbmsType() == AbstractDbmsVo.DBMS_KAFKA_TRANS_HS) {
-                this.tsiDatabaseMapper.insertKafkaTransHs((KafkaTransVo) dbmsVo);
-                job = "KafkaTransHs";
-                count = 1;
-            }
-            else if (dbmsVo.getDbmsType() == AbstractDbmsVo.DBMS_NODE_STATUS) {
-                this.tsiDatabaseMapper.updateNodeStatus((NodeStatusVo)object);
-                job = "NodeStatus";
-                count = 1;
+            try {
+                if (dbmsVo.getDbmsType() == AbstractDbmsVo.DBMS_TPMS_STAT_1S) {
+                    job = "CommTpHs";
+                    count = 1;
+                    this.tsiDatabaseMapper.insertCommTpsHs((CommStatusVo) dbmsVo);
+                }
+                else if (dbmsVo.getDbmsType() == AbstractDbmsVo.DBMS_KAFKA_TRANS_HS) {
+                    job = "KafkaTransHs";
+                    count = 1;
+                    this.tsiDatabaseMapper.insertKafkaTransHs((KafkaTransVo) dbmsVo);
+                }
+                else if (dbmsVo.getDbmsType() == AbstractDbmsVo.DBMS_NODE_STATUS) {
+                    job = "NodeStatus";
+                    count = 1;
+                    this.tsiDatabaseMapper.updateNodeStatus((NodeStatusVo)object);
+                }
+                else if (dbmsVo.getDbmsType() == AbstractDbmsVo.DBMS_ALARM_OCCR_HS) {
+                    job = "AlarmOccr";
+                    count = 1;
+                    this.tsiDatabaseMapper.insertAlarmOccrHs((AlarmOccrVo)object);
+                }
             }
-            else if (dbmsVo.getDbmsType() == AbstractDbmsVo.DBMS_ALARM_OCCR_HS) {
-                this.tsiDatabaseMapper.insertAlarmOccrHs((AlarmOccrVo)object);
-                job = "AlarmOccr";
-                count = 1;
+            catch (Exception e) {
+                log.error("{}, {}", job, dbmsVo);
+                log.error("{}", e.getMessage());
             }
         }
         else {

+ 8 - 10
src/main/java/com/tsi/comm/server/process/logging/TsiCvimLoggingWorker.java

@@ -106,28 +106,26 @@ public class TsiCvimLoggingWorker extends AbstractTsiCvimWorker implements Runna
         }
 
         MDC.put("id", Long.toString(packet.getNodeId()));
-        log.info("{} Node: {}, {}: {} {}", collectTime, packet.getNodeId(), String.format("%10s", "Q-Add"), TimeUtils.elapsedTimeStr(add), Thread.currentThread().getName());
-        log.info("{} Node: {}, {}: {} {}", collectTime, packet.getNodeId(), String.format("%10s", "Q-Pop"), TimeUtils.elapsedTimeStr(pop), Thread.currentThread().getName());
-        log.info("{} Node: {}, {}: {} {}", collectTime, packet.getNodeId(), String.format("%10s", "Parsing"), TimeUtils.elapsedTimeStr(par), Thread.currentThread().getName());
-        log.info("{} Node: {}, {}: {} {}", collectTime, packet.getNodeId(), String.format("%10s", "Kafka"), TimeUtils.elapsedTimeStr(kaf), Thread.currentThread().getName());
-        log.info("{} Node: {}, {}: {} {}, {} bytes, Average {}",
+//        log.info("{} Node: {},      Q-Add: {} {}", collectTime, packet.getNodeId(), TimeUtils.elapsedTimeStr(add), Thread.currentThread().getName());
+//        log.info("{} Node: {},      Q-Pop: {} {}", collectTime, packet.getNodeId(), TimeUtils.elapsedTimeStr(pop), Thread.currentThread().getName());
+//        log.info("{} Node: {},    Parsing: {} {}", collectTime, packet.getNodeId(), TimeUtils.elapsedTimeStr(par), Thread.currentThread().getName());
+//        log.info("{} Node: {},      kafka: {} {}", collectTime, packet.getNodeId(), TimeUtils.elapsedTimeStr(kaf), Thread.currentThread().getName());
+        log.info("{} Node: {},        Job: {} {}, {} bytes, Average {}",
                 collectTime,
                 packet.getNodeId(),
-                String.format("%10s", "Job"),
                 TimeUtils.elapsedTimeStr(job),
                 Thread.currentThread().getName(),
                 packet.getPacketLength(),
                 TimeUtils.elapsedTimeStr(packet.getAvg()));
         if (mongo > 0) {
-            log.info("{} Node: {}, {}: {} {}", collectTime, packet.getNodeId(), String.format("%10s", "MongoDb"), TimeUtils.elapsedTimeStr(mongo), Thread.currentThread().getName());
-            log.info("{} Node: {}, {}: {} {}",
+            log.info("{} Node: {},    MongoDb: {} {}", collectTime, packet.getNodeId(), TimeUtils.elapsedTimeStr(mongo), Thread.currentThread().getName());
+            log.info("{} Node: {},  Total Job: {} {}",
                     collectTime,
                     packet.getNodeId(),
-                    String.format("%10s", "Total Job"),
                     TimeUtils.elapsedTimeStr(jobTotal),
                     Thread.currentThread().getName());
         }
-        log.info("{} Node: {}, ====", collectTime, packet.getNodeId());
+//        log.info("{} Node: {}, ====", collectTime, packet.getNodeId());
         MDC.clear();
     }
 

+ 48 - 31
src/main/java/com/tsi/comm/server/protocol/TsiCpuPacket.java

@@ -10,7 +10,6 @@ import com.tsi.app.common.cpu.enums.eTimeReliability;
 import com.tsi.app.common.utils.ByteUtils;
 import com.tsi.app.common.utils.CRC16Utils;
 import com.tsi.app.common.utils.HexString;
-import com.tsi.app.common.utils.TimeUtils;
 import com.tsi.app.common.xnet.NettyUtils;
 import com.tsi.comm.server.mongo.dto.TcsNodeStatus;
 import com.tsi.comm.server.repository.TsiNodeAddManager;
@@ -66,6 +65,10 @@ public class TsiCpuPacket extends AbstractTsiPacket {
     uint8_t nodeid[4];  // big endian
     */
 
+    // TODO: 20240722 Protocol R28 Added
+    public static final byte PROTOCOL_R27 = 0x01;
+    public static final byte PROTOCOL_R28 = 0x1C;   // 28
+
     public static final byte STX1 = 0x7E;
     public static final byte STX2 = 0x7E;
 
@@ -128,17 +131,17 @@ public class TsiCpuPacket extends AbstractTsiPacket {
     }
 
     // FOR CVIM packet
-    public TsiCpuPacket(long nodeId, byte[] value) {
-        super(nodeId, TimeUtils.currentTimeSeconds(), System.nanoTime(), 0, 0);
-        this.buf = value;   // CVIM Header 를 포함한 내부 IPC 형식 데이터임
-        int nodeLength = this.buf.length - TsiCpuPacket.SIZE_IPC_SIZE;
-        this.cvimData = new byte[TsiCpuPacket.SIZE_IPC_SIZE];
-        System.arraycopy(this.buf, 0, this.cvimData, 0, TsiCpuPacket.SIZE_IPC_SIZE);
-        if (nodeLength > 0) {
-            this.nodeData = new byte[nodeLength];
-            System.arraycopy(this.buf, TsiCpuPacket.SIZE_IPC_SIZE, this.nodeData, 0, nodeLength);
-        }
-    }
+//    public TsiCpuPacket(long nodeId, byte[] value) {
+//        super(nodeId, TimeUtils.currentTimeSeconds(), System.nanoTime(), 0, 0);
+//        this.buf = value;   // CVIM Header 를 포함한 내부 IPC 형식 데이터임
+//        int nodeLength = this.buf.length - TsiCpuPacket.SIZE_IPC_SIZE;
+//        this.cvimData = new byte[TsiCpuPacket.SIZE_IPC_SIZE];
+//        System.arraycopy(this.buf, 0, this.cvimData, 0, TsiCpuPacket.SIZE_IPC_SIZE);
+//        if (nodeLength > 0) {
+//            this.nodeData = new byte[nodeLength];
+//            System.arraycopy(this.buf, TsiCpuPacket.SIZE_IPC_SIZE, this.nodeData, 0, nodeLength);
+//        }
+//    }
 
     protected byte getStx1() {
         if (this.buf != null) return this.buf[INDEX_STX1];
@@ -163,20 +166,20 @@ public class TsiCpuPacket extends AbstractTsiPacket {
      *  Make cvim-raw packet
      */
     protected void makeCvimPacket() {
-        int length = this.buf == null ? 0 : this.buf.length;
+        final int packetLength = (this.buf == null) ? 0 : this.buf.length;
 
-        this.cvimData = new byte[SIZE_IPC_SIZE + length];
+        this.cvimData = new byte[SIZE_IPC_SIZE + packetLength];
 
         // cvim-raw header
         System.arraycopy(this.timespec.bytes(), 0, this.cvimData, POS_IPC_TIMESPEC, SIZE_TIMESPEC);
         ByteUtils.setUnsignedInt(this.cvimData, POS_IPC_IPADDR, getRemoteIp());
         ByteUtils.setUnsignedShort(this.cvimData, POS_IPC_PORT, getRemotePort());
-        this.cvimData[POS_IPC_CONNECT] = opCode == (byte)eOpCode.TSI_CPU_SIGNAL_NOTIFY.getValue() ? CONNECT : DISCONNECT;
+        this.cvimData[POS_IPC_CONNECT] = (opCode == (byte)eOpCode.TSI_CPU_SIGNAL_NOTIFY.getValue()) ? CONNECT : DISCONNECT;
         ByteUtils.setUnsignedInt(this.cvimData, POS_IPC_NODEID, this.nodeId);
 
         // cvim-raw body
-        if (length > 0) {
-            System.arraycopy(this.buf, 0, this.cvimData, POS_IPC_PACKET, length);
+        if (packetLength > 0) {
+            System.arraycopy(this.buf, 0, this.cvimData, POS_IPC_PACKET, packetLength);
         }
         //log.error("CVIM: {}", HexString.fromBytes(this.cvimData));
     }
@@ -185,27 +188,27 @@ public class TsiCpuPacket extends AbstractTsiPacket {
      *  Make cvim-raw packet
      */
     protected void makeAddNodeCvimPaket(TsiCpuPacket cpuPacket, byte[] packet) {
-        int length = packet == null ? 0 : packet.length;
-
+        final int packetLength = (packet == null) ? 0 : packet.length;
         final int headSize = SIZE_IPC_SIZE + 6;
-        cpuPacket.cvimData = new byte[headSize + length + 2];   // cpu packet 6 byte(nodeid 제외), crc 2 byte
+
+        cpuPacket.cvimData = new byte[headSize + packetLength + 2];   // cpu packet 6 byte(nodeid 제외), crc 2 byte
 
         // cvim-raw header
         System.arraycopy(timespec.bytes(), 0, cpuPacket.cvimData, POS_IPC_TIMESPEC, SIZE_TIMESPEC);
         ByteUtils.setUnsignedInt(cpuPacket.cvimData, POS_IPC_IPADDR, getRemoteIp());
         ByteUtils.setUnsignedShort(cpuPacket.cvimData, POS_IPC_PORT, getRemotePort());
-        cpuPacket.cvimData[POS_IPC_CONNECT] = opCode == (byte)eOpCode.TSI_CPU_SIGNAL_NOTIFY.getValue() ? CONNECT : DISCONNECT;
+        cpuPacket.cvimData[POS_IPC_CONNECT] = (opCode == (byte)eOpCode.TSI_CPU_SIGNAL_NOTIFY.getValue()) ? CONNECT : DISCONNECT;
         ByteUtils.setUnsignedInt(cpuPacket.cvimData, POS_IPC_NODEID, cpuPacket.nodeId);
 
         cpuPacket.cvimData[SIZE_IPC_SIZE+INDEX_STX1] = getStx1();
         cpuPacket.cvimData[SIZE_IPC_SIZE+INDEX_STX2] = getStx2();
-        ByteUtils.setUnsignedShort(cpuPacket.cvimData, SIZE_IPC_SIZE+INDEX_LENGTH, length+2);
+        ByteUtils.setUnsignedShort(cpuPacket.cvimData, SIZE_IPC_SIZE+INDEX_LENGTH, packetLength+2);
         cpuPacket.cvimData[SIZE_IPC_SIZE+INDEX_OPCODE] = (byte)getOpCode();
         cpuPacket.cvimData[SIZE_IPC_SIZE+INDEX_VERSION] = getDataVer();
 
         // cvim-raw body
-        if (length > 0) {
-            System.arraycopy(packet, 0, cpuPacket.cvimData, headSize, length);
+        if (packetLength > 0) {
+            System.arraycopy(packet, 0, cpuPacket.cvimData, headSize, packetLength);
         }
         // 체크섬 계산하지 않음
     }
@@ -215,20 +218,34 @@ public class TsiCpuPacket extends AbstractTsiPacket {
         // 0 단계. STX1, STX2 체크
         if (this.buf[INDEX_STX1] != STX1 || this.buf[INDEX_STX2] != STX2) {
             log.info("Node: {}, STX Error: {}, {}", nodeId, this.buf[INDEX_STX1], this.buf[INDEX_STX2]);
+            log.error("{}", HexString.fromBytes(this.buf));
             return false;
         }
 
         // 1 단계. 패킷 길이 체크
-        if (this.length != ( SIZE_PACKET_DATA + (SIZE_STATUS_DATA * this.count) ) ) {
-            log.info("Node: {}, Length Error: {}, status count: {}, {}", nodeId, this.length, this.count, SIZE_PACKET_DATA + (SIZE_STATUS_DATA * this.count));
+        // TODO: 20240722, Protocol R28 ADDED
+//        int reqLength = SIZE_PACKET_DATA + (SIZE_STATUS_DATA * this.count);
+//        if (this.buf[INDEX_VERSION] == PROTOCOL_R28) {
+//            reqLength = SIZE_PACKET_DATA + (SIZE_STATUS_DATA * this.count) + 1; // ADD CPU byte packet
+//        }
+//        if (this.length != reqLength ) {
+//            log.info("Node: {}, Length Error: {}, Version: {}, status count: {}, {}", nodeId, this.length, this.buf[INDEX_VERSION],
+//                    this.count, reqLength);
+//            log.error("{}", HexString.fromBytes(this.buf));
+//            return false;
+//        }
+        int reqLength = SIZE_PACKET_DATA + (SIZE_STATUS_DATA * this.count);
+        if (this.length < reqLength ) {
+            log.info("Node: {}, Length Error: {}, Version: {}, status count: {}, {}", nodeId, this.length, this.buf[INDEX_VERSION],
+                    this.count, reqLength);
+            log.error("{}", HexString.fromBytes(this.buf));
             return false;
         }
-
         // 2단계. 체크섬
         this.checkSum = ByteUtils.getUnsignedShort(this.buf, this.buf.length-2);
         int calcCheckSum = CRC16Utils.CRC16_ccitt_cvim(this.buf, INDEX_LENGTH, this.length-2);  // 시작인덱스가 있으므로 전체길이로 계산
         if (this.checkSum != calcCheckSum) {
-            log.error("Node: {}, Check Sum Error: recv: {}, calc: {}", nodeId, this.checkSum, calcCheckSum);
+            log.error("Node: {}, Check Sum Error: Version: {}, recv: {}, calc: {}", nodeId, this.buf[INDEX_VERSION], this.checkSum, calcCheckSum);
             log.error("{}", HexString.fromBytes(this.buf));
             return false;
         }
@@ -251,9 +268,9 @@ public class TsiCpuPacket extends AbstractTsiPacket {
         TsiNodeAddVo tsiNodeAddVo = TsiNodeAddManager.getInstance().get(this.nodeId);
         if (tsiNodeAddVo == null) {
             // 연등지 정보가 없는 경우
-            int length = this.buf.length-SIZE_NODE_DUMMY;
-            this.nodeData = new byte[length];
-            System.arraycopy(this.buf, INDEX_NODE_ID, this.nodeData, 0, length);
+            final int addLength = this.buf.length-SIZE_NODE_DUMMY;
+            this.nodeData = new byte[addLength];
+            System.arraycopy(this.buf, INDEX_NODE_ID, this.nodeData, 0, addLength);
             return true;
         }
 

+ 2 - 1
src/main/java/com/tsi/comm/server/repository/TsiTpmsManager.java

@@ -66,10 +66,11 @@ public class TsiTpmsManager {
         this.readBPD.add(packet.getBuf().length);
     }
 
-    public void resetSecond() {
+    public void resetSecond(int serverId) {
         CommStatusVo stat = new CommStatusVo(AbstractDbmsVo.DBMS_TPMS_STAT_1S);
         long trans = this.readTPS.reset();
         long bytes = this.readBPS.reset();
+        stat.setId(serverId);
         stat.setTrans(trans);
         stat.setBytes(bytes);
         stat.setSessions(TsiSessionManager.getInstance().get());

+ 5 - 2
src/main/java/com/tsi/comm/server/scheduler/TsiCommScheduler.java

@@ -2,6 +2,7 @@ package com.tsi.comm.server.scheduler;
 
 import com.tsi.app.common.utils.Elapsed;
 import com.tsi.app.common.utils.TimeUtils;
+import com.tsi.comm.server.config.TsiCvimServerConfig;
 import com.tsi.comm.server.kafka.KafkaConsumerService;
 import com.tsi.comm.server.kafka.KafkaProducerService;
 import com.tsi.comm.server.mybatis.TsiDatabaseService;
@@ -23,11 +24,13 @@ import javax.annotation.PreDestroy;
 @Component
 public class TsiCommScheduler {
 
+    private final TsiCvimServerConfig config;
     private final TsiDatabaseService tsiDatabaseService;
     private final KafkaProducerService kafkaProducerService;
     private final KafkaConsumerService kafkaConsumerService;
 
-    public TsiCommScheduler(TsiDatabaseService tsiDatabaseService, KafkaProducerService kafkaProducerService, KafkaConsumerService kafkaConsumerService) {
+    public TsiCommScheduler(TsiCvimServerConfig config, TsiDatabaseService tsiDatabaseService, KafkaProducerService kafkaProducerService, KafkaConsumerService kafkaConsumerService) {
+        this.config = config;
         this.tsiDatabaseService = tsiDatabaseService;
         this.kafkaProducerService = kafkaProducerService;
         this.kafkaConsumerService = kafkaConsumerService;
@@ -41,7 +44,7 @@ public class TsiCommScheduler {
     @Scheduled(cron = "* * * * * *")  // 1초 주기 작업 실행
     public void staticsForPacketSecond() {
         Elapsed elapsed = new Elapsed();
-        TsiTpmsManager.getInstance().resetSecond();
+        TsiTpmsManager.getInstance().resetSecond(this.config.getServerId());
         log.info("{}", String.format("%25s: %s", "staticsForPacketSecond", TimeUtils.elapsedTimeStr(elapsed.nanoSeconds())));
     }
 

+ 0 - 2
src/main/java/com/tsi/comm/server/tcp/TsiCvimServer.java

@@ -33,9 +33,7 @@ public class TsiCvimServer extends NettyTcpServer {
 
     @PostConstruct
     public void initialize() {
-        //CvimServerIdleHandler cvimServerIdleHandler = new CvimServerIdleHandler(config.getReaderIdleTimeSeconds(), config.getWriterIdleTimeSeconds(), config.getAllIdleTimeSeconds(), config);
         super.setChannelInitializer(new CvimServerInitializer(this.config));
-        //super.setChannelInitializer(new CvimServerInitializer(cvimServerIdleHandler, cvimServerByteBufMessageDecoder, cvimServerInboundMessageHandler, cvimServerEncoder));
         if (!OS.isWindows()) {
             if (!Epoll.isAvailable()) {
                 Epoll.unavailabilityCause().printStackTrace();

+ 0 - 132
src/main/java/com/tsi/comm/server/tcp/handler/CvimServerIdleHandler.java

@@ -1,132 +0,0 @@
-package com.tsi.comm.server.tcp.handler;
-
-import com.tsi.app.common.app.AppUtils;
-import com.tsi.app.common.xnet.NettyUtils;
-import com.tsi.comm.server.config.TsiCvimServerConfig;
-import com.tsi.comm.server.mybatis.vo.AbstractDbmsVo;
-import com.tsi.comm.server.mybatis.vo.AlarmOccrVo;
-import com.tsi.comm.server.mybatis.vo.NodeStatusVo;
-import com.tsi.comm.server.process.dbms.TsiCvimDbmsProcess;
-import com.tsi.comm.server.process.packet.TsiCvimPacketProcess;
-import com.tsi.comm.server.protocol.TsiCpuDisconnected;
-import com.tsi.comm.server.repository.TsiAlarmManager;
-import com.tsi.comm.server.repository.TsiSessionManager;
-import com.tsi.comm.server.vo.TsiAlarmConfigVo;
-import com.tsi.comm.server.vo.TsiNodeVo;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.handler.timeout.IdleState;
-import io.netty.handler.timeout.IdleStateEvent;
-import io.netty.handler.timeout.IdleStateHandler;
-import lombok.extern.slf4j.Slf4j;
-
-@Slf4j
-//@Component
-//@ChannelHandler.Sharable
-public class CvimServerIdleHandler extends IdleStateHandler {
-
-    private final TsiCvimServerConfig config;
-    private TsiCvimPacketProcess tsiCvimPacketService;
-    private TsiCvimDbmsProcess tsiCvimDbmsService;
-
-    public CvimServerIdleHandler(TsiCvimServerConfig config) {
-        super(5, 0, 0);
-        //super(config.getReaderIdleTimeSeconds(), config.getWriterIdleTimeSeconds(), config.getAllIdleTimeSeconds());
-        this.config = config;
-        this.tsiCvimPacketService = (TsiCvimPacketProcess) AppUtils.getBean(TsiCvimPacketProcess.class);
-        this.tsiCvimDbmsService = (TsiCvimDbmsProcess) AppUtils.getBean(TsiCvimDbmsProcess.class);
-        log.error("Idle Config: {}", this.config.getReaderIdleTimeSeconds());
-    }
-
-    @Override
-    public void channelActive(ChannelHandlerContext ctx) throws Exception {
-
-        // session count increment
-        int sessions = TsiSessionManager.getInstance().add();
-        // IP Address 로 제어기를 판달할 수 있으면 여기서 제어기 등록 여부를 판단해서
-        // 접속 여부를 처리할 수 있다.
-        log.info("{}.++channelActive: {}, {} Sessions.", this.getClass().getSimpleName(), NettyUtils.getAddress(ctx.channel()), sessions);
-        super.channelActive(ctx);
-    }
-
-    @Override
-    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
-        TsiNodeVo nodeVo = TsiSessionManager.getInstance().getNodeVo(ctx.channel());
-        if (nodeVo != null) {
-            nodeVo.setConnect(null);
-            TsiSessionManager.getInstance().removeChannel(ctx.channel());
-
-            // TODO: session disconnect. to be continue
-            NodeStatusVo status = new NodeStatusVo(AbstractDbmsVo.DBMS_NODE_STATUS);
-            status.setNodeId(nodeVo.getNodeId());
-            status.setStatus(0);
-            status.setIpAddr(NettyUtils.getRemoteIpAddress(ctx.channel()));
-            if (TsiSessionManager.getInstance().isServerRun()) {
-                TsiCpuDisconnected packet = new TsiCpuDisconnected(nodeVo.getNodeId(), ctx.channel());
-                packet.setBuf(null);
-                packet.setObj(nodeVo);
-                this.tsiCvimPacketService.add(packet, (int)Thread.currentThread().getId());
-
-                this.tsiCvimDbmsService.add(status, (int)Thread.currentThread().getId());
-            }
-            else {
-                log.error("Node Logout but server not running: {}", status.toString());
-            }
-
-            log.error("{}.channelInactive: Node Channel close: {}, {}", this.getClass().getSimpleName(), nodeVo.getNodeId(), ctx.channel());
-        }
-        // Channel 메모리에서 처리하지 않고 그냥 전역 메모리로 처리함
-        ctx.channel().attr(TsiSessionManager.TSI_NODE_ATTRIBUTE_KEY).set(null);
-        //ctx.channel().attr(TsiCommManager.TSI_NODE_ATTRIBUTE_KEY).getAndSet(null);
-
-        // session count decrement
-        int sessions = TsiSessionManager.getInstance().remove();
-        log.info("{}.channelInactive: {}, {} Sessions.", this.getClass().getSimpleName(), NettyUtils.getAddress(ctx.channel()), sessions);
-
-        super.channelInactive(ctx);
-    }
-
-    @Override
-    protected void channelIdle(ChannelHandlerContext ctx, IdleStateEvent evt) throws Exception {
-
-        log.error("channelIdle: {}", evt.toString());
-        TsiNodeVo nodeVo = TsiSessionManager.getInstance().getNodeVo(ctx.channel());
-        if (nodeVo != null) {
-            log.error("{}.channelIdle: {}, {}, {}", this.getClass().getSimpleName(), nodeVo.getNodeId(), ctx.channel(), evt.state().toString());
-        }
-
-        // 연결이 완료된 후 송수신 데이터가 일정시간 동안 없을 경우 이곳에서 처리
-        if (evt.state() == IdleState.READER_IDLE) {
-            log.error("{}.channelIdle: READER_IDLE: {}", this.getClass().getSimpleName(), NettyUtils.getAddress(ctx.channel()));
-            if (nodeVo == null) {
-                // 통신 접속 후 수신 데이터가 없이 READ 타임아웃이 발생한 경우임
-                if (TsiAlarmManager.getInstance().checkAlarm(TsiAlarmConfigVo.COMM_02)) {
-                    AlarmOccrVo alarm = new AlarmOccrVo(AbstractDbmsVo.DBMS_ALARM_OCCR_HS);
-                    alarm.setAlarmCode(TsiAlarmConfigVo.COMM_02);
-                    alarm.setAlarmTarget(NettyUtils.getRemoteIpAddress(ctx.channel()));
-                    alarm.setAlarmValue(NettyUtils.getRemoteIpAddress(ctx.channel()));
-                    this.tsiCvimDbmsService.add(alarm, (int)Thread.currentThread().getId());
-                    log.warn("Recv Timeout: {}", NettyUtils.getRemoteIpAddress(ctx.channel()));
-                }
-                ctx.channel().close();
-            }
-        } else if (evt.state() == IdleState.WRITER_IDLE) {
-            log.error("{}.channelIdle: WRITER_IDLE: {}", this.getClass().getSimpleName(), NettyUtils.getAddress(ctx.channel()));
-            //ctx.channel().close();
-        } else if (evt.state() == IdleState.ALL_IDLE) {
-            log.error("{}.channelIdle: ALL_IDLE: {}", this.getClass().getSimpleName(), NettyUtils.getAddress(ctx.channel()));
-            //ctx.channel().close();
-        }
-        super.channelIdle(ctx, evt);
-    }
-
-    @Override
-    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
-        TsiNodeVo nodeVo = TsiSessionManager.getInstance().getNodeVo(ctx.channel());
-        if (nodeVo != null) {
-            log.error("{}.exceptionCaught: {}, {}", this.getClass().getSimpleName(), nodeVo.getNodeId(), ctx.channel());
-        }
-        log.error("{}.exceptionCaught: {}", this.getClass().getSimpleName(), NettyUtils.getAddress(ctx.channel()));
-        super.exceptionCaught(ctx, cause);
-        ctx.channel().close();
-    }
-}

+ 10 - 10
src/main/java/com/tsi/comm/server/tcp/handler/CvimServerInboundMessageHandler.java

@@ -38,7 +38,7 @@ public class CvimServerInboundMessageHandler extends ChannelInboundHandlerAdapte
     }
 
     public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
-        log.error("Handler: channelRead: {}", NettyUtils.getRemoteIpAddress(ctx.channel()));
+        //log.error("Handler: channelRead: {}", NettyUtils.getRemoteIpAddress(ctx.channel()));
         if (msg instanceof AbstractTsiPacket) {
             //TsiCpuPacket packet = (TsiCpuPacket)msg;
             //packet.setPop(System.nanoTime());
@@ -77,12 +77,11 @@ public class CvimServerInboundMessageHandler extends ChannelInboundHandlerAdapte
                 this.tsiCvimDbmsService.add(status, (int)Thread.currentThread().getId());
             }
             else {
-                log.error("Node Logout but server not running: {}", status.toString());
+                log.error("{}.channelInactive: Node {}, Logout but server not running: {}", this.getClass().getSimpleName(), nodeVo.getNodeId(), status.toString());
             }
-            log.error("{}.channelInactive: Node Channel close: {}, {}", this.getClass().getSimpleName(), nodeVo.getNodeId(), ctx.channel());
+            log.error("{}.channelInactive: Node {}, Channel close: {}", this.getClass().getSimpleName(), nodeVo.getNodeId(), ctx.channel());
 
             ctx.channel().attr(TsiSessionManager.TSI_NODE_ATTRIBUTE_KEY).set(null);
-            //ctx.channel().attr(TsiCommManager.TSI_NODE_ATTRIBUTE_KEY).getAndSet(null);
         }
 
         // session count decrement
@@ -95,9 +94,9 @@ public class CvimServerInboundMessageHandler extends ChannelInboundHandlerAdapte
         if (e instanceof IdleStateEvent) {
             IdleStateEvent evt = (IdleStateEvent) e;
             TsiNodeVo nodeVo = TsiSessionManager.getInstance().getNodeVo(ctx.channel());
-            if (nodeVo != null) {
-                log.error("{}.channelIdle: {}, {}, {}", this.getClass().getSimpleName(), nodeVo.getNodeId(), ctx.channel(), evt.state().toString());
-            }
+//            if (nodeVo != null) {
+//                log.error("{}.userEventTriggered: {}, {}, {}", this.getClass().getSimpleName(), nodeVo.getNodeId(), ctx.channel(), evt.state().toString());
+//            }
 
             // 연결이 완료된 후 송수신 데이터가 일정시간 동안 없을 경우 이곳에서 처리
             if (evt.state() == IdleState.READER_IDLE) {
@@ -109,17 +108,18 @@ public class CvimServerInboundMessageHandler extends ChannelInboundHandlerAdapte
                         alarm.setAlarmTarget(NettyUtils.getRemoteIpAddress(ctx.channel()));
                         alarm.setAlarmValue(NettyUtils.getRemoteIpAddress(ctx.channel()));
                         this.tsiCvimDbmsService.add(alarm, (int) Thread.currentThread().getId());
-                        log.warn("{}.channelIdle: Recv Timeout: {}", this.getClass().getSimpleName(), NettyUtils.getRemoteIpAddress(ctx.channel()));
+                        log.warn("{}.userEventTriggered: Recv Timeout: {}", this.getClass().getSimpleName(), NettyUtils.getRemoteIpAddress(ctx.channel()));
                     }
+                    ctx.channel().disconnect();
                     ctx.channel().close();
                 }
                 else {
                     // 통신 접속 후 데이터를 한번이라도 수신한 경우에는 스케쥴러에서 처리한다.
                 }
             } else if (evt.state() == IdleState.WRITER_IDLE) {
-                log.error("{}.channelIdle: WRITER_IDLE: {}", this.getClass().getSimpleName(), NettyUtils.getAddress(ctx.channel()));
+                log.error("{}.userEventTriggered: WRITER_IDLE: {}", this.getClass().getSimpleName(), NettyUtils.getAddress(ctx.channel()));
             } else if (evt.state() == IdleState.ALL_IDLE) {
-                log.error("{}.channelIdle: ALL_IDLE: {}", this.getClass().getSimpleName(), NettyUtils.getAddress(ctx.channel()));
+                log.error("{}.userEventTriggered: ALL_IDLE: {}", this.getClass().getSimpleName(), NettyUtils.getAddress(ctx.channel()));
             }
         }
         ctx.fireUserEventTriggered(e);

+ 7 - 8
src/main/java/com/tsi/comm/server/tcp/initializer/CvimServerInitializer.java

@@ -13,14 +13,12 @@ import io.netty.handler.timeout.IdleStateHandler;
 
 public class CvimServerInitializer extends ChannelInitializer<Channel> {
 
-    //private CvimServerIdleHandler cvimServerIdleHandler;
-    private CvimServerByteBufMessageDecoder cvimServerByteBufMessageDecoder;
-    private CvimServerInboundMessageHandler cvimServerInboundMessageHandler;
-    private CvimServerEncoder cvimServerEncoder;
-    private TsiCvimServerConfig config;
+    private final CvimServerByteBufMessageDecoder cvimServerByteBufMessageDecoder;
+    private final CvimServerInboundMessageHandler cvimServerInboundMessageHandler;
+    private final CvimServerEncoder cvimServerEncoder;
+    private final TsiCvimServerConfig config;
 
     public CvimServerInitializer(TsiCvimServerConfig config) {
-        //this.cvimServerIdleHandler = (CvimServerIdleHandler) AppUtils.getBean(CvimServerIdleHandler.class);
         this.cvimServerByteBufMessageDecoder = (CvimServerByteBufMessageDecoder) AppUtils.getBean(CvimServerByteBufMessageDecoder.class);
         this.cvimServerInboundMessageHandler = (CvimServerInboundMessageHandler) AppUtils.getBean(CvimServerInboundMessageHandler.class);
         this.cvimServerEncoder = (CvimServerEncoder) AppUtils.getBean(CvimServerEncoder.class);
@@ -29,11 +27,12 @@ public class CvimServerInitializer extends ChannelInitializer<Channel> {
 
     @Override
     protected void initChannel(Channel channel) throws Exception {
-        //IdleStateHandler idleStateHandler = new IdleStateHandler(this.config.getReaderIdleTimeSeconds(), this.config.getWriterIdleTimeSeconds(), this.config.getAllIdleTimeSeconds());
+        if (this.config.getReaderIdleTimeSeconds() < 5) {
+            this.config.setReaderIdleTimeSeconds(5);
+        }
         IdleStateHandler idleStateHandler = new IdleStateHandler(this.config.getReaderIdleTimeSeconds(), 0, 0);
         ChannelPipeline pipeline = channel.pipeline();
         pipeline.addLast("idleStateHandler", idleStateHandler);
-        //pipeline.addLast("cvimServerIdleHandler", this.cvimServerIdleHandler);
         pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(2048, 2, 2, -2, 0));
         pipeline.addLast("packetDecoder", this.cvimServerByteBufMessageDecoder);
         pipeline.addLast("packetInboundHandler", this.cvimServerInboundMessageHandler);

+ 279 - 294
src/main/java/com/tsi/comm/server/vo/TsiNodeVo.java

@@ -1,28 +1,13 @@
 package com.tsi.comm.server.vo;
 
-import com.tsi.app.common.cpu.dto.TsiCvimAbnormal;
-import com.tsi.app.common.cpu.dto.TsiCvimControl;
 import com.tsi.app.common.cpu.dto.TsiCvimDto;
-import com.tsi.app.common.cpu.dto.TsiCvimStatus;
-import com.tsi.app.common.cpu.enums.eLightsStatus;
-import com.tsi.app.common.cpu.enums.eLightsType;
-import com.tsi.app.common.cpu.enums.eTimeReliability;
-import com.tsi.app.common.utils.ByteUtils;
-import com.tsi.app.common.utils.CRC16Utils;
 import com.tsi.app.common.utils.Counter;
-import com.tsi.app.common.utils.SysUtils;
 import com.tsi.comm.server.protocol.TsiCpuPacket;
 import io.netty.channel.Channel;
 import lombok.Getter;
 import lombok.Setter;
 import lombok.extern.slf4j.Slf4j;
 
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Map;
-
 @Slf4j
 @Getter
 @Setter
@@ -108,177 +93,177 @@ public class TsiNodeVo {
         return null;//this.packet;
     }
 
-    public boolean parsing(byte[] packet) {
-
-        boolean result = true;
-        //long start = System.nanoTime();
-
-        // 0 단계. STX1, STX2 체크
-        if (packet[TsiCpuPacket.INDEX_STX1] != TsiCpuPacket.STX1 || packet[TsiCpuPacket.INDEX_STX2] != TsiCpuPacket.STX2) {
-            log.info("Node: {}, STX Error: {}, {}", nodeId, packet[TsiCpuPacket.INDEX_STX1], packet[TsiCpuPacket.INDEX_STX2]);
-            return false;
-        }
-        //log.info("Node: {}, a: {}", nodeId, TimeUtils.elapsedTime(start));
-        //start = System.nanoTime();
-
-        // 1 단계. 패킷 길이 체크
-        int dataLength = ByteUtils.getUnsignedShort(packet, TsiCpuPacket.INDEX_LENGTH);
-        int statusCount = (int)(packet[TsiCpuPacket.INDEX_STATUS_HDR+3] & 0x7F);
-        if (dataLength != ( TsiCpuPacket.SIZE_PACKET_DATA + (TsiCpuPacket.SIZE_STATUS_DATA * statusCount) ) ) {
-            log.info("Node: {}, Length Error: {}, status count: {}, {}", nodeId, dataLength, statusCount, TsiCpuPacket.SIZE_PACKET_DATA + (TsiCpuPacket.SIZE_STATUS_DATA * statusCount));
-            return false;
-        }
-        //log.info("Node: {}, b: {}", nodeId, TimeUtils.elapsedTime(start));
-        //start = System.nanoTime();
-
-        // 2단계. 체크섬
-        int recvCheckSum = ByteUtils.getUnsignedShort(packet, packet.length-2);
-        int calcCheckSum = CRC16Utils.CRC16_ccitt_cvim(packet, TsiCpuPacket.INDEX_LENGTH, dataLength-2);
-        if (recvCheckSum != calcCheckSum) {
-            log.info("Node: {}, Check Sum Error: recv: {}, calc: {}", nodeId, recvCheckSum, calcCheckSum);
-            return false;
-        }
-        //log.info("Node: {}, c: {}", nodeId, TimeUtils.elapsedTime(start));
-        //start = System.nanoTime();
-
-        initPacket();
-        //log.info("Node: {}, 1: {}", nodeId, TimeUtils.elapsedTime(start));
-        //start = System.nanoTime();
-
-        if (this.addNodeEnabled && this.tsiNodeAddVo != null) {
-            // 연등지 교차로가 존재하는 경우
-            for (Map.Entry<Integer, TsiNodeAddDetailVo> obj : this.tsiNodeAddVo.getAddNodeMap().entrySet()) {
-                if (obj.getValue().getNodeObj() != null) {
-                    obj.getValue().getNodeObj().initPacket();
-                }
-            }
-        }
-        //log.info("Node: {}, 2: {}", nodeId, TimeUtils.elapsedTime(start));
-        //start = System.nanoTime();
-
-        // CVIB Protocol Format(CPU-->CENTER)
-        //TYPE    STX1    STX2    LEN                 OPCODE  DataVer NodeID  DATA    CHKSUM
-        //Size    Byte    Byte    2Byte               Byte    1Byte   4Byte   NByte   2Byte
-        //Value   0x7E    0x7E    Size(LEN…CHKSUM)    0x13    0x01            …      CRC16
-        //- LEN   : LEN∼CHKSUM data length
-        //        - OPCODE: 0x13, 신호상태정보전송
-        //        - NodeID: Node ID
-        //- DATA  : Opcode에 따른 데이터 영역
-        //- CRC16 : CCITT / ITU / CRC - 16, bits shift right, final little(x) big(o) endian encoding.from LEN to DATA
-        ByteBuffer buffer = ByteBuffer.wrap(packet);
-
-        TsiCvimControl tscControlInfo = tsiCvimDto.getTscControlInfo();
-        TsiCvimAbnormal tscAbnormalInfo = tsiCvimDto.getTscAbnormalInfo();
-
-        tsiCvimDto.setNodeId(this.nodeId);
-        tsiCvimDto.setConnect(true);
-        tsiCvimDto.setCollectTime(SysUtils.getSysTimeStr());
-
-        //log.info("Node: {}, 3: {}", nodeId, TimeUtils.elapsedTime(start));
-        //start = System.nanoTime();
-
-        int stx1 = buffer.get();
-        int stx2 = buffer.get();
-        int length = (int)buffer.getShort() & 0xFFFF;
-        int opcode = buffer.get();
-        int version = buffer.get();
-        long recvNodeId = (long)(buffer.getInt() & 0xFFFFFFFFL);
-
-        byte control = buffer.get();
-        tscControlInfo.inManualControl     = ((control     ) & 0x01) == 0x01;  //수동
-        tscControlInfo.inFlashingControl   = ((control >> 1) & 0x01) == 0x01;  //점멸
-        tscControlInfo.inLightsOutControl  = ((control >> 2) & 0x01) == 0x01;  //소등
-        tscControlInfo.inActuationControl  = ((control >> 3) & 0x01) == 0x01;  //감응
-        tscControlInfo.inTransitionControl = ((control >> 4) & 0x01) == 0x01;  //전이
-
-        byte abnormal = buffer.get();
-        tscAbnormalInfo.inSignalConflict = ((abnormal     ) & 0x01) == 0x01;   //모순상태
-        tscAbnormalInfo.inCenterComm     = ((abnormal >> 1) & 0x01) == 0x01;   //센터상태
-        tscAbnormalInfo.inScuComm        = ((abnormal >> 2) & 0x01) == 0x01;   //SCU 상태
-
-        tsiCvimDto.setCycleElapsedTime((int)(buffer.get() & 0xFF));
-
-        byte stts = buffer.get();
-        tsiCvimDto.setSignalStatusInfoCount((int)(stts & 0x7F));
-        //int divFlag = (int)((stts >> 7) & 0x01);
-
-        long currTime = ((long)buffer.getInt() & 0xFFFFFFFFL);
-        //log.info("Node: {}, 4: {}", nodeId, TimeUtils.elapsedTime(start));
-        //start = System.nanoTime();
-
-        for (int idx = 0; idx < tsiCvimDto.getSignalStatusInfoCount(); idx++) {
-
-            byte dirInfo         = buffer.get();
-            byte statusInfo      = buffer.get();
-            int totalSeconds     = buffer.get();
-            int remainingSeconds = buffer.get();
-            int directionCode    = buffer.get();
-
-            TsiCvimStatus status = new TsiCvimStatus();
-
-            int dirAdd =                          (int)((dirInfo     ) & 0x0F);           // 3 ~ 0, 방향추가정보, 해당 방향에 연등지 없음(0), 해당 방향의 첫번째 연등지(1), 해당 방향의 두번째 연등지(2)
-            status.setLightsType(eLightsType.getByValue((dirInfo >> 4) & 0x0F));          // 신호등정보 [직진,좌,보행]
-
-            status.setLightsStatus(eLightsStatus.getByValue(      (statusInfo     ) & 0x07));          //신호등상태
-            status.setTimeReliability(eTimeReliability.getByValue((statusInfo >> 7) & 0x01));          //시간정보신뢰성
-            status.setReadyPedestrianSignal((                     (statusInfo >> 6) & 0x01) == 0x01);  //보행자
-            status.setUnProtectedSignal((                         (statusInfo >> 3) & 0x01) == 0x01);  //비보호 상태
-
-            status.setTotalSeconds    (totalSeconds);       //표출시간
-            status.setRemainingSeconds(remainingSeconds);   //잔여시간
-            status.setDirectionCode   (directionCode);      //방향코드
-
-            if (dirAdd == 0) {
-                tsiCvimDto.getSignalStatusInfos().add(status);
-            }
-            else {
-                if (this.tsiNodeAddVo != null) {
-                    TsiNodeAddDetailVo detailVo = this.tsiNodeAddVo.getAddNodeMap().get(directionCode * 1000 + dirAdd);
-                    if (detailVo != null) {
-                        for (int dirIdx = 0; dirIdx < 2; dirIdx++) {
-                            if (detailVo.getAddDirCode()[dirIdx] != 0x00) {
-                                if (dirIdx == 0) {
-                                    status.setDirectionCode((int) detailVo.getAddDirCode()[dirIdx]);
-                                    detailVo.getNodeObj().getTsiCvimDto().getSignalStatusInfos().add(status);
-                                }
-                                else {
-                                    TsiCvimStatus statusTmp = new TsiCvimStatus();
-                                    status.copy(statusTmp);
-                                    statusTmp.setDirectionCode((int) detailVo.getAddDirCode()[dirIdx]);
-                                    detailVo.getNodeObj().getTsiCvimDto().getSignalStatusInfos().add(statusTmp);
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        //log.info("Node: {}, 5: {}", nodeId, TimeUtils.elapsedTime(start));
-        //start = System.nanoTime();
-
-        Date date = new java.util.Date(currTime * 1000L);
-        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-        sdf.setTimeZone(java.util.TimeZone.getTimeZone("GMT+9"));
-        tsiCvimDto.setTscDateTime(sdf.format(date));
-
-        if (this.addNodeEnabled && this.tsiNodeAddVo != null) {
-            makePacket((byte) stx1, (byte) stx2, (byte) opcode, (byte) version, tsiCvimDto, currTime);
-            for (Map.Entry<Integer, TsiNodeAddDetailVo> obj : this.tsiNodeAddVo.getAddNodeMap().entrySet()) {
-                if (obj.getValue().getNodeObj() != null) {
-                    obj.getValue().getNodeObj().makePacket((byte) stx1, (byte) stx2, (byte) opcode, (byte) version, tsiCvimDto, currTime);
-                }
-            }
-        }
-        else {
-            //this.tsiNodeVo.setPacket(this.rawBytes);
-            makeNodePacket(length);
-        }
-        //log.info("Node: {}, 6: {}", nodeId, TimeUtils.elapsedTime(start));
-        //start = System.nanoTime();
-
-        return result;
-    }
+//    public boolean parsing(byte[] packet) {
+//
+//        boolean result = true;
+//        //long start = System.nanoTime();
+//
+//        // 0 단계. STX1, STX2 체크
+//        if (packet[TsiCpuPacket.INDEX_STX1] != TsiCpuPacket.STX1 || packet[TsiCpuPacket.INDEX_STX2] != TsiCpuPacket.STX2) {
+//            log.info("Node: {}, STX Error: {}, {}", nodeId, packet[TsiCpuPacket.INDEX_STX1], packet[TsiCpuPacket.INDEX_STX2]);
+//            return false;
+//        }
+//        //log.info("Node: {}, a: {}", nodeId, TimeUtils.elapsedTime(start));
+//        //start = System.nanoTime();
+//
+//        // 1 단계. 패킷 길이 체크
+//        int dataLength = ByteUtils.getUnsignedShort(packet, TsiCpuPacket.INDEX_LENGTH);
+//        int statusCount = (int)(packet[TsiCpuPacket.INDEX_STATUS_HDR+3] & 0x7F);
+//        if (dataLength != ( TsiCpuPacket.SIZE_PACKET_DATA + (TsiCpuPacket.SIZE_STATUS_DATA * statusCount) ) ) {
+//            log.info("Node: {}, Length Error: {}, status count: {}, {}", nodeId, dataLength, statusCount, TsiCpuPacket.SIZE_PACKET_DATA + (TsiCpuPacket.SIZE_STATUS_DATA * statusCount));
+//            return false;
+//        }
+//        //log.info("Node: {}, b: {}", nodeId, TimeUtils.elapsedTime(start));
+//        //start = System.nanoTime();
+//
+//        // 2단계. 체크섬
+//        int recvCheckSum = ByteUtils.getUnsignedShort(packet, packet.length-2);
+//        int calcCheckSum = CRC16Utils.CRC16_ccitt_cvim(packet, TsiCpuPacket.INDEX_LENGTH, dataLength-2);
+//        if (recvCheckSum != calcCheckSum) {
+//            log.info("Node: {}, Check Sum Error: recv: {}, calc: {}", nodeId, recvCheckSum, calcCheckSum);
+//            return false;
+//        }
+//        //log.info("Node: {}, c: {}", nodeId, TimeUtils.elapsedTime(start));
+//        //start = System.nanoTime();
+//
+//        initPacket();
+//        //log.info("Node: {}, 1: {}", nodeId, TimeUtils.elapsedTime(start));
+//        //start = System.nanoTime();
+//
+//        if (this.addNodeEnabled && this.tsiNodeAddVo != null) {
+//            // 연등지 교차로가 존재하는 경우
+//            for (Map.Entry<Integer, TsiNodeAddDetailVo> obj : this.tsiNodeAddVo.getAddNodeMap().entrySet()) {
+//                if (obj.getValue().getNodeObj() != null) {
+//                    obj.getValue().getNodeObj().initPacket();
+//                }
+//            }
+//        }
+//        //log.info("Node: {}, 2: {}", nodeId, TimeUtils.elapsedTime(start));
+//        //start = System.nanoTime();
+//
+//        // CVIB Protocol Format(CPU-->CENTER)
+//        //TYPE    STX1    STX2    LEN                 OPCODE  DataVer NodeID  DATA    CHKSUM
+//        //Size    Byte    Byte    2Byte               Byte    1Byte   4Byte   NByte   2Byte
+//        //Value   0x7E    0x7E    Size(LEN…CHKSUM)    0x13    0x01            …      CRC16
+//        //- LEN   : LEN∼CHKSUM data length
+//        //        - OPCODE: 0x13, 신호상태정보전송
+//        //        - NodeID: Node ID
+//        //- DATA  : Opcode에 따른 데이터 영역
+//        //- CRC16 : CCITT / ITU / CRC - 16, bits shift right, final little(x) big(o) endian encoding.from LEN to DATA
+//        ByteBuffer buffer = ByteBuffer.wrap(packet);
+//
+//        TsiCvimControl tscControlInfo = tsiCvimDto.getTscControlInfo();
+//        TsiCvimAbnormal tscAbnormalInfo = tsiCvimDto.getTscAbnormalInfo();
+//
+//        tsiCvimDto.setNodeId(this.nodeId);
+//        tsiCvimDto.setConnect(true);
+//        tsiCvimDto.setCollectTime(SysUtils.getSysTimeStr());
+//
+//        //log.info("Node: {}, 3: {}", nodeId, TimeUtils.elapsedTime(start));
+//        //start = System.nanoTime();
+//
+//        int stx1 = buffer.get();
+//        int stx2 = buffer.get();
+//        int length = (int)buffer.getShort() & 0xFFFF;
+//        int opcode = buffer.get();
+//        int version = buffer.get();
+//        long recvNodeId = (long)(buffer.getInt() & 0xFFFFFFFFL);
+//
+//        byte control = buffer.get();
+//        tscControlInfo.inManualControl     = ((control     ) & 0x01) == 0x01;  //수동
+//        tscControlInfo.inFlashingControl   = ((control >> 1) & 0x01) == 0x01;  //점멸
+//        tscControlInfo.inLightsOutControl  = ((control >> 2) & 0x01) == 0x01;  //소등
+//        tscControlInfo.inActuationControl  = ((control >> 3) & 0x01) == 0x01;  //감응
+//        tscControlInfo.inTransitionControl = ((control >> 4) & 0x01) == 0x01;  //전이
+//
+//        byte abnormal = buffer.get();
+//        tscAbnormalInfo.inSignalConflict = ((abnormal     ) & 0x01) == 0x01;   //모순상태
+//        tscAbnormalInfo.inCenterComm     = ((abnormal >> 1) & 0x01) == 0x01;   //센터상태
+//        tscAbnormalInfo.inScuComm        = ((abnormal >> 2) & 0x01) == 0x01;   //SCU 상태
+//
+//        tsiCvimDto.setCycleElapsedTime((int)(buffer.get() & 0xFF));
+//
+//        byte stts = buffer.get();
+//        tsiCvimDto.setSignalStatusInfoCount((int)(stts & 0x7F));
+//        //int divFlag = (int)((stts >> 7) & 0x01);
+//
+//        long currTime = ((long)buffer.getInt() & 0xFFFFFFFFL);
+//        //log.info("Node: {}, 4: {}", nodeId, TimeUtils.elapsedTime(start));
+//        //start = System.nanoTime();
+//
+//        for (int idx = 0; idx < tsiCvimDto.getSignalStatusInfoCount(); idx++) {
+//
+//            byte dirInfo         = buffer.get();
+//            byte statusInfo      = buffer.get();
+//            int totalSeconds     = buffer.get();
+//            int remainingSeconds = buffer.get();
+//            int directionCode    = buffer.get();
+//
+//            TsiCvimStatus status = new TsiCvimStatus();
+//
+//            int dirAdd =                          (int)((dirInfo     ) & 0x0F);           // 3 ~ 0, 방향추가정보, 해당 방향에 연등지 없음(0), 해당 방향의 첫번째 연등지(1), 해당 방향의 두번째 연등지(2)
+//            status.setLightsType(eLightsType.getByValue((dirInfo >> 4) & 0x0F));          // 신호등정보 [직진,좌,보행]
+//
+//            status.setLightsStatus(eLightsStatus.getByValue(      (statusInfo     ) & 0x07));          //신호등상태
+//            status.setTimeReliability(eTimeReliability.getByValue((statusInfo >> 7) & 0x01));          //시간정보신뢰성
+//            status.setReadyPedestrianSignal((                     (statusInfo >> 6) & 0x01) == 0x01);  //보행자
+//            status.setUnProtectedSignal((                         (statusInfo >> 3) & 0x01) == 0x01);  //비보호 상태
+//
+//            status.setTotalSeconds    (totalSeconds);       //표출시간
+//            status.setRemainingSeconds(remainingSeconds);   //잔여시간
+//            status.setDirectionCode   (directionCode);      //방향코드
+//
+//            if (dirAdd == 0) {
+//                tsiCvimDto.getSignalStatusInfos().add(status);
+//            }
+//            else {
+//                if (this.tsiNodeAddVo != null) {
+//                    TsiNodeAddDetailVo detailVo = this.tsiNodeAddVo.getAddNodeMap().get(directionCode * 1000 + dirAdd);
+//                    if (detailVo != null) {
+//                        for (int dirIdx = 0; dirIdx < 2; dirIdx++) {
+//                            if (detailVo.getAddDirCode()[dirIdx] != 0x00) {
+//                                if (dirIdx == 0) {
+//                                    status.setDirectionCode((int) detailVo.getAddDirCode()[dirIdx]);
+//                                    detailVo.getNodeObj().getTsiCvimDto().getSignalStatusInfos().add(status);
+//                                }
+//                                else {
+//                                    TsiCvimStatus statusTmp = new TsiCvimStatus();
+//                                    status.copy(statusTmp);
+//                                    statusTmp.setDirectionCode((int) detailVo.getAddDirCode()[dirIdx]);
+//                                    detailVo.getNodeObj().getTsiCvimDto().getSignalStatusInfos().add(statusTmp);
+//                                }
+//                            }
+//                        }
+//                    }
+//                }
+//            }
+//        }
+//
+//        //log.info("Node: {}, 5: {}", nodeId, TimeUtils.elapsedTime(start));
+//        //start = System.nanoTime();
+//
+//        Date date = new java.util.Date(currTime * 1000L);
+//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+//        sdf.setTimeZone(java.util.TimeZone.getTimeZone("GMT+9"));
+//        tsiCvimDto.setTscDateTime(sdf.format(date));
+//
+//        if (this.addNodeEnabled && this.tsiNodeAddVo != null) {
+//            makePacket((byte) stx1, (byte) stx2, (byte) opcode, (byte) version, tsiCvimDto, currTime);
+//            for (Map.Entry<Integer, TsiNodeAddDetailVo> obj : this.tsiNodeAddVo.getAddNodeMap().entrySet()) {
+//                if (obj.getValue().getNodeObj() != null) {
+//                    obj.getValue().getNodeObj().makePacket((byte) stx1, (byte) stx2, (byte) opcode, (byte) version, tsiCvimDto, currTime);
+//                }
+//            }
+//        }
+//        else {
+//            //this.tsiNodeVo.setPacket(this.rawBytes);
+//            makeNodePacket(length);
+//        }
+//        //log.info("Node: {}, 6: {}", nodeId, TimeUtils.elapsedTime(start));
+//        //start = System.nanoTime();
+//
+//        return result;
+//    }
 
     public void makeNodePacket(int length) {
         this.nodePacket = null;
@@ -298,113 +283,113 @@ public class TsiNodeVo {
         }
     }
 
-    public void makePacket(byte stx1, byte stx2, byte opcode, byte version, TsiCvimDto tsiCvimDto, long currTime) {
-        if (this.tsiCvimDto == null) {
-            return;
-        }
-
-        if (tsiCvimDto != null) {
-            this.tsiCvimDto.setConnect(true);
-            this.tsiCvimDto.setCollectTime(tsiCvimDto.getCollectTime());
-            this.tsiCvimDto.setTscDateTime(tsiCvimDto.getTscDateTime());
-            this.tsiCvimDto.setCycleElapsedTime(tsiCvimDto.getCycleElapsedTime());
-
-            this.tsiCvimDto.setTscControlInfo(tsiCvimDto.getTscControlInfo());
-            this.tsiCvimDto.setTscAbnormalInfo(tsiCvimDto.getTscAbnormalInfo());
-            this.tsiCvimDto.setSignalStatusInfoCount(this.tsiCvimDto.getSignalStatusInfos().size());
-        }
-        else {
-            this.tsiCvimDto.setConnect(true);
-            this.tsiCvimDto.setSignalStatusInfoCount(0);
-        }
-
-        int length = 2 + 1 + 1 + 4 + 8 + (5 * this.tsiCvimDto.getSignalStatusInfoCount()) + 2;
-        ByteBuffer byteBuffer = ByteBuffer.allocate(2 + length);
-        byteBuffer.order(ByteOrder.BIG_ENDIAN);
-
-        // 헤더 (10 byte)
-        byteBuffer.put(stx1);
-        byteBuffer.put(stx2);
-        //byteBuffer.putShort((short)length);
-        byteBuffer.put((byte)((length>>8) & 0xFF));
-        byteBuffer.put((byte)((length)    & 0xFF));
-        byteBuffer.put(opcode);
-        byteBuffer.put(version);
-        //byteBuffer.putInt((int)this.getNodeId());
-        byteBuffer.put((byte)((this.getNodeId()>>24) & 0xFF));
-        byteBuffer.put((byte)((this.getNodeId()>>16) & 0xFF));
-        byteBuffer.put((byte)((this.getNodeId()>> 8) & 0xFF));
-        byteBuffer.put((byte)((this.getNodeId()    ) & 0xFF));
-
-        byte inManualControl     = (byte) (this.tsiCvimDto.getTscControlInfo().inManualControl     ? 0x01 : 0x00);
-        byte inFlashingControl   = (byte) (this.tsiCvimDto.getTscControlInfo().inFlashingControl   ? 0x01 : 0x00);
-        byte inLightsOutControl  = (byte) (this.tsiCvimDto.getTscControlInfo().inLightsOutControl  ? 0x01 : 0x00);
-        byte inActuationControl  = (byte) (this.tsiCvimDto.getTscControlInfo().inActuationControl  ? 0x01 : 0x00);
-        byte inTransitionControl = (byte) (this.tsiCvimDto.getTscControlInfo().inTransitionControl ? 0x01 : 0x00);
-        byte control = (byte) (
-                (inManualControl         ) |
-                (inFlashingControl   << 1) |
-                (inLightsOutControl  << 2) |
-                (inActuationControl  << 3) |
-                (inTransitionControl << 4)
-        );
-
-        byte inSignalConflict = (byte) (this.tsiCvimDto.getTscAbnormalInfo().inSignalConflict ? 0x01 : 0x00);
-        byte inCenterComm     = (byte) (this.tsiCvimDto.getTscAbnormalInfo().inCenterComm     ? 0x01 : 0x00);
-        byte inScuComm        = (byte) (this.tsiCvimDto.getTscAbnormalInfo().inScuComm        ? 0x01 : 0x00);
-        byte abnormal = (byte) (
-                (inSignalConflict     ) |
-                (inCenterComm     << 1) |
-                (inScuComm        << 2)
-        );
-
-        byte sttsCount = (byte) this.tsiCvimDto.getSignalStatusInfoCount();
-        byte splitFlag = 0x01;
-        byte signalStatusInfoCount = (byte) (sttsCount | (splitFlag << 7));
-
-        // 상태헤더 (8 byte)
-        byteBuffer.put(control);
-        byteBuffer.put(abnormal);
-        byteBuffer.put((byte)this.tsiCvimDto.getCycleElapsedTime());
-        byteBuffer.put(signalStatusInfoCount);
-        //byteBuffer.putInt((int)currTime);
-        byteBuffer.put((byte)((currTime>>24) & 0xFF));
-        byteBuffer.put((byte)((currTime>>16) & 0xFF));
-        byteBuffer.put((byte)((currTime>> 8) & 0xFF));
-        byteBuffer.put((byte)((currTime    ) & 0xFF));
-
-        for (TsiCvimStatus status : this.tsiCvimDto.getSignalStatusInfos()) {
-            byte lightsType = (byte) status.getLightsType().getValue();
-
-            byte lightsStatus = (byte) status.getLightsStatus().getValue();
-            byte unProtectedSignal = (byte) (status.isUnProtectedSignal() ? 0x01 : 0x00);
-            byte readyPedestrianSignal = (byte) (status.isReadyPedestrianSignal() ? 0x01 : 0x00);
-            byte timeReliability = (byte) status.getTimeReliability().getValue();
-
-            byte statusFlag = (byte) (
-                    (lightsStatus              ) |
-                    (unProtectedSignal     << 3) |
-                    (readyPedestrianSignal << 6) |
-                    (timeReliability       << 7)
-            );
-
-            byteBuffer.put((byte) (lightsType << 4));
-            byteBuffer.put(statusFlag);
-            byteBuffer.put((byte) status.getTotalSeconds());
-            byteBuffer.put((byte) status.getRemainingSeconds());
-            byteBuffer.put((byte) status.getDirectionCode());
-        }
-        byteBuffer.put((byte)0x00);
-        byteBuffer.put((byte)0x00);
-/*
-
-        this.packet = byteBuffer.array();
-        int checkSum = CRC16Utils.CRC16_ccitt_cvim(this.packet, 2, length-2);
-        this.packet[this.packet.length - 2] = (byte)((checkSum >> 8) & 0xFF);
-        this.packet[this.packet.length - 1] = (byte)((checkSum     ) & 0xFF);
-*/
-
-        makeNodePacket(length);
-    }
+//    public void makePacket(byte stx1, byte stx2, byte opcode, byte version, TsiCvimDto tsiCvimDto, long currTime) {
+//        if (this.tsiCvimDto == null) {
+//            return;
+//        }
+//
+//        if (tsiCvimDto != null) {
+//            this.tsiCvimDto.setConnect(true);
+//            this.tsiCvimDto.setCollectTime(tsiCvimDto.getCollectTime());
+//            this.tsiCvimDto.setTscDateTime(tsiCvimDto.getTscDateTime());
+//            this.tsiCvimDto.setCycleElapsedTime(tsiCvimDto.getCycleElapsedTime());
+//
+//            this.tsiCvimDto.setTscControlInfo(tsiCvimDto.getTscControlInfo());
+//            this.tsiCvimDto.setTscAbnormalInfo(tsiCvimDto.getTscAbnormalInfo());
+//            this.tsiCvimDto.setSignalStatusInfoCount(this.tsiCvimDto.getSignalStatusInfos().size());
+//        }
+//        else {
+//            this.tsiCvimDto.setConnect(true);
+//            this.tsiCvimDto.setSignalStatusInfoCount(0);
+//        }
+//
+//        int length = 2 + 1 + 1 + 4 + 8 + (5 * this.tsiCvimDto.getSignalStatusInfoCount()) + 2;
+//        ByteBuffer byteBuffer = ByteBuffer.allocate(2 + length);
+//        byteBuffer.order(ByteOrder.BIG_ENDIAN);
+//
+//        // 헤더 (10 byte)
+//        byteBuffer.put(stx1);
+//        byteBuffer.put(stx2);
+//        //byteBuffer.putShort((short)length);
+//        byteBuffer.put((byte)((length>>8) & 0xFF));
+//        byteBuffer.put((byte)((length)    & 0xFF));
+//        byteBuffer.put(opcode);
+//        byteBuffer.put(version);
+//        //byteBuffer.putInt((int)this.getNodeId());
+//        byteBuffer.put((byte)((this.getNodeId()>>24) & 0xFF));
+//        byteBuffer.put((byte)((this.getNodeId()>>16) & 0xFF));
+//        byteBuffer.put((byte)((this.getNodeId()>> 8) & 0xFF));
+//        byteBuffer.put((byte)((this.getNodeId()    ) & 0xFF));
+//
+//        byte inManualControl     = (byte) (this.tsiCvimDto.getTscControlInfo().inManualControl     ? 0x01 : 0x00);
+//        byte inFlashingControl   = (byte) (this.tsiCvimDto.getTscControlInfo().inFlashingControl   ? 0x01 : 0x00);
+//        byte inLightsOutControl  = (byte) (this.tsiCvimDto.getTscControlInfo().inLightsOutControl  ? 0x01 : 0x00);
+//        byte inActuationControl  = (byte) (this.tsiCvimDto.getTscControlInfo().inActuationControl  ? 0x01 : 0x00);
+//        byte inTransitionControl = (byte) (this.tsiCvimDto.getTscControlInfo().inTransitionControl ? 0x01 : 0x00);
+//        byte control = (byte) (
+//                (inManualControl         ) |
+//                (inFlashingControl   << 1) |
+//                (inLightsOutControl  << 2) |
+//                (inActuationControl  << 3) |
+//                (inTransitionControl << 4)
+//        );
+//
+//        byte inSignalConflict = (byte) (this.tsiCvimDto.getTscAbnormalInfo().inSignalConflict ? 0x01 : 0x00);
+//        byte inCenterComm     = (byte) (this.tsiCvimDto.getTscAbnormalInfo().inCenterComm     ? 0x01 : 0x00);
+//        byte inScuComm        = (byte) (this.tsiCvimDto.getTscAbnormalInfo().inScuComm        ? 0x01 : 0x00);
+//        byte abnormal = (byte) (
+//                (inSignalConflict     ) |
+//                (inCenterComm     << 1) |
+//                (inScuComm        << 2)
+//        );
+//
+//        byte sttsCount = (byte) this.tsiCvimDto.getSignalStatusInfoCount();
+//        byte splitFlag = 0x01;
+//        byte signalStatusInfoCount = (byte) (sttsCount | (splitFlag << 7));
+//
+//        // 상태헤더 (8 byte)
+//        byteBuffer.put(control);
+//        byteBuffer.put(abnormal);
+//        byteBuffer.put((byte)this.tsiCvimDto.getCycleElapsedTime());
+//        byteBuffer.put(signalStatusInfoCount);
+//        //byteBuffer.putInt((int)currTime);
+//        byteBuffer.put((byte)((currTime>>24) & 0xFF));
+//        byteBuffer.put((byte)((currTime>>16) & 0xFF));
+//        byteBuffer.put((byte)((currTime>> 8) & 0xFF));
+//        byteBuffer.put((byte)((currTime    ) & 0xFF));
+//
+//        for (TsiCvimStatus status : this.tsiCvimDto.getSignalStatusInfos()) {
+//            byte lightsType = (byte) status.getLightsType().getValue();
+//
+//            byte lightsStatus = (byte) status.getLightsStatus().getValue();
+//            byte unProtectedSignal = (byte) (status.isUnProtectedSignal() ? 0x01 : 0x00);
+//            byte readyPedestrianSignal = (byte) (status.isReadyPedestrianSignal() ? 0x01 : 0x00);
+//            byte timeReliability = (byte) status.getTimeReliability().getValue();
+//
+//            byte statusFlag = (byte) (
+//                    (lightsStatus              ) |
+//                    (unProtectedSignal     << 3) |
+//                    (readyPedestrianSignal << 6) |
+//                    (timeReliability       << 7)
+//            );
+//
+//            byteBuffer.put((byte) (lightsType << 4));
+//            byteBuffer.put(statusFlag);
+//            byteBuffer.put((byte) status.getTotalSeconds());
+//            byteBuffer.put((byte) status.getRemainingSeconds());
+//            byteBuffer.put((byte) status.getDirectionCode());
+//        }
+//        byteBuffer.put((byte)0x00);
+//        byteBuffer.put((byte)0x00);
+///*
+//
+//        this.packet = byteBuffer.array();
+//        int checkSum = CRC16Utils.CRC16_ccitt_cvim(this.packet, 2, length-2);
+//        this.packet[this.packet.length - 2] = (byte)((checkSum >> 8) & 0xFF);
+//        this.packet[this.packet.length - 1] = (byte)((checkSum     ) & 0xFF);
+//*/
+//
+//        makeNodePacket(length);
+//    }
 
 }

+ 7 - 21
src/main/resources/application.yml

@@ -1,4 +1,7 @@
 spring:
+  config:
+    import:
+      - optional:file:${user.dir}/conf/tsi-comm-server.yml
   application:
     name: tsi-comm-server
   main:
@@ -64,46 +67,29 @@ application:
       enable-node: true
       enable-test: true
 
----
-spring:
-  profiles: wonju
-  datasource:
-    mybatis:
-      jdbc-url: jdbc:mariadb://10.4.4.20:3307/cvim_db?characterEncoding=UTF-8&serverTimezone=UTC
-
-  data:
-    mongodb:
-      host: 10.4.4.20
-      port: 29017
-
-application:
-  kafka:
-    producer:
-      bootstrap-servers: 123.142.27.53:9092
-
 ---
 spring:
   profiles: seoul
   datasource:
     mybatis:
-      jdbc-url: jdbc:mariadb://192.168.202.105:3306/cvim_db?characterEncoding=UTF-8&serverTimezone=UTC
+      jdbc-url: jdbc:mariadb://10.4.4.20:3306/cvim_db?characterEncoding=UTF-8&serverTimezone=Asia/Seoul
 
   data:
     mongodb:
-      host: 192.168.202.106
+      host: 172.24.0.40
       port: 27017
 
 application:
   kafka:
     producer:
-      bootstrap-servers: 192.168.202.105:9093
+      bootstrap-servers: 172.24.0.30:9092,172.24.0.31:9093,172.24.0.32:9094
 
 ---
 spring:
   profiles: dev
   datasource:
     mybatis:
-      jdbc-url: jdbc:mariadb://61.108.209.105:3306/cvim_db?characterEncoding=UTF-8&serverTimezone=UTC
+      jdbc-url: jdbc:mariadb://61.108.209.105:3306/cvim_db?characterEncoding=UTF-8&serverTimezone=Asia/Seoul
 
   data:
     mongodb:

+ 31 - 27
src/main/resources/mybatis/mapper/tsi-comm-server.xml

@@ -19,10 +19,10 @@
 
     <select id="getNodeInfoList" parameterType="java.util.HashMap" resultType="com.tsi.comm.server.mybatis.vo.NodeVo">
         <![CDATA[
-            select a.nodeid, nvl(trim(a.ipaddr), '0'),
-                   useyn, cvimyn, nodeyn, testyn
-              from tb_tsc_node a
-             where a.useyn  = 'Y'
+        select a.nodeid, nvl(trim(a.ipaddr), '0'),
+               useyn, cvimyn, nodeyn, testyn
+        from tb_tsc_node a
+        where a.useyn  = 'Y'
         ]]>
     </select>
 
@@ -38,32 +38,32 @@
 
     <select id="getNodeAddInfoList" resultMap="result-nodeAdd">
         <![CDATA[
-            select a.origin_nodeid, a.nodeid, a.origin_dir_code,
-                   a.add_node_order, a.add_dir_code
-              from tb_tsc_node_add a, tb_tsc_node b, tb_tsc_node c
-             where a.nodeid        = b.nodeid
-               and a.origin_nodeid = c.nodeid
-               and b.useyn         = 'Y'
-               and c.useyn         = 'Y'
-             order by a.origin_nodeid, a.nodeid, a.add_node_order
+        select a.origin_nodeid, a.nodeid, a.origin_dir_code,
+               a.add_node_order, a.add_dir_code
+        from tb_tsc_node_add a, tb_tsc_node b, tb_tsc_node c
+        where a.nodeid        = b.nodeid
+          and a.origin_nodeid = c.nodeid
+          and b.useyn         = 'Y'
+          and c.useyn         = 'Y'
+        order by a.origin_nodeid, a.nodeid, a.add_node_order
         ]]>
     </select>
 
     <insert id="insertNodeStatusInitialize">
     <![CDATA[
-          insert into tb_tsc_node_status(nodeid, status, eventdt)
-          select nodeid, 0, NOW()
-            from tb_tsc_node
-           where nodeid not in (select nodeid from tb_tsc_node_status)
-    ]]>
+        insert into tb_tsc_node_status(nodeid, status, eventdt)
+        select nodeid, 0, NOW()
+        from tb_tsc_node
+        where nodeid not in (select nodeid from tb_tsc_node_status)
+        ]]>
     </insert>
 
     <update id="updateNodeStatusTerm">
     <![CDATA[
-		update tb_tsc_node_status
-		   set status = 0,
-		       eventdt = NOW()
-    ]]>
+        update tb_tsc_node_status
+        set status = 0,
+            eventdt = NOW()
+        ]]>
     </update>
 
     <update id="updateNodeStatusLoginTempX" parameterType="com.tsi.comm.server.mybatis.vo.NodeStatusVo">
@@ -78,12 +78,12 @@
 
     <update id="updateNodeStatus" parameterType="com.tsi.comm.server.mybatis.vo.NodeStatusVo">
     <![CDATA[
-		update tb_tsc_node_status
-		   set status  = #{stts.status},
-		       eventdt = NOW(),
-		       ipAddr  = #{stts.ipAddr}
-		 where nodeid = #{stts.nodeId}
-    ]]>
+        update tb_tsc_node_status
+        set status  = #{stts.status},
+            eventdt = NOW(),
+            ipAddr  = #{stts.ipAddr}
+        where nodeid = #{stts.nodeId}
+        ]]>
     </update>
 
 
@@ -98,6 +98,10 @@
         <![CDATA[
         INSERT INTO tb_tsc_comm_tps_hs (prcn_dt, sessions, trans, bytes)
         VALUES (STR_TO_DATE(#{stat.eventDt},'%Y%m%d%H%i%S'), #{stat.sessions}, #{stat.trans}, #{stat.bytes})
+            ON DUPLICATE KEY UPDATE
+            sessions = sessions + #{stat.sessions},
+            trans = trans + #{stat.trans},
+            bytes = bytes + #{stat.bytes}
         ]]>
     </insert>