shjung hai 1 ano
achega
ca2dd7f71c

+ 35 - 0
.gitignore

@@ -0,0 +1,35 @@
+HELP.md
+target/
+logs/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+.mvn
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/

+ 0 - 0
README.md


+ 4 - 0
bin/broker.sh

@@ -0,0 +1,4 @@
+kafkacat -b 123.142.27.53:9092 -L
+kafkacat -b 123.142.27.53:9093 -L
+kafkacat -b 123.142.27.53:9094 -L
+

+ 1 - 0
bin/conn.bat

@@ -0,0 +1 @@
+sftp -oPort=10022 hante-devops@59.29.208.150

+ 1 - 0
bin/seoul.bat

@@ -0,0 +1 @@
+sftp -oPort=22 cvim@61.108.209.104

+ 59 - 0
bin/start.sh

@@ -0,0 +1,59 @@
+#!/bin/sh
+
+ACTIVE_PROFILE=wonju
+#ACTIVE_PROFILE=wonju,mongodb
+SERVICE_HOME=$(dirname $0)
+
+usage() {
+	echo "Usage:" $0 "[comm/data]"
+	echo "RUN tsi-comm-server:" $0 "comm"
+	echo "RUN tsi-data-broker:" $0 "data"
+	exit
+}
+
+case $1 in
+  comm)
+    SERVICE_NAME=tsi-comm-server
+    SERVICE_VERSION=0.0.1
+    ;;
+  data)
+    SERVICE_NAME=tsi-data-broker
+    SERVICE_VERSION=0.0.1
+    ;;
+  *)
+    usage
+    ;;
+esac
+
+
+EXE_NAME=$SERVICE_NAME-$SERVICE_VERSION.jar
+PID_NAME=$SERVICE_NAME.pid
+SERVICE_PID=$SERVICE_HOME/conf/$PID_NAME
+
+export JAVA_OPT="-server"
+#export JAVA_OPT="$JAVA_OPT -Xms4096m -Xmx4096m"
+export JAVA_OPT="$JAVA_OPT -Xlog:gc*:file=logs/${SERVICE_NAME}/${SERVICE_NAME}.gc.log"
+export CONFIG_OPT="-Dspring.profiles.active=${ACTIVE_PROFILE}"
+#export CONFIG_OPT="--spring.config.location=conf//$SERVICE_NAME.yml"
+
+if [ ! -z "$SERVICE_PID" ]; then
+  if [ -f "$SERVICE_PID" ]; then
+    echo "$SERVICE_NAME is already running...."
+    exit
+  fi
+fi
+
+#nohup java $JAVA_OPT -jar ./$EXE_NAME $CONFIG_OPT 1> /dev/null 2>&1 &
+#java $JAVA_OPT -jar ./$EXE_NAME $CONFIG_OPT &
+java $JAVA_OPT -jar $CONFIG_OPT ./$EXE_NAME &
+
+echo "$SERVICE_NAME is started...."
+
+sleep 1
+
+ps -eaf | grep $SERVICE_NAME | grep -v grep |wc -l
+
+sleep 1
+
+ps -eaf | grep $SERVICE_NAME | grep -v grep
+

+ 9 - 0
bin/stat.sh

@@ -0,0 +1,9 @@
+#!/bin/sh
+
+export SERVICE_NAME=tsi-
+
+ps -eaf | grep $SERVICE_NAME | grep -v grep | grep -v tail | grep -v kafka | grep java | wc -l
+
+sleep 1
+
+ps -eaf | grep $SERVICE_NAME | grep -v grep | grep -v tail | grep -v kafka | grep java

+ 54 - 0
bin/stop.sh

@@ -0,0 +1,54 @@
+#!/bin/sh
+
+SERVICE_HOME=$(dirname $0)
+
+usage() {
+        echo "Usage:" $0 "[comm/data]"
+        echo "STOP tsi-comm-server:" $0 "comm"
+        echo "STOP tsi-data-broker:" $0 "data"
+        exit
+}
+
+case $1 in
+  comm)
+    SERVICE_NAME=tsi-comm-server
+    SERVICE_VERSION=0.0.1
+    ;;
+  data)
+    SERVICE_NAME=tsi-data-broker
+    SERVICE_VERSION=0.0.1
+    ;;
+  *)
+    usage
+    ;;
+esac
+
+
+EXE_NAME=$SERVICE_NAME-$SERVICE_VERSION.jar
+PID_NAME=$SERVICE_NAME.pid
+SERVICE_PID=$SERVICE_HOME/conf/$PID_NAME
+
+if [ ! -z "$SERVICE_PID" ]; then
+  if [ -f "$SERVICE_PID" ]; then
+    kill -15 `cat "$SERVICE_PID"` >/dev/null 2>&1
+    echo "$SERVICE_NAME stopping.........."
+  else
+    echo "$SERVICE_NAME is not running...."
+    exit
+  fi
+fi
+
+LOOP=$(seq 0 9)
+for i in $LOOP
+do
+  sleep 1
+  if [ -f "$SERVICE_PID" ]; then
+    echo "$SERVICE_NAME stopping.........."
+  else
+    echo "$SERVICE_NAME stopped.........."
+    exit
+  fi
+done
+
+echo "$SERVICE_NAME cannot be terminated......."
+ps -eaf | grep $SERVICE_NAME | grep -v grep

+ 103 - 0
bin/tsi-agent.sh

@@ -0,0 +1,103 @@
+#!/bin/bash
+
+SSIP_API_URI="http://10.4.4.40:8444/api/system-status"
+SSIP_API_TIMEOUT=3
+HEADER_CONTEXT_TYPE="Content-Type: application/json"
+
+# Check hostname
+name=$HOSTNAME
+echo -e "Hostname:" $name
+
+# Check OS Type
+otype=$(uname -o)
+echo -e "Operating System Type:" $otype
+
+# Check OS Release Version and Name
+oname=`cat /etc/os-release | grep 'NAME' | grep -v 'PRETTY_NAME' | grep -v 'CODENAME' | cut -f2 -d\"`
+over=`cat /etc/os-release | grep 'VERSION' | grep -v '_' | cut -f2 -d\"`
+echo "OS Name:" $oname
+echo "OS Version:" $over
+
+# Check Architecture
+oarch=$(uname -m)
+echo "Architecture:" $oarch
+
+# Check Kernel Release
+kernel=$(uname -r)
+echo "Kernel Release:" $kernel
+
+# Check Internal IP
+iip=$(hostname -I)
+echo "Internal IP:" $iip
+
+# Check Internal IP
+eip=$(dig +short myip.opendns.com @resolver1.opendns.com)
+echo "External IP:" $eip
+
+run_monitoring() {
+    totalmem=`free -m | grep ^Mem | awk '{print $2}'`
+    usedmem=`free -m | grep ^Mem | awk '{print $3}'`
+    freemem=`free -m | grep ^Mem | awk '{print $4}'`
+    cachemem=`free -m | grep ^Mem | awk '{print $6}'`
+    availablemem=`free -m | grep ^Mem | awk '{print $7}'`
+
+    swapmem=`free -m | grep ^Swap | awk '{print $2}'`
+    usedswap=`free -m | grep ^Swap | awk '{print $3}'`
+
+    cpucnt=`cat /proc/cpuinfo | grep 'processor' | wc -l`
+    uptimes=`uptime -s`
+
+    echo "cpuCnt:" ${cpucnt}
+
+    #usecpurate=`top -b -n 1 | grep Cpu | awk '{print $8}' | tr -d "%id," | awk '{print 100-$1}'`
+    usecpurate=`mpstat 1 1 | tail -1 | awk '{print 100-$NF}'`
+    echo "useCpuRate:" ${usecpurate}
+    tasks=`ps aux | grep -v ps | wc -l`
+    threads=200
+
+    #loadavg=`uptime | awk '{print $10}' | cut -f 1 -d ','`
+    loadavg=`cat /proc/loadavg | awk '{print $1}'`
+    echo "loadAvg:" ${loadavg}
+    
+    #DISK 사용율
+    totaldisk=`df -P | grep -v ^Filesystem | awk '{sum += $2} END { print sum; }'`
+    useddisk=`df -P | grep -v ^Filesystem | awk '{sum += $3} END { print sum; }'`
+    useddiskrate=$((100*$useddisk/$totaldisk))
+    echo DISK: $(($totaldisk/1024/1024)) GB, Used DISK: $(($useddisk/1024/1024)) GB, Rate: $useddiskrate %
+
+    # Call System Status Save REST API
+    PAYLOAD='{"hostName"      : "'${name}'", 
+              "osType"        : "'${otype}'", 
+              "osName"        : "'${oname}'", 
+              "osVersion"     : "'${over}'", 
+              "osArch"        : "'${oarch}'", 
+              "kernelRelease" : "'${kernel}'", 
+              "internalIp"    : "'${iip}'", 
+              "externalIp"    : "'${eip}'",
+              "totalMem"      : "'${totalmem}'",
+              "swapMem"       : "'${swapmem}'",
+              "totalDisk"     : "'${totaldisk}'",
+              "cpuCnt"        : "'${cpucnt}'",
+              "upTimes"       : "'${uptimes}'",
+              "usedDisk"      : "'${useddisk}'",
+              "usedMem"       : "'${usedmem}'",
+              "freeMem"       : "'${freemem}'",
+              "cacheMem"      : "'${cachemem}'",
+              "availableMem"  : "'${availablemem}'",
+              "usedSwap"      : "'${usedswap}'",
+              "tasks"         : "'${tasks}'",
+              "threads"       : "'${threads}'",
+              "useCpuRate"    : "'${usecpurate}'",
+              "loadAvg"       : "'${loadavg}'"
+	    }'
+
+    api_result=$(curl -d "${PAYLOAD}" -X POST $SSIP_API_URI -H "$HEADER_CONTEXT_TYPE" --connect-timeout $SSIP_API_TIMEOUT)
+
+    # Result
+    echo ""
+    echo ${api_result}
+    echo ""
+}
+
+run_monitoring
+

+ 151 - 0
conf/ggits-tsinfo-server-2.yml

@@ -0,0 +1,151 @@
+#spring:
+#  profiles:
+#    active: prod
+
+#server:
+#  port: 9871
+#
+#management:
+#  endpoints:
+#    web:
+#      exposure:
+#        include: health, metrics
+
+application:
+#  ggits-server-ip: 192.168.10.66
+  server-ip: 127.0.0.1
+  server-port: 8900
+  connect-timeout: 5
+#  sta-path: /home/ggits/EasyTraffic/sta
+  sta-path: C:\KoROAD\Z.GGITS\ggits\EasyTraffic\sta
+  regions:
+    -
+      region: 41110,L19,7619,127.0.0.1,4110
+      region-no: 41110
+      region-cd: L19
+      region-id: 7619
+    -
+      region: 41130,L09,7619,127.0.0.1,41130
+      region-no: 41130
+      region-cd: L09
+      region-id: 7609
+    -
+      region: 41150,L14,7614,127.0.0.1,41150
+      region-no: 41150
+      region-cd: L14
+      region-id: 7614
+    -
+      region: 41170,L05,7605,127.0.0.1,41170
+      region-no: 41170
+      region-cd: L05
+      region-id: 7605
+    -
+      region: 41190,L03,7603,127.0.0.1,41190
+      region-no: 41190
+      region-cd: L03
+      region-id: 7603
+    -
+      region: 41210,L04,7604,127.0.0.1,41210
+      region-no: 41210
+      region-cd: L04
+      region-id: 7604
+    -
+      region: 41220,L44,7644,127.0.0.1,41220
+      region-no: 41220
+      region-cd: L44
+      region-id: 7644
+    -
+      region: 41270,L07,7607,127.0.0.1,41270
+      region-no: 41270
+      region-cd: L07
+      region-id: 7607
+    -
+      region: 41280,L10,7610,127.0.0.1,41280
+      region-no: 41280
+      region-cd: L10
+      region-id: 7610
+    -
+      region: 41290,L06,7606,127.0.0.1,41290
+      region-no: 41290
+      region-cd: L06
+      region-id: 7606
+    -
+      region: 41310,L21,7621,127.0.0.1,41310
+      region-no: 41310
+      region-cd: L21
+      region-id: 7621
+    -
+      region: 41370,L70,7670,127.0.0.1,41370
+      region-no: 41370
+      region-cd: L70
+      region-id: 7670
+    -
+      region: 41390,L11,7611,127.0.0.1,41390
+      region-no: 41390
+      region-cd: L11
+      region-id: 7611
+    -
+      region: 41410,L17,7617,127.0.0.1,41410
+      region-no: 41410
+      region-cd: L17
+      region-id: 7617
+    -
+      region: 41430,L16,7616,127.0.0.1,41430
+      region-no: 41430
+      region-cd: L16
+      region-id: 7616
+    -
+      region: 41450,L22,7622,127.0.0.1,41450
+      region-no: 41450
+      region-cd: L22
+      region-id: 7622
+    -
+      region: 41460,L08,7608,127.0.0.1,41460
+      region-no: 41460
+      region-cd: L08
+      region-id: 7608
+    -
+      region: 41480,L12,7612,127.0.0.1,41480
+      region-no: 41480
+      region-cd: L12
+      region-id: 7612
+    -
+      region: 41500,L65,7665,127.0.0.1,41500
+      region-no: 41500
+      region-cd: L65
+      region-id: 7665
+    -
+      region: 41550,L56,7656,127.0.0.1,41550
+      region-no: 41550
+      region-cd: L56
+      region-id: 7656
+    -
+      region: 41570,L19,7615,127.0.0.1,41570
+      region-no: 41570
+      region-cd: L15
+      region-id: 7615
+    -
+      region: 41590,L48,7648,127.0.0.1,41590
+      region-no: 41590
+      region-cd: L48
+      region-id: 7648
+    -
+      region: 41610,L20,7620,127.0.0.1,41610
+      region-no: 41610
+      region-cd: L20
+      region-id: 7620
+    -
+      region: 41630,L13,7613,127.0.0.1,41630
+      region-no: 41630
+      region-cd: L13
+      region-id: 7613
+    -
+      region: 41670,L59,7659,127.0.0.1,41670
+      region-no: 41670
+      region-cd: L59
+      region-id: 7659
+    -
+      region: 41800,L69,7669,127.0.0.1,41800
+      region-no: 41800
+      region-cd: L69
+      region-id: 7669

+ 58 - 0
conf/ggits-tsinfo-server.yml

@@ -0,0 +1,58 @@
+application:
+#  ggits-server-ip: 192.168.10.66
+  server-ip: 127.0.0.1
+#  sta-path: /home/ggits/EasyTraffic/sta
+  sta-path: C:\KoROAD\Z.GGITS\ggits\EasyTraffic\sta
+  regions:
+    -
+      region: 41110,L19,7619,127.0.0.1
+    -
+      region: 41130,L09,7609,127.0.0.1
+    -
+      region: 41150,L14,7614,127.0.0.1
+    -
+      region: 41170,L05,7605,127.0.0.1
+    -
+      region: 41190,L03,7603,127.0.0.1
+    -
+      region: 41210,L04,7604,127.0.0.1
+    -
+      region: 41220,L44,7644,127.0.0.1
+    -
+      region: 41270,L07,7607,127.0.0.1
+    -
+      region: 41280,L10,7610,127.0.0.1
+    -
+      region: 41290,L06,7606,127.0.0.1
+    -
+      region: 41310,L21,7621,127.0.0.1
+    -
+      region: 41370,L70,7670,127.0.0.1
+    -
+      region: 41390,L11,7611,127.0.0.1
+    -
+      region: 41410,L17,7617,127.0.0.1
+    -
+      region: 41430,L16,7616,127.0.0.1
+    -
+      region: 41450,L22,7622,127.0.0.1
+    -
+      region: 41460,L08,7608,127.0.0.1
+    -
+      region: 41480,L12,7612,127.0.0.1
+    -
+      region: 41500,L65,7665,127.0.0.1
+    -
+      region: 41550,L56,7656,127.0.0.1
+    -
+      region: 41570,L19,7615,127.0.0.1
+    -
+      region: 41590,L48,7648,127.0.0.1
+    -
+      region: 41610,L20,7620,127.0.0.1
+    -
+      region: 41630,L13,7613,127.0.0.1
+    -
+      region: 41670,L59,7659,127.0.0.1
+    -
+      region: 41800,L69,7669,127.0.0.1

+ 322 - 0
mvnw

@@ -0,0 +1,322 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#    https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+#   JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+#   M2_HOME - location of maven2's installed home dir
+#   MAVEN_OPTS - parameters passed to the Java VM when running Maven
+#     e.g. to debug Maven itself, use
+#       set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,config=y,suspend=y,address=8000
+#   MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ]; then
+
+  if [ -f /etc/mavenrc ]; then
+    . /etc/mavenrc
+  fi
+
+  if [ -f "$HOME/.mavenrc" ]; then
+    . "$HOME/.mavenrc"
+  fi
+
+fi
+
+# OS specific support.  $var _must_ be set to either true or false.
+cygwin=false
+darwin=false
+mingw=false
+case "$(uname)" in
+CYGWIN*) cygwin=true ;;
+MINGW*) mingw=true ;;
+Darwin*)
+  darwin=true
+  # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+  # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+  if [ -z "$JAVA_HOME" ]; then
+    if [ -x "/usr/libexec/java_home" ]; then
+      export JAVA_HOME="$(/usr/libexec/java_home)"
+    else
+      export JAVA_HOME="/Library/Java/Home"
+    fi
+  fi
+  ;;
+esac
+
+if [ -z "$JAVA_HOME" ]; then
+  if [ -r /etc/gentoo-release ]; then
+    JAVA_HOME=$(java-config --jre-home)
+  fi
+fi
+
+if [ -z "$M2_HOME" ]; then
+  ## resolve links - $0 may be a link to maven's home
+  PRG="$0"
+
+  # need this for relative symlinks
+  while [ -h "$PRG" ]; do
+    ls=$(ls -ld "$PRG")
+    link=$(expr "$ls" : '.*-> \(.*\)$')
+    if expr "$link" : '/.*' >/dev/null; then
+      PRG="$link"
+    else
+      PRG="$(dirname "$PRG")/$link"
+    fi
+  done
+
+  saveddir=$(pwd)
+
+  M2_HOME=$(dirname "$PRG")/..
+
+  # make it fully qualified
+  M2_HOME=$(cd "$M2_HOME" && pwd)
+
+  cd "$saveddir"
+  # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin; then
+  [ -n "$M2_HOME" ] &&
+    M2_HOME=$(cygpath --unix "$M2_HOME")
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
+  [ -n "$CLASSPATH" ] &&
+    CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw; then
+  [ -n "$M2_HOME" ] &&
+    M2_HOME="$( (
+      cd "$M2_HOME"
+      pwd
+    ))"
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME="$( (
+      cd "$JAVA_HOME"
+      pwd
+    ))"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+  javaExecutable="$(which javac)"
+  if [ -n "$javaExecutable" ] && ! [ "$(expr \"$javaExecutable\" : '\([^ ]*\)')" = "no" ]; then
+    # readlink(1) is not available as standard on Solaris 10.
+    readLink=$(which readlink)
+    if [ ! $(expr "$readLink" : '\([^ ]*\)') = "no" ]; then
+      if $darwin; then
+        javaHome="$(dirname \"$javaExecutable\")"
+        javaExecutable="$(cd \"$javaHome\" && pwd -P)/javac"
+      else
+        javaExecutable="$(readlink -f \"$javaExecutable\")"
+      fi
+      javaHome="$(dirname \"$javaExecutable\")"
+      javaHome=$(expr "$javaHome" : '\(.*\)/bin')
+      JAVA_HOME="$javaHome"
+      export JAVA_HOME
+    fi
+  fi
+fi
+
+if [ -z "$JAVACMD" ]; then
+  if [ -n "$JAVA_HOME" ]; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ]; then
+      # IBM's JDK on AIX uses strange locations for the executables
+      JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+      JAVACMD="$JAVA_HOME/bin/java"
+    fi
+  else
+    JAVACMD="$(which java)"
+  fi
+fi
+
+if [ ! -x "$JAVACMD" ]; then
+  echo "Error: JAVA_HOME is not defined correctly." >&2
+  echo "  We cannot execute $JAVACMD" >&2
+  exit 1
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+  echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+  if [ -z "$1" ]; then
+    echo "Path not specified to find_maven_basedir"
+    return 1
+  fi
+
+  basedir="$1"
+  wdir="$1"
+  while [ "$wdir" != '/' ]; do
+    if [ -d "$wdir"/.mvn ]; then
+      basedir=$wdir
+      break
+    fi
+    # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+    if [ -d "${wdir}" ]; then
+      wdir=$(
+        cd "$wdir/.."
+        pwd
+      )
+    fi
+    # end of workaround
+  done
+  echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+  if [ -f "$1" ]; then
+    echo "$(tr -s '\n' ' ' <"$1")"
+  fi
+}
+
+BASE_DIR=$(find_maven_basedir "$(pwd)")
+if [ -z "$BASE_DIR" ]; then
+  exit 1
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+  if [ "$MVNW_VERBOSE" = true ]; then
+    echo "Found .mvn/wrapper/maven-wrapper.jar"
+  fi
+else
+  if [ "$MVNW_VERBOSE" = true ]; then
+    echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+  fi
+  if [ -n "$MVNW_REPOURL" ]; then
+    jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+  else
+    jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+  fi
+  while IFS="=" read key value; do
+    case "$key" in wrapperUrl)
+      jarUrl="$value"
+      break
+      ;;
+    esac
+  done <"$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+  if [ "$MVNW_VERBOSE" = true ]; then
+    echo "Downloading from: $jarUrl"
+  fi
+  wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+  if $cygwin; then
+    wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
+  fi
+
+  if command -v wget >/dev/null; then
+    if [ "$MVNW_VERBOSE" = true ]; then
+      echo "Found wget ... using wget"
+    fi
+    if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+      wget "$jarUrl" -O "$wrapperJarPath"
+    else
+      wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
+    fi
+  elif command -v curl >/dev/null; then
+    if [ "$MVNW_VERBOSE" = true ]; then
+      echo "Found curl ... using curl"
+    fi
+    if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+      curl -o "$wrapperJarPath" "$jarUrl" -f
+    else
+      curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+    fi
+
+  else
+    if [ "$MVNW_VERBOSE" = true ]; then
+      echo "Falling back to using Java to download"
+    fi
+    javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+    # For Cygwin, switch paths to Windows format before running javac
+    if $cygwin; then
+      javaClass=$(cygpath --path --windows "$javaClass")
+    fi
+    if [ -e "$javaClass" ]; then
+      if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+        if [ "$MVNW_VERBOSE" = true ]; then
+          echo " - Compiling MavenWrapperDownloader.java ..."
+        fi
+        # Compiling the Java class
+        ("$JAVA_HOME/bin/javac" "$javaClass")
+      fi
+      if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+        # Running the downloader
+        if [ "$MVNW_VERBOSE" = true ]; then
+          echo " - Running MavenWrapperDownloader.java ..."
+        fi
+        ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+      fi
+    fi
+  fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+  echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+  [ -n "$M2_HOME" ] &&
+    M2_HOME=$(cygpath --path --windows "$M2_HOME")
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
+  [ -n "$CLASSPATH" ] &&
+    CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
+  [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+    MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+  $MAVEN_OPTS \
+  -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+  "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+  ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

+ 182 - 0
mvnw.cmd

@@ -0,0 +1,182 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements.  See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership.  The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License.  You may obtain a copy of the License at
+@REM
+@REM    https://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied.  See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM     e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on"  echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+
+FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+    IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Found %WRAPPER_JAR%
+    )
+) else (
+    if not "%MVNW_REPOURL%" == "" (
+        SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+    )
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Couldn't find %WRAPPER_JAR%, downloading it ...
+        echo Downloading from: %DOWNLOAD_URL%
+    )
+
+    powershell -Command "&{"^
+		"$webclient = new-object System.Net.WebClient;"^
+		"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+		"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+		"}"^
+		"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+		"}"
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Finished downloading %WRAPPER_JAR%
+    )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%

+ 95 - 0
pom.xml

@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.4.13</version>
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+
+    <groupId>com.ggits.tsinfo</groupId>
+    <artifactId>ggits-tsinfo-server</artifactId>
+    <version>0.0.1</version>
+    <name>sig-comm-server</name>
+    <description>GGITS Traffic Signal State Gather Server</description>
+
+    <properties>
+        <java.version>1.8</java.version>
+        <netty.version>4.1.52.Final</netty.version>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <maven.compiler.source>1.8</maven.compiler.source>
+        <maven.compiler.target>1.8</maven.compiler.target>
+        <start-class>com.ggits.tsinfo.server.GgitsTsinfoServerApplication</start-class>
+        <webapp.lib>C:\java\repository</webapp.lib>
+        <maven.test.skip>true</maven.test.skip>
+    </properties>
+
+    <repositories>
+        <repository>
+            <id>jitpack.io</id>
+            <url>https://jitpack.io</url>
+        </repository>
+    </repositories>
+
+    <dependencies>
+
+<!--        <dependency>-->
+<!--            <groupId>com.google.guava</groupId>-->
+<!--            <artifactId>guava</artifactId>-->
+<!--            <version>31.1-jre</version>-->
+<!--        </dependency>-->
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-configuration-processor</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-buffer</artifactId>
+<!--            <version>${netty.version}</version>-->
+        </dependency>
+
+<!--        <dependency>-->
+<!--            <groupId>org.springframework.boot</groupId>-->
+<!--            <artifactId>spring-boot-devtools</artifactId>-->
+<!--            <version>2.7.0</version>-->
+<!--        </dependency>-->
+
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <includeSystemScope>true</includeSystemScope>
+                    <excludeDevtools>false</excludeDevtools>
+                    <excludes>
+                        <exclude>
+                            <groupId>org.projectlombok</groupId>
+                            <artifactId>lombok</artifactId>
+                        </exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 78 - 0
src/main/java/com/ggits/tsinfo/server/GgitsTsinfoServerApplication.java

@@ -0,0 +1,78 @@
+package com.ggits.tsinfo.server;
+
+import com.ggits.tsinfo.server.common.SpringUtils;
+import com.ggits.tsinfo.server.service.TsinfoFileWatcherService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.boot.Banner;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.context.ApplicationPidFileWriter;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.event.ContextClosedEvent;
+import org.springframework.scheduling.annotation.EnableAsync;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+@Slf4j
+@EnableAsync
+@Configuration
+@SpringBootApplication//(exclude = {DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
+public class GgitsTsinfoServerApplication implements CommandLineRunner, ApplicationListener<ContextClosedEvent>, InitializingBean, DisposableBean {
+
+    private static final String APPLICATION_NAME = "ggits-tsinfo-server";
+
+    public static void main(String[] args) {
+        SpringApplication application = new SpringApplicationBuilder()
+                .sources(GgitsTsinfoServerApplication.class)
+                .listeners(new ApplicationPidFileWriter("./conf/" + APPLICATION_NAME + ".pid"))
+                .build();
+        application.setBannerMode(Banner.Mode.OFF);
+        application.run(args);
+    }
+
+    @Override
+    public void run(String... args) throws Exception {
+        SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        log.info("");
+        log.info("");
+        log.info("************************************************************************************");
+        log.info("**                                                                                **");
+        log.info("**                            UTIC Signal System                                  **");
+        log.info("**              GGITS Traffic Signal State Gather Server Program.                 **");
+        log.info("**                                                                                **");
+        log.info("**                                                                   [ver.1.0]    **");
+        log.info("** startup: {}", sdfDate.format(new Date()));
+        log.info("**    HOME: {}", System.getProperty("user.home"));
+        log.info("************************************************************************************");
+
+        TsinfoFileWatcherService tsinfoFileWatcherService = SpringUtils.getBean(TsinfoFileWatcherService.class);
+        tsinfoFileWatcherService.start();
+    }
+
+    public void terminateApplication() {
+//        SigTcpClientCommService sigCommClientService = SpringUtils.getBean(SigTcpClientCommService.class);
+//        sigCommClientService.shutdown();
+    }
+    @Override
+    public void onApplicationEvent(ContextClosedEvent event) {
+        SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        log.error("Application Terminated: {}, {}", sdfDate.format(new Date()), event);
+        terminateApplication();
+    }
+
+    @Override
+    public void destroy() throws Exception {
+        log.error("Application destroy");
+    }
+
+    @Override
+    public void afterPropertiesSet() throws Exception {
+        //log.info("Application afterPropertiesSet");
+    }
+}

+ 41 - 0
src/main/java/com/ggits/tsinfo/server/common/SpringUtils.java

@@ -0,0 +1,41 @@
+package com.ggits.tsinfo.server.common;
+
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Component;
+
+@Component
+public class SpringUtils implements ApplicationContextAware {
+    private static ApplicationContext _applicationContext;
+    private static String _applicationId;
+    private static Environment _environment;
+
+    @Override
+    public void setApplicationContext(ApplicationContext ctx) throws BeansException {
+        _applicationContext = ctx;
+        _applicationId = ctx.getId();
+        _environment = ctx.getEnvironment();
+    }
+
+    public static ApplicationContext getApplicationContext() {
+        return _applicationContext;
+    }
+
+    public static Object getBean(String name){
+        return getApplicationContext().getBean(name);
+    }
+
+    public static <T> T getBean(Class<T> clazz){
+        return getApplicationContext().getBean(clazz);
+    }
+
+    public static <T> T getBean(String name, Class<T> clazz){
+        return getApplicationContext().getBean(name, clazz);
+    }
+
+    public static String[] getAllDefinitionBeanName() {
+        return getApplicationContext().getBeanDefinitionNames();
+    }
+}

+ 77 - 0
src/main/java/com/ggits/tsinfo/server/config/ApplicationConfig.java

@@ -0,0 +1,77 @@
+package com.ggits.tsinfo.server.config;
+
+import com.ggits.tsinfo.server.dto.GgitsRegion;
+import lombok.*;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import javax.validation.constraints.NotBlank;
+import java.util.List;
+
+@Slf4j
+@Data
+@Component
+@ConfigurationProperties(prefix = "application")
+@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
+public class ApplicationConfig {
+
+    @NotBlank
+    private String serverIp = "192.168.10.66";
+    private int serverPort = 8900;
+    private int connectTimeout = 5;
+    private int readerIdleTime = 0;
+    private int writerIdleTime = 0;
+    private int allIdleTime = 0;
+    private int retrySeconds = 10;
+    private boolean commLogging = false;
+
+    @NotBlank
+    private String staPath;
+
+    @NotBlank
+    private List<RegionInfo> regions;
+
+
+    @Getter
+    @Setter
+    @ToString
+    @AllArgsConstructor
+    @NoArgsConstructor
+    public static class RegionInfo {
+        private String region;
+        private int ggitsRegionNo;        /* 경기도 지역 번호 */
+        private String regionCd;        /* 지역 코드 */
+        private int regionId;
+        private String serverIp;
+
+        public GgitsRegion toDto() {
+            String[] data = this.region.split(",");
+            if (data.length != 4) {
+                log.error("Parameter count error: {}, {}", data.length, this.region);
+                return null;
+            }
+            this.ggitsRegionNo = Integer.parseInt(data[0].trim());
+            this.regionCd = data[1].trim();
+            this.regionId = Integer.parseInt(data[2].trim());
+            this.serverIp = data[3].trim();
+            return new GgitsRegion(this.ggitsRegionNo, this.regionCd.trim(), this.regionId, this.serverIp, this.regionId);
+        }
+    }
+
+    @PostConstruct
+    private void init() {
+        if (this.connectTimeout < 5) {
+            this.connectTimeout = 5;
+        }
+        this.writerIdleTime = 10;
+        if (this.retrySeconds < 10) {
+            this.retrySeconds = 10;
+        }
+        log.info("{}", this.regions);
+    }
+
+}

+ 34 - 0
src/main/java/com/ggits/tsinfo/server/dto/GgitsIntStatusDto.java

@@ -0,0 +1,34 @@
+package com.ggits.tsinfo.server.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class GgitsIntStatusDto implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    public String regionCd;    /* 지역 코드 */
+    public String clctTime;
+    public int regionNo;
+    public int intNo;
+    public int ringAP;
+    public int ringAS;
+    public int ringBP;
+    public int ringBS;
+    public boolean comm;
+    public int mapNo;
+    public boolean crs;
+    public int mode;
+    public boolean pnlManCont;
+    public boolean pnlMan;
+    public boolean pnlBlink;
+    public boolean pnlOut;
+    public boolean pnlAS;
+    public boolean pnlOutS;
+    public boolean pnlBlinkS;
+    public boolean pnlDb;
+    public int ppc;
+    public int omit;
+
+}

+ 49 - 0
src/main/java/com/ggits/tsinfo/server/dto/GgitsRegion.java

@@ -0,0 +1,49 @@
+package com.ggits.tsinfo.server.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+@Data
+@Builder
+@NoArgsConstructor//(access = AccessLevel.PROTECTED)
+@AllArgsConstructor
+public class GgitsRegion implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /*
+    *  Region Center properties
+     */
+    private int ggitsRegionNo;        /* 경기도 지역 번호 */
+    private String regionCd;        /* 지역 코드 */
+    private int regionId;
+    private String serverIp;
+    private int serverPort;
+
+    private String clctTime;
+    private int clctCount;
+//    private HashMap<Integer, GgitsIntStatusDto> intMap;
+
+    private String logKey;
+
+    private short sendSeq;
+
+    public GgitsRegion(int ggitsRegionNo, String regionCd, int regionId, String serverIp, int serverPort) {
+        this.ggitsRegionNo = ggitsRegionNo;
+        this.regionCd = regionCd;
+        this.regionId = regionId;
+        this.serverIp = serverIp;
+        this.serverPort = serverPort;
+//        this.intMap = new HashMap<>();
+        this.logKey = String.valueOf(this.ggitsRegionNo);
+
+        initNet();
+    }
+    void initNet() {
+        this.sendSeq  = 0;
+    }
+
+}

+ 80 - 0
src/main/java/com/ggits/tsinfo/server/repository/ApplicationRepository.java

@@ -0,0 +1,80 @@
+package com.ggits.tsinfo.server.repository;
+
+import com.ggits.tsinfo.server.config.ApplicationConfig;
+import com.ggits.tsinfo.server.dto.GgitsRegion;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Slf4j
+@Component
+@RequiredArgsConstructor
+public class ApplicationRepository {
+
+    private final ApplicationConfig config;
+
+    @Getter
+    private final ConcurrentHashMap<Integer, GgitsRegion> centerMap = new ConcurrentHashMap<>();
+
+    @PostConstruct
+    private void init() {
+        log.info("ApplicationRepository.init: Start.");
+        initCenterMap();
+        log.info("ApplicationRepository.init: ..End.");
+    }
+
+    private void initCenterMap() {
+        try {
+            List<ApplicationConfig.RegionInfo> lists  = this.config.getRegions();
+            log.info("TsinfoFileWatcherService.loadCenterInfo: {} EA", lists.size());
+            for (ApplicationConfig.RegionInfo entity : lists) {
+                log.info("TsinfoFileWatcherService.loadCenterInfo: {}.", entity);
+                GgitsRegion dto = entity.toDto();
+                this.centerMap.put(dto.getGgitsRegionNo(), dto);
+            }
+        }
+        catch (Exception e) {
+            log.error("AppRepositoryService.initCtlrInfo: Exception: {}.", e.toString());
+        }
+    }
+
+    @PreDestroy
+    public void destroyService() {
+        log.error("AppRepositoryService.destroy. system terminated.......");
+        this.centerMap.forEach((key, center) -> {
+        });
+    }
+
+    public void reportChannelSessions() {
+        log.info("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
+        //log.info("Report Region Center Channel Sessions Information.");
+        log.info("Center Name       IpAddress       Connect_Count   Connect_Time          Disconnect_Time       Remote_Address");
+        log.info("----------------------------------------------------------------------------------------------------------------");
+        List<Integer> keySet = new ArrayList<>(this.centerMap.keySet());
+        Collections.sort(keySet);
+        //this.centerMap.forEach((key, center) -> {
+        for (Integer key : keySet) {
+            GgitsRegion center = this.centerMap.get(key);
+//            String channelIpAddress = center.getNetState().isActive() ? NettyUtils.getRemoteAddress(center.getNetState().getChannel()) : "---";
+//            log.info("{}", String.format("%-6s %-9s %-15s %-7s %5d   %s   %s   %s",
+//                    center.getRegionCd(),
+//                    center.getRegionNm(),
+//                    center.getIpAddress(),
+//                    center.getNetState().isActive(),
+//                    center.getNetState().getConnectCount(),
+//                    center.getNetState().getConnectTimeString(),
+//                    center.getNetState().getDisconnectTimeString(),
+//                    channelIpAddress));
+        }
+        log.info("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
+    }
+
+}

+ 46 - 0
src/main/java/com/ggits/tsinfo/server/scheduler/ApplicationScheduler.java

@@ -0,0 +1,46 @@
+package com.ggits.tsinfo.server.scheduler;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PreDestroy;
+
+@Slf4j
+@RequiredArgsConstructor
+@EnableScheduling
+@Component
+public class ApplicationScheduler {
+
+    @PreDestroy
+    public void onShutDown() {
+    }
+
+    @Async
+    @Scheduled(cron = "0/10 * * * * *")  // 10초 주기 작업 실행
+    public void reportNodeSessionAlive() {
+//        Elapsed elapsed = new Elapsed();
+//        this.appRepositoryService.reportChannelSessions();
+//        log.info("{}", String.format("%25s: %s", "reportNodeSessionAlive", TimeUtils.elapsedTimeStr(elapsed.nanoSeconds())));
+    }
+
+    @Async
+    @Scheduled(cron = "0/30 * * * * *")  // 10초 주기 작업 실행
+    public void updateProcessState() {
+//        Elapsed elapsed = new Elapsed();
+//        this.unitSystService.updateUnitSystStts(true);
+//        log.info("{}", String.format("%25s: %s", "updateProcessState", TimeUtils.elapsedTimeStr(elapsed.nanoSeconds())));
+    }
+
+    @Async
+    @Scheduled(cron = "0 * * * * *")  // 1분 주기 작업 실행
+    public void staticsForPacketMinute() {
+//        Elapsed elapsed = new Elapsed();
+        //TsiTpmsManager.getInstance().resetMinute();
+        //log.info("{}", String.format("%25s: %s", "staticsForPacketMinute", TimeUtils.elapsedTimeStr(elapsed.nanoSeconds())));
+    }
+
+}

+ 79 - 0
src/main/java/com/ggits/tsinfo/server/service/TsinfoFileWatcherService.java

@@ -0,0 +1,79 @@
+package com.ggits.tsinfo.server.service;
+
+import com.ggits.tsinfo.server.config.ApplicationConfig;
+import com.ggits.tsinfo.server.dto.GgitsRegion;
+import com.ggits.tsinfo.server.repository.ApplicationRepository;
+import com.ggits.tsinfo.server.service.worker.TsinfoFileWorker;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+@Slf4j
+@AllArgsConstructor
+@Service
+public class TsinfoFileWatcherService {
+
+    private final ApplicationConfig config;
+    private final ApplicationRepository repository;
+    private final ThreadGroup workerGroup = new ThreadGroup("TsinfoFileWatcher");
+    private final List<Thread> threadList = new ArrayList<>();
+    private final List<TsinfoFileWorker> workerList = new ArrayList<>();
+
+    @PostConstruct
+    private void init() {
+    }
+
+    public boolean start() {
+        String watchRootDirectory = this.config.getStaPath();
+        Path watchRootPath = Paths.get(watchRootDirectory);
+        if (!Files.exists(watchRootPath)) {
+            log.error("Watch Directory does not exist: {}", watchRootDirectory);
+            return false;
+        }
+        List<Integer> keySet = new ArrayList<>(this.repository.getCenterMap().keySet());
+        Collections.sort(keySet);
+        int idx = 0;
+        for (Integer key : keySet) {
+            GgitsRegion center = this.repository.getCenterMap().get(key);
+            String centerDirectory = this.config.getStaPath() + File.separator + center.getGgitsRegionNo();
+            Path centerPath = Paths.get(centerDirectory);
+            if (!Files.exists(centerPath)) {
+                log.error("Watch Center Directory does not exist: {}, {}, {}", center.getRegionCd(), center.getGgitsRegionNo(), centerDirectory);
+                continue;
+            }
+            try {
+                TsinfoFileWorker tsinfoFileWorker = new TsinfoFileWorker(center, String.valueOf(center.getGgitsRegionNo()), centerDirectory);
+                this.workerList.add(tsinfoFileWorker);
+                Thread worker = new Thread(this.workerGroup, tsinfoFileWorker);
+                worker.setName(String.format("TsinfoFileWatcher-%02d", idx++));
+                worker.setDaemon(true);
+                this.threadList.add(worker);
+            } catch (IOException e) {
+                log.error("Watch Center Directory thread create failed: {}, {}, {}", center.getRegionCd(), center.getGgitsRegionNo(), e.getMessage());
+            }
+        }
+        for (Thread worker : this.threadList) {
+            worker.start();
+        }
+        log.info("TsinfoFileWatcherService: start.");
+        return true;
+    }
+
+    @PreDestroy
+    public void onDestroy() throws Exception {
+        log.error("TsinfoFileWatcherService onDestroy.");
+        for(Thread thread : this.threadList) {
+        }
+    }
+}

+ 93 - 0
src/main/java/com/ggits/tsinfo/server/service/worker/SigProtocolConst.java

@@ -0,0 +1,93 @@
+package com.ggits.tsinfo.server.service.worker;
+
+public class SigProtocolConst {
+    /**
+     * Protocol Format
+     * TYPE    STX   OpCode  Year   /Mon/Day/Hour/Min/Sec Sequence  RegionId Length Count  DATA     CheckSum ETX
+     * Size    1     1       1       1   1   1    1   1   2         2        2      2      N Bytes  1        1
+     * Value   0x02  -       년-2000 -   -   -    -   -   (1~65535) --                              XOR      0x03
+     * -
+     * - Byte Ordering 은 Big Endian (Network Byte Order) 방식 으로 한다.
+     * - Length: Data 의 길이
+     * - Count 는 전송 되는 패킷의 개수 인데 전송 되는 총 데이터의 길이가 1024이하로 전송 되도록 패킷 개수를 조절 한다.
+     * - CheckSum : Data 부의 모든 Byte 를 XOR 한값.
+     * ****************************************************************************************************************
+         Header + Body + Tail
+
+         *** Header...............................................................................
+         STX        - 1 byte
+         OpCode     - 1 byte
+         DateTime   - 6 byte, yymmddhhmiss
+         Sequence   - 2 byte(word)
+         regionId   - 2 byte(word)
+         DataLength - 2 byte(word)
+         Count      - 2 byte(word)
+
+         ***   Data...............................................................................
+         ***   - Count * (OpCode 별 Data Size)
+         ***   Tail...............................................................................
+         CheckSum (1 Byte)
+         ETX
+     * ****************************************************************************************************************/
+
+//     typedef struct _pktHead
+//     {
+//            byte stx   [1]; /*  0 */
+//            byte opcode[1]; /*  1 */
+//            byte year  [1]; /*  2 */
+//            byte mon   [1]; /*  3 */
+//            byte day   [1]; /*  4 */
+//            byte hour  [1]; /*  5 */
+//            byte min   [1]; /*  6 */
+//            byte sec   [1]; /*  7 */
+//            byte seq   [2]; /*  8,  9 */
+//            byte r_id  [2]; /* 10, 11 */
+//            byte len   [2]; /* 12, 13 */
+//            byte count [2]; /* 14, 15 */
+//        } pkt_head, *pkt_headp;
+//
+//        typedef struct _pktFrame
+//        {
+//            pkt_head head;
+//            byte     body[1];
+//        } pkt_frame, *pkt_framep;
+//
+//        typedef struct _pktTail
+//        {
+//            byte crc[1];
+//            byte etx[1];
+//        } pkt_tail, *pkt_tailp;
+
+    public static final int SIG_MAX_PACKET = 4096;      /* 한번에 전송하는 최대 패킷 크기, 4070 */
+    public static final int SIG_BODY_SIZE  = 4070;      /* SIG_MAX_PACKET-SIG_HEAD_SIZE-SIG_TAIL_SIZE */ /* 4096-13-2 = 4081 */
+    public static final int SIG_HEAD_SIZE  = 16;        /* 프로토콜 헤더 크기 16 byte */
+    public static final int SIG_TAIL_SIZE  = 2;         /* 프로토콜 Tail 크기 = checksum 1 byte + etx 1byte */
+    public static final int SIG_PACKET_LENGTH_FIELD_OFFSET = 12;
+    public static final int SIG_PACKET_LENGTH_FIELD_SIZE   = 2;
+    public static final int SIG_PACKET_LENGTH_ADJUSTMENTS  = 2 + SIG_TAIL_SIZE;  /* Length Field 이후의 데이터 나머지 크기 Count(2Byte) + Tail(2Byte)*/
+
+    public static final int SIG_OPCODE_POS = 1;
+
+    public static final byte SIG_STX = (byte)0x02;  /* STX */
+    public static final byte SIG_ETX = (byte)0x03;  /* ETX */
+
+    /**
+     * Protocol OP Code
+     */
+    public static final byte SIG_LOGIN              = (byte)0x10;   // 로그인, 통신 접속시
+    public static final byte SIG_LOGIN_ACK          = (byte)0x11;   // 로그인 응답, 로그인 시(Optional)
+    public static final byte SIG_PHASE_CHANGE       = (byte)0xA1;   // 제어기 실시간 정보, 현시 변경시
+    public static final byte SIG_STATIC_CYCLE       = (byte)0xA2;   // 제어기 정주기 정보, 30초
+    public static final byte SIG_EVENT_INFO         = (byte)0xB1;   // 제어기 이벤트 정보, 이벤트 발생시
+    public static final byte SIG_TODPLAN_SEND       = (byte)0xC1;   // 제어기 DAY PLAN, 1일 1번 전송
+    public static final byte SIG_HOLIDAY_SEND       = (byte)0xC2;   // 제어기 HOLIDAY PLAN, 1일 1번 전송
+    public static final byte SIG_WEEK_SEND          = (byte)0xC3;   // 제어기 WEEK PLAN, 1일 1번 전송
+    public static final byte SIG_FUNCTION_SEND      = (byte)0xC4;   // 제어기 FUNCTION TABLE, 1일 1번 전송
+    public static final byte SIG_SIGNALMAP_SEND     = (byte)0xC5;
+    public static final byte SIG_SIMUL_SEND         = (byte)0xA6;
+    public static final byte SIG_EHIST_SEND         = (byte)0xF1;
+    public static final byte SIG_LOGOUT             = (byte)0xF2;
+    public static final byte SIG_REGION_FILE_UPDATE = (byte)0xFB;
+
+
+}

+ 235 - 0
src/main/java/com/ggits/tsinfo/server/service/worker/TsinfoFileWorker.java

@@ -0,0 +1,235 @@
+package com.ggits.tsinfo.server.service.worker;
+
+import com.ggits.tsinfo.server.dto.GgitsRegion;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.util.StringUtils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.nio.file.*;
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+@Slf4j
+public class TsinfoFileWorker implements Runnable, AutoCloseable {
+
+    private final WatchService service;
+    private final GgitsRegion center;
+    private final String filePath;  // 지역 번호
+    private final String absolutePath; // 파일 절대 경로
+    private final AtomicBoolean running = new AtomicBoolean(false);
+    private InetAddress serverAddress;
+    private DatagramSocket datagramSocket;
+    private int packetSeq = 0;
+
+    public TsinfoFileWorker(GgitsRegion center, String filePath, String absoluteFilePath) throws IOException {
+        this.service = FileSystems.getDefault().newWatchService();
+        this.center = center;
+        this.filePath = filePath;
+        this.absolutePath = absoluteFilePath;
+
+        Path watchPath = FileSystems.getDefault().getPath(absoluteFilePath);
+        watchPath.register(this.service,
+                //StandardWatchEventKinds.ENTRY_CREATE,
+                StandardWatchEventKinds.ENTRY_MODIFY);
+    }
+
+    private boolean initUdpChannel() {
+        try {
+            this.datagramSocket = new DatagramSocket();
+            try {
+                this.serverAddress = InetAddress.getByName(this.center.getServerIp());
+            } catch (UnknownHostException e) {
+                log.error("{}", e.getMessage());
+                return false;
+            }
+            this.datagramSocket.connect(this.serverAddress, this.center.getServerPort());
+        } catch (SocketException e) {
+            log.error("{}", e.getMessage());
+            return false;
+        }
+        return true;
+    }
+    @Override
+    public void run() {
+        if (!initUdpChannel()) {
+            log.error("TsinfoFileWorker.run: initUdpChannel failed: {}, {}", this.filePath, this.absolutePath);
+            return;
+        }
+        log.info("TsinfoFileWorker.run: Start File Watcher: {}, {}", this.filePath, this.absolutePath);
+
+        String oldFileName = "";
+        long oldFileSize = 0;
+        int calDataCount;
+        String createTime;
+        if (this.running.compareAndSet(false, true)) {
+            while (this.running.get()) {
+                WatchKey key;
+
+                try {
+                    key = service.take();
+                }
+                catch (InterruptedException e) {
+                    log.error("{}, {}", this.filePath, e.getMessage());
+                    Thread.currentThread().interrupt();
+                    break;
+                }
+
+                if (key.isValid()) {
+                    List<WatchEvent<?>> watchEvents = key.pollEvents();
+                    for (WatchEvent<?> watchEvent : watchEvents) {
+                        WatchEvent<Path> pathEvent = (WatchEvent<Path>) watchEvent;
+                        Path path = pathEvent.context();
+                        WatchEvent.Kind<Path> eventKind = pathEvent.kind();
+
+                        if (eventKind != StandardWatchEventKinds.ENTRY_MODIFY) {
+                            log.warn("{}, Unsupported event, {}", this.filePath, eventKind.name());
+                            continue;
+                        }
+
+                        // A1-20240723153652.dat
+                        String fileName = path.toString();
+                        if (fileName.length() != 21) {
+                            log.error("{}, FileName Length Error. {}", this.filePath, fileName);
+                            continue;
+                        }
+                        String fileExt = StringUtils.getFilenameExtension(fileName);
+                        if (!"dat".equalsIgnoreCase(fileExt)) {
+                            log.error("{}, FileName Extension Error. {}", this.filePath, fileName);
+                            continue;
+                        }
+
+                        Path absoluteFilePath = FileSystems.getDefault().getPath(this.absolutePath + File.separator + fileName);
+                        long fileSize = absoluteFilePath.toFile().length();
+
+                        if (fileSize == 0) {
+                            log.warn("{}, FileSize is zero, {}", this.filePath, fileName);
+                            continue;
+                        }
+                        if (fileName.equals(oldFileName)) {
+                            log.warn("{}, FileName is equals, {}, {}, {}, {}", this.filePath, fileName, oldFileName, oldFileSize, fileSize);
+                            continue;
+                        }
+
+                        //remainder = (int)(fileSize % 10);
+                        //dataCount = (int)(fileSize / 10);
+                        createTime = fileName.substring(3, 17);
+                        for (int ii = 0; ii < 2; ii++) {
+                            calDataCount = tsinfoDataSend(absoluteFilePath, fileName, createTime);
+                            log.info("{}, DataSend: {}", this.filePath, calDataCount);
+                            if (calDataCount > 0) {
+                                break;
+                            }
+                        }
+                        oldFileName = fileName;
+                        oldFileSize = fileSize;
+//                        if (calDataCount > 0) {
+//                            this.center.setClctTime(createTime);
+//                            this.center.setClctCount(calDataCount);
+//                        }
+                    }
+                    if (!key.reset()) {
+                        log.error("{}, FileWatcher Event Reset Error....", this.filePath);
+                        break;
+                    }
+                }
+            }
+            this.running.set(false);
+        }
+    }
+
+    public int tsinfoDataSend(Path absoluteFilePath, String fileName, String createTime) {
+        int calDataCount = 0;
+        byte[] buffer = new byte[8170];
+        int bytesRead;
+/** Protocol Format
+* TYPE    STX   OpCode  Year   /Mon/Day/Hour/Min/Sec Sequence  RegionId Length Count  DATA     CheckSum ETX
+* Size    1     1       1       1   1   1    1   1   2         2        2      2      N Bytes  1        1
+* Value   0x02  -       년-2000 -   -   -    -   -   (1~65535) --                              XOR      0x03
+* -
+* - Byte Ordering 은 Big Endian (Network Byte Order) 방식 으로 한다.
+* - Length: Data 의 길이
+* - Count 는 전송 되는 패킷의 개수 인데 전송 되는 총 데이터의 길이가 1024이하로 전송 되도록 패킷 개수를 조절 한다.
+* - CheckSum : Data 부의 모든 Byte 를 XOR 한값.
+* *****************************************************************************************************************/
+// UDP Total Packet Size: 8192, Header Size: 16, Data Size: 10 * 817 = 8170, Tail Size: 2
+
+        LocalDateTime now = LocalDateTime.now();
+        byte year = (byte)(now.getYear() - 2000);
+        byte month = (byte)now.getMonthValue();
+        byte day = (byte)now.getDayOfMonth();
+        byte hour = (byte)now.getHour();
+        byte min = (byte)now.getMinute();
+        byte sec = (byte)now.getSecond();
+
+        File file = new File(absoluteFilePath.toString());
+        try (FileInputStream fileInputStream = new FileInputStream(file)) {
+            while ((bytesRead = fileInputStream.read(buffer)) != -1) {
+                // 데이터 길이 계산 (2바이트)
+                short dataLength = (short) bytesRead;
+                short count = (short)(dataLength / 10);
+                this.packetSeq++;
+
+                // Packet Frame Head
+                ByteBuf head = Unpooled.buffer(16);
+
+                head.writeByte(SigProtocolConst.SIG_STX);
+                head.writeByte(SigProtocolConst.SIG_PHASE_CHANGE);
+                head.writeByte(year);
+                head.writeByte(month);
+                head.writeByte(day);
+                head.writeByte(hour);
+                head.writeByte(min);
+                head.writeByte(sec);
+                head.writeShort(this.packetSeq);
+                head.writeShort(this.center.getRegionId());
+                head.writeShort(dataLength);
+                head.writeShort(count);
+
+                // Packet Frame Data
+                ByteBuf data = Unpooled.wrappedBuffer(buffer, 0, bytesRead);
+
+                // Packet Frame Tail
+                ByteBuf tail = Unpooled.buffer(2);
+                tail.writeByte((byte)0x00);
+                tail.writeByte(SigProtocolConst.SIG_ETX);
+
+                // Packet Frame (Head + Data + Tail)
+                ByteBuf packet = Unpooled.wrappedBuffer(head, data, tail);
+
+                // 서버로 전송
+                int length = packet.readableBytes();
+                byte[] bytes = new byte[length];
+                packet.getBytes(packet.readerIndex(), bytes);
+                java.net.DatagramPacket sendPacket = new java.net.DatagramPacket(bytes, bytes.length, this.serverAddress, this.center.getServerPort());
+                this.datagramSocket.send(sendPacket);
+//                log.info("Packet Frame Sent: Data {} EA, Total {} Bytes.", count, length);
+                calDataCount++;
+            }
+        }
+        catch (FileNotFoundException e) {
+            log.warn("{}, {}, File Not Found. {}", this.filePath, absoluteFilePath, e.getMessage());
+            return -1;
+        }
+        catch (IOException e) {
+            log.warn("{}, {}, IOException: {}", this.filePath, absoluteFilePath, e.getMessage());
+            return calDataCount;
+        }
+        return calDataCount;
+    }
+
+    @Override
+    public void close() throws Exception {
+        this.running.set(false);
+        this.service.close();
+    }
+}

+ 17 - 0
src/main/resources/application.yml

@@ -0,0 +1,17 @@
+spring:
+  config:
+      import:
+        - optional:file:${user.dir}/conf/ggits-tsinfo-server.yml
+  application:
+    name: ggits-tsinfo-server
+  main:
+    web-application-type: none
+    log-startup-info: true
+    banner-mode: off
+  output:
+    ansi:
+      enabled: always
+
+application:
+  process-id: 81010
+

+ 77 - 0
src/main/resources/logback-spring-appender.xml

@@ -0,0 +1,77 @@
+<included>
+    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+        <!--        <withJansi>true</withJansi>-->
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <charset>${LOG_CHARSET}</charset>
+            <pattern>${LOG_PATTERN_CONSOLE}</pattern>
+        </encoder>
+    </appender>
+
+    <appender name="FILE_PACKET" class="ch.qos.logback.classic.sift.SiftingAppender">
+        <discriminator>
+            <key>id</key>
+            <defaultValue>${LOG_FILE_NAME_PACKET}</defaultValue>
+        </discriminator>
+        <sift>
+            <appender name="FILE-${id}" class="ch.qos.logback.core.rolling.RollingFileAppender">
+                <file>${LOG_PATH}packet/${id}.log</file>
+                <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+                    <charset>${LOG_CHARSET}</charset>
+                    <Pattern>${LOG_PATTERN_PACKET}</Pattern>
+                </encoder>
+
+                <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+                    <FileNamePattern>${LOG_BACKUP_PATH}packet/${id}.${LOG_FILE_NAME_PATTERN}</FileNamePattern>
+                    <maxFileSize>${MAX_FILESIZE}</maxFileSize>
+                    <maxHistory>${MAX_HISTORY}</maxHistory>
+                </rollingPolicy>
+            </appender>
+        </sift>
+    </appender>
+
+    <appender name="FILE_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${LOG_PATH}${LOG_FILE_NAME}</file>
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <charset>${LOG_CHARSET}</charset>
+            <pattern>${LOG_PATTERN_FILE}</pattern>
+        </encoder>
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${LOG_BACKUP_PATH}${LOG_FILE_NAME}.${LOG_FILE_NAME_PATTERN}</fileNamePattern>
+            <maxFileSize>${MAX_FILESIZE}</maxFileSize>
+            <maxHistory>${MAX_HISTORY}</maxHistory>
+        </rollingPolicy>
+    </appender>
+
+    <appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>error</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+        <file>${LOG_PATH}${LOG_FILE_NAME_ERROR}</file>
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <charset>${LOG_CHARSET}</charset>
+            <pattern>${LOG_PATTERN_ERROR}</pattern>
+        </encoder>
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${LOG_BACKUP_PATH}${LOG_FILE_NAME_ERROR}.${LOG_FILE_NAME_PATTERN}</fileNamePattern>
+            <maxFileSize>${MAX_FILESIZE}</maxFileSize>
+            <maxHistory>${MAX_HISTORY}</maxHistory>
+        </rollingPolicy>
+    </appender>
+
+    <appender name="FILE_SCHEDULE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${LOG_PATH}${LOG_FILE_NAME_SCHEDULE}</file>
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <charset>${LOG_CHARSET}</charset>
+            <pattern>${LOG_PATTERN_SCHEDULE}</pattern>
+        </encoder>
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${LOG_BACKUP_PATH}${LOG_FILE_NAME_SCHEDULE}.${LOG_FILE_NAME_PATTERN}</fileNamePattern>
+            <maxFileSize>${MAX_FILESIZE}</maxFileSize>
+            <maxHistory>${MAX_HISTORY}</maxHistory>
+        </rollingPolicy>
+    </appender>
+
+
+</included>

+ 48 - 0
src/main/resources/logback-spring.xml

@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration scan="true" scanPeriod="60 seconds">
+    <shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/>
+
+    <property name="APP_CLASS_PATH"  value="com.ggits.tsinfo.server"/>
+    <property name="PROJECT_PREFIX"  value="ggits"/>
+    <property name="PROJECT_NAME"    value="${PROJECT_PREFIX}-tsinfo-server"/>
+    <property name="ROOT_LOG_LEVEL"  value="INFO"/>
+    <property name="LOG_CHARSET"     value="UTF-8" />
+    <property name="LOG_PATH"        value="${user.home}/logs/${PROJECT_NAME}/"/>
+    <property name="LOG_BACKUP_PATH" value="${user.home}/logs/${PROJECT_NAME}/backup/"/>
+
+    <property name="LOG_FILE_NAME"             value="${PROJECT_NAME}.log"/>
+    <property name="LOG_FILE_NAME_ERROR"       value="${PROJECT_NAME}.err.log"/>
+    <property name="LOG_FILE_NAME_PATTERN"     value="%d{yyyyMMdd}_%i.log.gz"/>
+    <property name="LOG_FILE_NAME_PACKET"      value="${PROJECT_PREFIX}-packet"/>
+    <property name="LOG_FILE_NAME_SCHEDULE"    value="${PROJECT_PREFIX}-schedule.log"/>
+
+    <property name="MAX_FILESIZE" value="10MB"/>
+    <property name="MAX_HISTORY"  value="30"/>
+    <property name="LOG_PATTERN_FILE"        value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %msg%n"/>
+    <property name="LOG_PATTERN_ERROR"       value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%30t] [%5level] %42logger{35}.%-20M ${PID:-} %n%msg%n"/>
+    <property name="LOG_PATTERN_PACKET"      value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %msg%n"/>
+    <property name="LOG_PATTERN_SCHEDULE"    value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %msg%n"/>
+    <property name="LOG_PATTERN_CONSOLE"     value="[%d{HH:mm:ss.SSS}] [%5level] %msg %n"/>
+
+    <springProfile name="!xxx">
+        <include resource="logback-spring-appender.xml"/>
+    </springProfile>
+
+    <root level="INFO">
+        <appender-ref ref="CONSOLE"/>
+        <appender-ref ref="FILE_LOG"/>
+        <appender-ref ref="FILE_ERROR"/>
+    </root>
+
+    <logger name="${APP_CLASS_PATH}.service" level="INFO" additivity="false">
+        <appender-ref ref="FILE_PACKET"/>
+        <appender-ref ref="FILE_ERROR"/>
+    </logger>
+
+    <logger name="${APP_CLASS_PATH}.scheduler" level="INFO" additivity="false">
+        <appender-ref ref="CONSOLE"/>
+        <appender-ref ref="FILE_SCHEDULE"/>
+        <appender-ref ref="FILE_ERROR"/>
+    </logger>
+
+</configuration>

+ 9 - 0
src/test/java/com/ggits/tsinfo/server/GgitsTsinfoServerApplicationTests.java

@@ -0,0 +1,9 @@
+package com.ggits.tsinfo.server;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+//@SpringBootTest
+public class GgitsTsinfoServerApplicationTests {
+
+}

+ 50 - 0
start.sh

@@ -0,0 +1,50 @@
+#!/bin/sh
+
+#SERVICE_HOME=$(dirname $0)
+USER_HOME=/home/itcs
+SERVICE_HOME=/home/itcs/bin
+
+usage() {
+	echo "Usage:" $0 "[tsinfo]"
+	echo "RUN ggits-tsinfo-server:" $0 "tsinfo"
+	exit
+}
+
+case $1 in
+  tsinfo)
+    SERVICE_NAME=ggits-tsinfo-server
+    SERVICE_VERSION=0.0.1
+    ;;
+  *)
+    usage
+    ;;
+esac
+
+
+EXE_NAME=${SERVICE_HOME}/$SERVICE_NAME-$SERVICE_VERSION.jar
+PID_NAME=$SERVICE_NAME.pid
+SERVICE_PID=$SERVICE_HOME/conf/$PID_NAME
+
+export JAVA_OPT="-server"
+#export JAVA_OPT="$JAVA_OPT -Xms4096m -Xmx4096m"
+export JAVA_OPT="$JAVA_OPT -Xlog:gc*:file=${USER_HOME}/logs/${SERVICE_NAME}/${SERVICE_NAME}.gc.log"
+
+if [ ! -z "$SERVICE_PID" ]; then
+  if [ -f "$SERVICE_PID" ]; then
+    echo "$SERVICE_NAME is already running...."
+    exit
+  fi
+fi
+
+java $JAVA_OPT -jar $EXE_NAME &
+
+echo "$SERVICE_NAME is started...."
+
+sleep 1
+
+ps -eaf | grep $SERVICE_NAME | grep -v grep |wc -l
+
+sleep 1
+
+ps -eaf | grep $SERVICE_NAME | grep -v grep
+

+ 9 - 0
stat.sh

@@ -0,0 +1,9 @@
+#!/bin/sh
+
+export SERVICE_NAME=ggits-
+
+ps -eaf | grep $SERVICE_NAME | grep -v grep | grep -v tail | grep -v kafka | grep java | wc -l
+
+sleep 1
+
+ps -eaf | grep $SERVICE_NAME | grep -v grep | grep -v tail | grep -v kafka | grep java

+ 51 - 0
stop.sh

@@ -0,0 +1,51 @@
+#!/bin/sh
+
+#SERVICE_HOME=$(dirname $0)
+USER_HOME=/home/itcs
+SERVICE_HOME=/home/itcs/bin
+
+usage() {
+    echo "Usage:" $0 "[tsinfo]"
+    echo "RUN ggits-tsinfo-server:" $0 "tsinfo"
+    exit
+}
+
+case $1 in
+  tsinfo)
+    SERVICE_NAME=ggits-tsinfo-server
+    SERVICE_VERSION=0.0.1
+    ;;
+  *)
+    usage
+    ;;
+esac
+
+
+EXE_NAME=$SERVICE_NAME-$SERVICE_VERSION.jar
+PID_NAME=$SERVICE_NAME.pid
+SERVICE_PID=$SERVICE_HOME/conf/$PID_NAME
+
+if [ ! -z "$SERVICE_PID" ]; then
+  if [ -f "$SERVICE_PID" ]; then
+    kill -15 `cat "$SERVICE_PID"` >/dev/null 2>&1
+    echo "$SERVICE_NAME stopping.........."
+  else
+    echo "$SERVICE_NAME is not running...."
+    exit
+  fi
+fi
+
+LOOP=$(seq 0 9)
+for i in $LOOP
+do
+  sleep 1
+  if [ -f "$SERVICE_PID" ]; then
+    echo "$SERVICE_NAME stopping.........."
+  else
+    echo "$SERVICE_NAME stopped.........."
+    exit
+  fi
+done
+
+echo "$SERVICE_NAME cannot be terminated......."
+ps -eaf | grep $SERVICE_NAME | grep -v grep