shjung 3 years ago
parent
commit
9a8fceb487

+ 13 - 1
pom.xml

@@ -15,7 +15,7 @@
     <name>vds-comm-server</name>
     <description>VDS Communication Server</description>
 
-    <packaging>war</packaging>
+    <packaging>jar</packaging>
 
     <repositories>
         <repository>
@@ -181,11 +181,23 @@
             <artifactId>httpclient</artifactId>
             <version>4.5.12</version>
         </dependency>
+        <dependency>
+            <groupId>com.intellij</groupId>
+            <artifactId>forms_rt</artifactId>
+            <version>7.0.3</version>
+        </dependency>
 
     </dependencies>
 
     <build>
         <plugins>
+<!--            <plugin>-->
+<!--                <groupId>org.springframework.boot</groupId>-->
+<!--                <artifactId>spring-boot-maven-plugin</artifactId>-->
+<!--                <configuration>-->
+<!--                    <executable>true</executable>-->
+<!--                </configuration>-->
+<!--            </plugin>-->
             <plugin>
                 <groupId>org.springframework.boot</groupId>
                 <artifactId>spring-boot-maven-plugin</artifactId>

+ 119 - 0
src/main/java/com/its/vds/UI/CtlrSttsTableModel.java

@@ -0,0 +1,119 @@
+package com.its.vds.UI;
+
+import com.its.vds.entity.TbVdsCtlr;
+import lombok.extern.slf4j.Slf4j;
+
+import javax.swing.table.AbstractTableModel;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+@Slf4j
+public class CtlrSttsTableModel extends AbstractTableModel {
+    private static final long serialVersionUID = 1331132425472559704L;
+
+    private final List<TbVdsCtlr> ctlrList = Collections.synchronizedList(new ArrayList<TbVdsCtlr>());
+    private final String[] header = {
+            "S",
+            "번호",
+            "시설물ID",
+            "명칭",
+            "IP",
+            "PORT",
+            "연결상태",
+            "도어",
+            "팬",
+            "히터",
+            "Video",
+    };
+
+    public int getRowCount() {
+        int size = 0;
+        synchronized (this.ctlrList) {
+            size = this.ctlrList.size();
+        }
+        return size;
+    }
+
+    public int getColumnCount() {
+        return header.length;
+    }
+
+    public String getColumnName(int column) {
+        if (column < header.length) {
+            return header[column];
+        }
+        return super.getColumnName(column);
+    }
+
+    public void setValueAt(TbVdsCtlr cctv, int rowIndex, int columnIndex) {
+        synchronized (this.ctlrList) {
+            TbVdsCtlr info = this.ctlrList.get(rowIndex);
+            switch (columnIndex) {
+                case 4:
+                    //info.setM_stat(cctv.getM_stat());
+                    break;
+            }
+        }
+        fireTableCellUpdated(rowIndex, columnIndex);
+        fireTableDataChanged();
+    }
+
+    public Object getValueAt(int rowIndex, int columnIndex) {
+        String ret = "";
+        synchronized (this.ctlrList) {
+            TbVdsCtlr info = this.ctlrList.get(rowIndex);
+            if (info == null) {
+                return "";
+            }
+
+            switch (columnIndex) {
+                case 0:
+                    ret = "";
+                    break;
+                case 1:
+                    ret = info.getVDS_CTLR_NMBR();
+                    break;
+                case 2:
+                    ret = info.getVDS_CTLR_ID();
+                    break;
+                case 3:
+                    ret = info.getVDS_NM();
+                    break;
+                case 4:
+                    ret = info.getVDS_CTLR_IP();
+                    break;
+                case 5:
+                    ret = String.valueOf(info.getVDS_CTLR_PORT());
+                    break;
+                case 6:
+                    ret = "연결";
+                    break;
+                default:
+                    String door = "-";
+                    String fan = "-";
+                    String heater = "-";
+                    String video = "-";
+                    if ("CMS0".equals(info.getStts().getCMNC_STTS_CD())) {
+
+                    }
+                    switch(columnIndex) {
+                        case  7: ret = door; break;
+                        case  8: ret = fan; break;
+                        case  9: ret = heater; break;
+                        case 10: ret = video; break;
+                    }
+            }
+        }
+        return ret;
+    }
+
+    public void Add(TbVdsCtlr info) {
+        int index = 0;
+        synchronized (this.ctlrList) {
+            index = this.ctlrList.size();
+            this.ctlrList.add(info);
+        }
+        fireTableRowsInserted(index, index);
+    }
+}

+ 73 - 0
src/main/java/com/its/vds/UI/JTextAreaOutputStream.java

@@ -0,0 +1,73 @@
+package com.its.vds.UI;
+
+import javax.swing.*;
+import javax.swing.text.BadLocationException;
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class JTextAreaOutputStream extends OutputStream {
+
+    private final JTextArea logArea;
+    public static boolean isLoggingPause = false;
+
+    public JTextAreaOutputStream(JTextArea logArea) {
+        if (logArea == null)
+            throw new IllegalArgumentException ("Destination is null...");
+
+        this.logArea = logArea;
+    }
+
+    public synchronized void logWrite(String text) {
+        Runnable  runnable = new Runnable() {
+            public void run() {
+                logArea.append(text);
+                if (logArea.getDocument().getLength() >
+                        50000) {
+                    try {
+                        logArea.getDocument().remove(0, 5000);
+                    } catch (BadLocationException e) {
+                        //log.error("Can't clean log", e);
+                    }
+                }
+                logArea.setCaretPosition(logArea.getDocument().getLength());
+            }
+        };
+        SwingUtilities.invokeLater(runnable);
+    }
+
+    @Override
+    public void write(byte[] buffer, int offset, int length) throws IOException
+    {
+        if (isLoggingPause) {
+            return;
+        }
+
+        final String text = new String(buffer, offset, length);
+        //logWrite(text);
+        SwingUtilities.invokeLater(new Runnable ()
+        {
+            @Override
+            public void run()
+            {
+                synchronized (logArea) {
+//                    if (logArea.getDocument().getLength() > 50000) {
+//                        try {
+//                            logArea.getDocument().remove(0,5000);
+//                        } catch (BadLocationException e) {
+//                        }
+//                    }
+                    if (logArea.getLineCount() > 500) {
+                        logArea.setText(null);
+                    }
+                    logArea.append(text);
+                    logArea.setCaretPosition(logArea.getDocument().getLength());
+                }
+            }
+        });
+    }
+
+    @Override
+    public void write(int b) throws IOException {
+        write (new byte [] {(byte)b}, 0, 1);
+    }
+}

+ 293 - 0
src/main/java/com/its/vds/UI/MainUI.form

@@ -0,0 +1,293 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.its.vds.UI.MainUI">
+  <grid id="27dc6" binding="rootPanel" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+    <margin top="0" left="0" bottom="0" right="0"/>
+    <constraints>
+      <xy x="20" y="20" width="841" height="620"/>
+    </constraints>
+    <properties/>
+    <border type="none"/>
+    <children>
+      <grid id="d0095" binding="pnlCtlr" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+        <margin top="10" left="4" bottom="0" right="4"/>
+        <constraints>
+          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties/>
+        <border type="none"/>
+        <children>
+          <grid id="d1b2f" binding="pnlCtlrTitle" layout-manager="GridLayoutManager" row-count="1" column-count="6" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+            <margin top="0" left="0" bottom="0" right="0"/>
+            <constraints>
+              <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+            </constraints>
+            <properties/>
+            <border type="none"/>
+            <children>
+              <component id="25222" class="javax.swing.JLabel">
+                <constraints>
+                  <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties>
+                  <font name="Malgun Gothic" size="12" style="0"/>
+                  <horizontalAlignment value="2"/>
+                  <horizontalTextPosition value="11"/>
+                  <icon value="static/image/controller.png"/>
+                  <text value="제어기 정보"/>
+                </properties>
+              </component>
+              <hspacer id="e90f6">
+                <constraints>
+                  <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+                </constraints>
+              </hspacer>
+              <component id="c9b9" class="javax.swing.JLabel">
+                <constraints>
+                  <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties>
+                  <font name="Malgun Gothic" size="12" style="0"/>
+                  <text value="제어기 전체: "/>
+                </properties>
+              </component>
+              <component id="20b88" class="javax.swing.JLabel">
+                <constraints>
+                  <grid row="0" column="4" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties>
+                  <font name="Malgun Gothic" size="12" style="0"/>
+                  <text value="통신 이상: "/>
+                </properties>
+              </component>
+              <component id="baf10" class="javax.swing.JLabel" binding="lblTotal">
+                <constraints>
+                  <grid row="0" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties>
+                  <font name="Malgun Gothic" size="12" style="1"/>
+                  <horizontalAlignment value="0"/>
+                  <horizontalTextPosition value="0"/>
+                  <text value="     -"/>
+                </properties>
+              </component>
+              <component id="1c841" class="javax.swing.JLabel" binding="lblError">
+                <constraints>
+                  <grid row="0" column="5" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties>
+                  <font name="Malgun Gothic" size="12" style="1"/>
+                  <foreground color="-65536"/>
+                  <horizontalAlignment value="0"/>
+                  <horizontalTextPosition value="0"/>
+                  <text value="     -"/>
+                </properties>
+              </component>
+            </children>
+          </grid>
+          <scrollpane id="b21be">
+            <constraints>
+              <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+            </constraints>
+            <properties/>
+            <border type="none"/>
+            <children>
+              <component id="a0dd1" class="javax.swing.JTable" binding="tblCtlr">
+                <constraints/>
+                <properties>
+                  <font name="Malgun Gothic" size="12" style="0"/>
+                </properties>
+              </component>
+            </children>
+          </scrollpane>
+        </children>
+      </grid>
+      <grid id="1a658" binding="pnlLog" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+        <margin top="0" left="4" bottom="0" right="4"/>
+        <constraints>
+          <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false">
+            <minimum-size width="-1" height="250"/>
+            <preferred-size width="-1" height="250"/>
+            <maximum-size width="-1" height="250"/>
+          </grid>
+        </constraints>
+        <properties/>
+        <border type="none"/>
+        <children>
+          <grid id="dbb05" binding="pnlLogTitle" layout-manager="GridLayoutManager" row-count="1" column-count="6" same-size-horizontally="false" same-size-vertically="false" hgap="1" vgap="1">
+            <margin top="0" left="0" bottom="0" right="0"/>
+            <constraints>
+              <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+            </constraints>
+            <properties/>
+            <border type="none"/>
+            <children>
+              <component id="9ac90" class="javax.swing.JLabel">
+                <constraints>
+                  <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties>
+                  <font name="Malgun Gothic" size="12" style="0"/>
+                  <horizontalAlignment value="2"/>
+                  <icon value="static/image/logging.png"/>
+                  <text value="시스템 로그"/>
+                </properties>
+              </component>
+              <hspacer id="656fd">
+                <constraints>
+                  <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+                </constraints>
+              </hspacer>
+              <component id="df2a0" class="javax.swing.JButton" binding="btnLogDirOpen">
+                <constraints>
+                  <grid row="0" column="5" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties>
+                  <font name="Malgun Gothic" size="12" style="0"/>
+                  <horizontalTextPosition value="0"/>
+                  <text value="로그 폴더"/>
+                </properties>
+              </component>
+              <component id="69a98" class="javax.swing.JButton" binding="btnLogPause">
+                <constraints>
+                  <grid row="0" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties>
+                  <font name="Malgun Gothic" size="12" style="0"/>
+                  <horizontalTextPosition value="0"/>
+                  <text value="지우기"/>
+                </properties>
+              </component>
+              <component id="1e9e7" class="javax.swing.JCheckBox" binding="chkLogPause">
+                <constraints>
+                  <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties>
+                  <font name="Malgun Gothic" size="12" style="0"/>
+                  <horizontalAlignment value="0"/>
+                  <horizontalTextPosition value="11"/>
+                  <text value="멈춤"/>
+                </properties>
+              </component>
+              <component id="ba97c" class="javax.swing.JButton" binding="btnLogCopy">
+                <constraints>
+                  <grid row="0" column="4" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
+                </constraints>
+                <properties>
+                  <font name="Malgun Gothic" size="12" style="0"/>
+                  <text value="복사"/>
+                </properties>
+              </component>
+            </children>
+          </grid>
+          <scrollpane id="a6866">
+            <constraints>
+              <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+            </constraints>
+            <properties/>
+            <border type="none"/>
+            <children>
+              <component id="8ce8a" class="javax.swing.JTextArea" binding="taLog">
+                <constraints/>
+                <properties>
+                  <background color="-16777216"/>
+                  <caretColor color="-1"/>
+                  <editable value="false"/>
+                  <font name="D2Coding" size="14" style="0"/>
+                  <foreground color="-1"/>
+                  <margin top="4" left="4" bottom="4" right="4"/>
+                </properties>
+              </component>
+            </children>
+          </scrollpane>
+        </children>
+      </grid>
+      <grid id="e0774" binding="pnlStatusBar" layout-manager="GridLayoutManager" row-count="1" column-count="7" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+        <margin top="0" left="4" bottom="4" right="4"/>
+        <constraints>
+          <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+        </constraints>
+        <properties/>
+        <border type="none"/>
+        <children>
+          <hspacer id="653ec">
+            <constraints>
+              <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+            </constraints>
+          </hspacer>
+          <component id="20f9" class="javax.swing.JLabel" binding="lblSystime">
+            <constraints>
+              <grid row="0" column="6" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
+            </constraints>
+            <properties>
+              <font name="Malgun Gothic" size="12" style="1"/>
+              <horizontalAlignment value="0"/>
+              <horizontalTextPosition value="0"/>
+              <text value=" 2022-08-04 13:24:33 "/>
+            </properties>
+          </component>
+          <component id="a516b" class="javax.swing.JLabel">
+            <constraints>
+              <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+            </constraints>
+            <properties>
+              <icon value="static/image/on.png"/>
+              <text value=" "/>
+            </properties>
+          </component>
+          <component id="94189" class="javax.swing.JLabel" binding="lblCpuRate">
+            <constraints>
+              <grid row="0" column="5" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+                <minimum-size width="40" height="-1"/>
+                <preferred-size width="40" height="-1"/>
+                <maximum-size width="40" height="-1"/>
+              </grid>
+            </constraints>
+            <properties>
+              <font name="Malgun Gothic" size="12" style="1"/>
+              <horizontalAlignment value="2"/>
+              <horizontalTextPosition value="0"/>
+              <text value="    "/>
+            </properties>
+          </component>
+          <component id="19dbe" class="javax.swing.JLabel" binding="lblMemoryUsage">
+            <constraints>
+              <grid row="0" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+                <minimum-size width="40" height="-1"/>
+                <preferred-size width="40" height="-1"/>
+                <maximum-size width="40" height="-1"/>
+              </grid>
+            </constraints>
+            <properties>
+              <font name="Malgun Gothic" size="12" style="1"/>
+              <horizontalAlignment value="2"/>
+              <horizontalTextPosition value="0"/>
+              <text value="    "/>
+            </properties>
+          </component>
+          <component id="f6d5e" class="javax.swing.JLabel">
+            <constraints>
+              <grid row="0" column="4" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
+            </constraints>
+            <properties>
+              <font name="Malgun Gothic" size="12" style="0"/>
+              <horizontalAlignment value="0"/>
+              <horizontalTextPosition value="0"/>
+              <text value="  CPU 사용율(%):"/>
+            </properties>
+          </component>
+          <component id="d8ff5" class="javax.swing.JLabel">
+            <constraints>
+              <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
+            </constraints>
+            <properties>
+              <font name="Malgun Gothic" size="12" style="0"/>
+              <horizontalAlignment value="0"/>
+              <horizontalTextPosition value="0"/>
+              <text value="  메모리 사용율(%):"/>
+            </properties>
+          </component>
+        </children>
+      </grid>
+    </children>
+  </grid>
+</form>

+ 374 - 0
src/main/java/com/its/vds/UI/MainUI.java

@@ -0,0 +1,374 @@
+package com.its.vds.UI;
+
+import com.intellij.uiDesigner.core.GridConstraints;
+import com.intellij.uiDesigner.core.GridLayoutManager;
+import com.intellij.uiDesigner.core.Spacer;
+import com.its.app.utils.SysUtils;
+import com.its.vds.entity.TbVdsCtlr;
+import com.its.vds.global.AppRepository;
+import com.its.vds.service.VdsCtlrService;
+import com.sun.management.OperatingSystemMXBean;
+import lombok.Getter;
+import org.apache.commons.lang.StringUtils;
+
+import javax.swing.*;
+import javax.swing.plaf.FontUIResource;
+import javax.swing.text.StyleContext;
+import java.awt.*;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.StringSelection;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.util.Locale;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+@Getter
+public class MainUI {
+    private static MainUI _instance = null;
+    private VdsCtlrService vdsCtlrService = null;
+    OperatingSystemMXBean osBean = null;
+    private Timer timer;
+    private Long tick = Long.valueOf(0);
+
+    private CtlrSttsTableModel ctlrSttsTableModel = new CtlrSttsTableModel();
+
+    private JPanel rootPanel;
+    private JPanel pnlCtlr;
+    private JPanel pnlLog;
+    private JPanel pnlLogTitle;
+    private JPanel pnlCtlrTitle;
+    private JButton btnLogDirOpen;
+    private JButton btnLogPause;
+    private JCheckBox chkLogPause;
+    private JLabel lblSystime;
+    private JPanel pnlStatusBar;
+    private JTable tblCtlr;
+    private JTextArea taLog;
+    private JButton btnLogCopy;
+    private JLabel lblTotal;
+    private JLabel lblError;
+    private JLabel lblCpuRate;
+    private JLabel lblMemoryUsage;
+
+    public static MainUI getInstance() {
+        return _instance;
+    }
+
+    public void displaySystime() {
+        lblSystime.setText(" " + SysUtils.getSysTimeStr() + "  ");
+    }
+
+    public void displayResource() {
+        long memoryUsage = Math.round(((double) (osBean.getTotalPhysicalMemorySize() - osBean.getFreePhysicalMemorySize())) / (double) osBean.getTotalPhysicalMemorySize() * 100.0);
+        lblMemoryUsage.setText(String.valueOf(memoryUsage));
+        double cpuLoad = osBean.getSystemCpuLoad();
+        lblCpuRate.setText(String.valueOf(Math.round(cpuLoad * 100.0)));
+    }
+
+    public MainUI() {
+        if (_instance == null) {
+            _instance = this;
+        }
+        osBean = ManagementFactory.getPlatformMXBean(OperatingSystemMXBean.class);
+
+        displaySystime();
+        displayResource();
+        //task = new MonitoringTask();
+        timer = new Timer(1000, new ActionListener() {
+            public void actionPerformed(ActionEvent evt) {
+                displaySystime();
+                tick++;
+                if (tick % 5 == 0) {
+                    displayResource();
+                }
+            }
+        });
+        timer.start();
+
+        chkLogPause.setFocusable(false);
+        btnLogPause.setFocusable(false);
+        btnLogDirOpen.setFocusable(false);
+        btnLogCopy.setFocusable(false);
+
+        initTblListHeader();
+
+        btnLogPause.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                taLog.setText(null);
+            }
+        });
+        btnLogDirOpen.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                Runtime rt = Runtime.getRuntime();
+                try {
+                    rt.exec("explorer.exe logs");
+                } catch (IOException ex) {
+                    throw new RuntimeException(ex);
+                }
+            }
+        });
+        chkLogPause.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                JTextAreaOutputStream.isLoggingPause = chkLogPause.isSelected();
+            }
+        });
+        btnLogCopy.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                StringSelection stringSelection = new StringSelection(taLog.getText());
+                Clipboard clpBrd = Toolkit.getDefaultToolkit().getSystemClipboard();
+                clpBrd.setContents(stringSelection, null);
+            }
+        });
+    }
+
+    /**
+     * 목록 헤더 생성
+     */
+    private void initTblListHeader() {
+
+        tblCtlr.setModel(ctlrSttsTableModel);
+        tblCtlr.setBackground(Color.WHITE);
+        tblCtlr.setSelectionMode(1);
+        //tblCtlr.addMouseListener(new ListMouseListener(null));
+        tblCtlr.getColumnModel().getColumn(0).setPreferredWidth(50);
+        tblCtlr.getColumnModel().getColumn(1).setPreferredWidth(100);
+        tblCtlr.getColumnModel().getColumn(2).setPreferredWidth(100);
+        tblCtlr.getColumnModel().getColumn(3).setPreferredWidth(210);
+        tblCtlr.getColumnModel().getColumn(4).setPreferredWidth(50);
+//
+//        this.defaultTableCellRenderer = new DefaultTableCellRenderer();
+//        this.defaultTableCellRenderer.setHorizontalAlignment(0);
+//        this.defaultTableCellRenderer.setBackground(new Color(255, 220, 220));
+//        this.tableColumnModel = tblCtlr.getColumnModel();
+//        for (int i = 0; i < this.tableColumnModel.getColumnCount(); i++)
+//            this.tableColumnModel.getColumn(i).setCellRenderer(this.defaultTableCellRenderer);
+//        this.tableCellRenderer = new CommTableCellRenderer();
+//        try {
+//            tblCtlr.setDefaultRenderer(Class.forName("java.lang.String"), this.tableCellRenderer);
+//        } catch (ClassNotFoundException ex) {
+//            System.exit(0);
+//        }
+    }
+
+    public void LoadControllerInfo(VdsCtlrService vdsCtlrService) {
+        this.vdsCtlrService = vdsCtlrService;
+
+        SortedMap<Integer, TbVdsCtlr> ctlrMap = new TreeMap<>();
+        for (Map.Entry<String, TbVdsCtlr> e : AppRepository.getInstance().getCtlrMap().entrySet()) {
+            TbVdsCtlr obj = e.getValue();
+            if (StringUtils.equals("N", obj.getDEL_YN()) && StringUtils.equals("Y", obj.getVALD_YN())) {
+                ctlrMap.put(Integer.valueOf(obj.getVDS_CTLR_NMBR()), obj);
+            }
+        }
+
+        int ctlrTotal = ctlrMap.size();
+        int ctlrError = 0;
+        for (Map.Entry<Integer, TbVdsCtlr> e : ctlrMap.entrySet()) {
+            TbVdsCtlr obj = e.getValue();
+            ctlrSttsTableModel.Add(obj);
+            if (!"CMS0".equals(obj.getStts().getCMNC_STTS_CD())) {
+                ctlrError++;
+            }
+        }
+        lblTotal.setText(" " + ctlrTotal + " ");
+        lblError.setText(" " + ctlrError + " ");
+    }
+
+    {
+// GUI initializer generated by IntelliJ IDEA GUI Designer
+// >>> IMPORTANT!! <<<
+// DO NOT EDIT OR ADD ANY CODE HERE!
+        $$$setupUI$$$();
+    }
+
+    /**
+     * Method generated by IntelliJ IDEA GUI Designer
+     * >>> IMPORTANT!! <<<
+     * DO NOT edit this method OR call it in your code!
+     *
+     * @noinspection ALL
+     */
+    private void $$$setupUI$$$() {
+        rootPanel = new JPanel();
+        rootPanel.setLayout(new GridLayoutManager(3, 1, new Insets(0, 0, 0, 0), -1, -1));
+        pnlCtlr = new JPanel();
+        pnlCtlr.setLayout(new GridLayoutManager(2, 1, new Insets(10, 4, 0, 4), -1, -1));
+        rootPanel.add(pnlCtlr, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
+        pnlCtlrTitle = new JPanel();
+        pnlCtlrTitle.setLayout(new GridLayoutManager(1, 6, new Insets(0, 0, 0, 0), -1, -1));
+        pnlCtlr.add(pnlCtlrTitle, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
+        final JLabel label1 = new JLabel();
+        Font label1Font = this.$$$getFont$$$("Malgun Gothic", Font.PLAIN, 12, label1.getFont());
+        if (label1Font != null) label1.setFont(label1Font);
+        label1.setHorizontalAlignment(2);
+        label1.setHorizontalTextPosition(11);
+        label1.setIcon(new ImageIcon(getClass().getResource("/static/image/controller.png")));
+        label1.setText("제어기 정보");
+        pnlCtlrTitle.add(label1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+        final Spacer spacer1 = new Spacer();
+        pnlCtlrTitle.add(spacer1, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false));
+        final JLabel label2 = new JLabel();
+        Font label2Font = this.$$$getFont$$$("Malgun Gothic", Font.PLAIN, 12, label2.getFont());
+        if (label2Font != null) label2.setFont(label2Font);
+        label2.setText("제어기 전체: ");
+        pnlCtlrTitle.add(label2, new GridConstraints(0, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+        final JLabel label3 = new JLabel();
+        Font label3Font = this.$$$getFont$$$("Malgun Gothic", Font.PLAIN, 12, label3.getFont());
+        if (label3Font != null) label3.setFont(label3Font);
+        label3.setText("통신 이상: ");
+        pnlCtlrTitle.add(label3, new GridConstraints(0, 4, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+        lblTotal = new JLabel();
+        Font lblTotalFont = this.$$$getFont$$$("Malgun Gothic", Font.BOLD, 12, lblTotal.getFont());
+        if (lblTotalFont != null) lblTotal.setFont(lblTotalFont);
+        lblTotal.setHorizontalAlignment(0);
+        lblTotal.setHorizontalTextPosition(0);
+        lblTotal.setText("     -");
+        pnlCtlrTitle.add(lblTotal, new GridConstraints(0, 3, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+        lblError = new JLabel();
+        Font lblErrorFont = this.$$$getFont$$$("Malgun Gothic", Font.BOLD, 12, lblError.getFont());
+        if (lblErrorFont != null) lblError.setFont(lblErrorFont);
+        lblError.setForeground(new Color(-65536));
+        lblError.setHorizontalAlignment(0);
+        lblError.setHorizontalTextPosition(0);
+        lblError.setText("     -");
+        pnlCtlrTitle.add(lblError, new GridConstraints(0, 5, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+        final JScrollPane scrollPane1 = new JScrollPane();
+        pnlCtlr.add(scrollPane1, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
+        tblCtlr = new JTable();
+        Font tblCtlrFont = this.$$$getFont$$$("Malgun Gothic", Font.PLAIN, 12, tblCtlr.getFont());
+        if (tblCtlrFont != null) tblCtlr.setFont(tblCtlrFont);
+        scrollPane1.setViewportView(tblCtlr);
+        pnlLog = new JPanel();
+        pnlLog.setLayout(new GridLayoutManager(2, 1, new Insets(0, 4, 0, 4), -1, -1));
+        rootPanel.add(pnlLog, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, new Dimension(-1, 250), new Dimension(-1, 250), new Dimension(-1, 250), 0, false));
+        pnlLogTitle = new JPanel();
+        pnlLogTitle.setLayout(new GridLayoutManager(1, 6, new Insets(0, 0, 0, 0), 1, 1));
+        pnlLog.add(pnlLogTitle, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
+        final JLabel label4 = new JLabel();
+        Font label4Font = this.$$$getFont$$$("Malgun Gothic", Font.PLAIN, 12, label4.getFont());
+        if (label4Font != null) label4.setFont(label4Font);
+        label4.setHorizontalAlignment(2);
+        label4.setIcon(new ImageIcon(getClass().getResource("/static/image/logging.png")));
+        label4.setText("시스템 로그");
+        pnlLogTitle.add(label4, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+        final Spacer spacer2 = new Spacer();
+        pnlLogTitle.add(spacer2, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false));
+        btnLogDirOpen = new JButton();
+        Font btnLogDirOpenFont = this.$$$getFont$$$("Malgun Gothic", Font.PLAIN, 12, btnLogDirOpen.getFont());
+        if (btnLogDirOpenFont != null) btnLogDirOpen.setFont(btnLogDirOpenFont);
+        btnLogDirOpen.setHorizontalTextPosition(0);
+        btnLogDirOpen.setText("로그 폴더");
+        pnlLogTitle.add(btnLogDirOpen, new GridConstraints(0, 5, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+        btnLogPause = new JButton();
+        Font btnLogPauseFont = this.$$$getFont$$$("Malgun Gothic", Font.PLAIN, 12, btnLogPause.getFont());
+        if (btnLogPauseFont != null) btnLogPause.setFont(btnLogPauseFont);
+        btnLogPause.setHorizontalTextPosition(0);
+        btnLogPause.setText("지우기");
+        pnlLogTitle.add(btnLogPause, new GridConstraints(0, 3, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+        chkLogPause = new JCheckBox();
+        Font chkLogPauseFont = this.$$$getFont$$$("Malgun Gothic", Font.PLAIN, 12, chkLogPause.getFont());
+        if (chkLogPauseFont != null) chkLogPause.setFont(chkLogPauseFont);
+        chkLogPause.setHorizontalAlignment(0);
+        chkLogPause.setHorizontalTextPosition(11);
+        chkLogPause.setText("멈춤");
+        pnlLogTitle.add(chkLogPause, new GridConstraints(0, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+        btnLogCopy = new JButton();
+        Font btnLogCopyFont = this.$$$getFont$$$("Malgun Gothic", Font.PLAIN, 12, btnLogCopy.getFont());
+        if (btnLogCopyFont != null) btnLogCopy.setFont(btnLogCopyFont);
+        btnLogCopy.setText("복사");
+        pnlLogTitle.add(btnLogCopy, new GridConstraints(0, 4, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+        final JScrollPane scrollPane2 = new JScrollPane();
+        pnlLog.add(scrollPane2, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
+        taLog = new JTextArea();
+        taLog.setBackground(new Color(-16777216));
+        taLog.setCaretColor(new Color(-1));
+        taLog.setEditable(false);
+        Font taLogFont = this.$$$getFont$$$("D2Coding", Font.PLAIN, 14, taLog.getFont());
+        if (taLogFont != null) taLog.setFont(taLogFont);
+        taLog.setForeground(new Color(-1));
+        taLog.setMargin(new Insets(4, 4, 4, 4));
+        scrollPane2.setViewportView(taLog);
+        pnlStatusBar = new JPanel();
+        pnlStatusBar.setLayout(new GridLayoutManager(1, 7, new Insets(0, 4, 4, 4), -1, -1));
+        rootPanel.add(pnlStatusBar, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
+        final Spacer spacer3 = new Spacer();
+        pnlStatusBar.add(spacer3, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false));
+        lblSystime = new JLabel();
+        Font lblSystimeFont = this.$$$getFont$$$("Malgun Gothic", Font.BOLD, 12, lblSystime.getFont());
+        if (lblSystimeFont != null) lblSystime.setFont(lblSystimeFont);
+        lblSystime.setHorizontalAlignment(0);
+        lblSystime.setHorizontalTextPosition(0);
+        lblSystime.setText(" 2022-08-04 13:24:33 ");
+        pnlStatusBar.add(lblSystime, new GridConstraints(0, 6, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+        final JLabel label5 = new JLabel();
+        label5.setIcon(new ImageIcon(getClass().getResource("/static/image/on.png")));
+        label5.setText(" ");
+        pnlStatusBar.add(label5, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+        lblCpuRate = new JLabel();
+        Font lblCpuRateFont = this.$$$getFont$$$("Malgun Gothic", Font.BOLD, 12, lblCpuRate.getFont());
+        if (lblCpuRateFont != null) lblCpuRate.setFont(lblCpuRateFont);
+        lblCpuRate.setHorizontalAlignment(2);
+        lblCpuRate.setHorizontalTextPosition(0);
+        lblCpuRate.setText("    ");
+        pnlStatusBar.add(lblCpuRate, new GridConstraints(0, 5, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, new Dimension(40, -1), new Dimension(40, -1), new Dimension(40, -1), 0, false));
+        lblMemoryUsage = new JLabel();
+        Font lblMemoryUsageFont = this.$$$getFont$$$("Malgun Gothic", Font.BOLD, 12, lblMemoryUsage.getFont());
+        if (lblMemoryUsageFont != null) lblMemoryUsage.setFont(lblMemoryUsageFont);
+        lblMemoryUsage.setHorizontalAlignment(2);
+        lblMemoryUsage.setHorizontalTextPosition(0);
+        lblMemoryUsage.setText("    ");
+        pnlStatusBar.add(lblMemoryUsage, new GridConstraints(0, 3, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, new Dimension(40, -1), new Dimension(40, -1), new Dimension(40, -1), 0, false));
+        final JLabel label6 = new JLabel();
+        Font label6Font = this.$$$getFont$$$("Malgun Gothic", Font.PLAIN, 12, label6.getFont());
+        if (label6Font != null) label6.setFont(label6Font);
+        label6.setHorizontalAlignment(0);
+        label6.setHorizontalTextPosition(0);
+        label6.setText("  CPU 사용율(%):");
+        pnlStatusBar.add(label6, new GridConstraints(0, 4, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+        final JLabel label7 = new JLabel();
+        Font label7Font = this.$$$getFont$$$("Malgun Gothic", Font.PLAIN, 12, label7.getFont());
+        if (label7Font != null) label7.setFont(label7Font);
+        label7.setHorizontalAlignment(0);
+        label7.setHorizontalTextPosition(0);
+        label7.setText("  메모리 사용율(%):");
+        pnlStatusBar.add(label7, new GridConstraints(0, 2, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+    }
+
+    /**
+     * @noinspection ALL
+     */
+    private Font $$$getFont$$$(String fontName, int style, int size, Font currentFont) {
+        if (currentFont == null) return null;
+        String resultName;
+        if (fontName == null) {
+            resultName = currentFont.getName();
+        } else {
+            Font testFont = new Font(fontName, Font.PLAIN, 10);
+            if (testFont.canDisplay('a') && testFont.canDisplay('1')) {
+                resultName = fontName;
+            } else {
+                resultName = currentFont.getName();
+            }
+        }
+        Font font = new Font(resultName, style >= 0 ? style : currentFont.getStyle(), size >= 0 ? size : currentFont.getSize());
+        boolean isMac = System.getProperty("os.name", "").toLowerCase(Locale.ENGLISH).startsWith("mac");
+        Font fontWithFallback = isMac ? new Font(font.getFamily(), font.getStyle(), font.getSize()) : new StyleContext().getFont(font.getFamily(), font.getStyle(), font.getSize());
+        return fontWithFallback instanceof FontUIResource ? fontWithFallback : new FontUIResource(fontWithFallback);
+    }
+
+    /**
+     * @noinspection ALL
+     */
+    public JComponent $$$getRootComponent$$$() {
+        return rootPanel;
+    }
+
+}

+ 93 - 0
src/main/java/com/its/vds/UI/MonitoringTask.java

@@ -0,0 +1,93 @@
+package com.its.vds.UI;
+
+import javax.swing.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public class MonitoringTask {
+	
+	private static final int TASK_LENGTH = 1000;
+	private AtomicBoolean isStarted =  new AtomicBoolean(false);
+	private AtomicBoolean isRunning = new AtomicBoolean(false);
+	private AtomicBoolean isDone = new AtomicBoolean(false);
+	private int lengthOfTask;
+	private int current = 0;	
+	private String statMessage;
+
+	public MonitoringTask() {
+		lengthOfTask = TASK_LENGTH;
+	}
+
+	public void go() {
+		isRunning.set(true);
+		if (!isStarted.get()) {
+			isDone.set(false);
+			isStarted.set(true);
+			statMessage = null;
+			current = 0;
+			final SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
+				@Override
+				protected Void doInBackground() throws Exception {
+					// Fake a long task, making a random amount of progress every second.
+					while (!isDone.get()) {
+						if (isRunning.get()) {
+							try {
+								Thread.sleep(1000); // sleep for a second
+								current += Math.random() * 100; // make some progress
+								if (current >= lengthOfTask) {
+									onDown();
+									current = lengthOfTask;
+								}
+								statMessage = "Completed " + current + " out of " + lengthOfTask + ".";
+							} catch (InterruptedException e) {
+								e.printStackTrace();
+							}
+						}
+					}
+					return null;
+				}
+			};
+			worker.execute();
+		}
+	}
+
+	public void pause() {
+		this.isRunning.set(false);
+	}
+
+	/**
+	 * Called from SwingTimerDemo to find out how much work needs to be done.
+	 */
+	public int getLengthOfTask() {
+		return lengthOfTask;
+	}
+
+	/**
+	 * Called from SwingTimerDemo to find out how much has been done.
+	 */
+	public int getCurrent() {
+		return current;
+	}
+
+	public void onDown() {
+		isDone.set(true);
+		isStarted.set(false);
+		isRunning.set(false);
+		statMessage = null;
+	}
+
+	/**
+	 * Called from SwingTimerDemo to find out if the task has completed.
+	 */
+	public boolean isDone() {
+		return isDone.get();
+	}
+
+	/**
+	 * Returns the most recent status message, or null if there is no current
+	 * status message.
+	 */
+	public String getMessage() {
+		return statMessage;
+	}
+
+}

+ 98 - 8
src/main/java/com/its/vds/VdsCommServerApplication.java

@@ -1,6 +1,8 @@
 package com.its.vds;
 
 import com.its.app.AppUtils;
+import com.its.vds.UI.JTextAreaOutputStream;
+import com.its.vds.UI.MainUI;
 import com.its.vds.config.ProcessConfig;
 import com.its.vds.process.DbmsJobProcess;
 import com.its.vds.service.UnitSystService;
@@ -12,23 +14,31 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.catalina.connector.Connector;
 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.WebApplicationType;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.builder.SpringApplicationBuilder;
-import org.springframework.boot.context.ApplicationPidFileWriter;
+import org.springframework.context.ApplicationContext;
 import org.springframework.context.ApplicationListener;
 import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.event.ContextClosedEvent;
 import org.springframework.scheduling.annotation.EnableAsync;
 
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.io.PrintStream;
+
 @Slf4j
 @EnableAsync
 @Configuration
 @SpringBootApplication
 @ComponentScan(basePackages = {"com.its.vds.config", "com.its.vds.dao.mapper", "com.its"})
 public class VdsCommServerApplication implements CommandLineRunner, ApplicationListener<ContextClosedEvent>, InitializingBean, DisposableBean {
+//public class VdsCommServerApplication implements ApplicationListener<ContextClosedEvent>, InitializingBean, DisposableBean {
 
     private Connector connector;
 
@@ -39,18 +49,62 @@ public class VdsCommServerApplication implements CommandLineRunner, ApplicationL
         /*String userDir = System.getProperty("user.dir");
         String logbackConfigFileName = userDir + "/conf/app-comm-server-log.xml";
         System.setProperty(ContextInitializer.CONFIG_FILE_PROPERTY, logbackConfigFileName);*/
-        SpringApplication application = new SpringApplicationBuilder()
-                .sources(VdsCommServerApplication.class)
-                .listeners(new ApplicationPidFileWriter("./conf/vds-comm-server.pid"))
-                .build();
-        application.run(args);
-        //SpringApplication.run(CommunicationServerApplication.class, args);
+
+//        new SpringApplicationBuilder(VdsCommServerApplication.class)
+//                .headless(false)
+//                .web(WebApplicationType.NONE)
+//                .run(args);
+        ApplicationContext context = new SpringApplicationBuilder(VdsCommServerApplication.class)
+                .web(WebApplicationType.NONE)
+                .headless(false)
+                .bannerMode(Banner.Mode.OFF)
+                .run(args);
+
+//        SpringApplication application = new SpringApplicationBuilder()
+//                .sources(VdsCommServerApplication.class)
+//                .listeners(new ApplicationPidFileWriter("./conf/vds-comm-server.pid"))
+//                //.headless(false)
+//                //.web(WebApplicationType.NONE)
+//                .build();
+//        application.run(args);
     }
 
     @Override
     public void run(String... args) throws Exception {
+        SwingUtilities.invokeLater(() -> {
+            String pathOfImage = "C:\\DEV\\ITS\\01.WINDOWS\\22.01.YONGIN\\JAVA\\vds-comm-server\\src\\main\\resources\\static\\image\\application.png";
+            JFrame frame = new JFrame("VDS 통신 서버");
+            MainUI UI = new MainUI();
+            frame.setIconImage(Toolkit.getDefaultToolkit().getImage(pathOfImage));
+            frame.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
+            frame.setContentPane(UI.getRootPanel());
+            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+            frame.addWindowListener(new WindowAdapter() {
+                @Override
+                public void windowClosing(WindowEvent e) {
+                    if (JOptionPane.showConfirmDialog(UI.getRootPanel(), "시스템을 종료 하시겠습니까?", "시스템 종료", 0) == 0){
+                        System.exit(0);
+                    } else {
+                        frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
+                    }
+                }
+            });
+            frame.pack();
+            frame.setBounds(100, 100, 860, 740);
+            frame.setLocationRelativeTo(null);
+            frame.setVisible(true);
+
+            JTextArea logArea = UI.getTaLog();
+            logArea.setText(null);
+            JTextAreaOutputStream out = new JTextAreaOutputStream (logArea);
+            System.setOut (new PrintStream(out));
+
+        });
+
         ProcessConfig processConfig = (ProcessConfig) AppUtils.getBean(ProcessConfig.class);
 
+        //CreateUI();
+
         log.info("");
         log.info("");
         log.info("************************************************************************************");
@@ -77,6 +131,10 @@ public class VdsCommServerApplication implements CommandLineRunner, ApplicationL
         VdsCtlrService ctlrService = (VdsCtlrService)AppUtils.getBean(VdsCtlrService.class);
         ctlrService.loadDb();
         ctlrService.updateCtlrStts(true);
+        MainUI mainUI = MainUI.getInstance();
+        if (mainUI != null) {
+            mainUI.LoadControllerInfo(ctlrService);
+        }
 
         VdsTcpClientCommService vdsCommClientService = (VdsTcpClientCommService)AppUtils.getBean(VdsTcpClientCommService.class);
         vdsCommClientService.run();
@@ -99,6 +157,38 @@ public class VdsCommServerApplication implements CommandLineRunner, ApplicationL
         log.error("val1: {}, val2: {}, nval1: {}, nval2: {}, sval1: {}, sval2: {}", val1, val2, nval1, nval2, sval1, sval2);*/
     }
 
+    private void CreateUI() {
+        String pathOfImage = "C:\\DEV\\ITS\\01.WINDOWS\\22.01.YONGIN\\JAVA\\WindowConsole\\src\\application.png";
+//        MainUI UI = new MainUI();//.getInstance();
+//        //JFrame.setDefaultLookAndFeelDecorated(true);
+//        JFrame frame = new JFrame("VDS 통신 서버");
+//        frame.setIconImage(Toolkit.getDefaultToolkit().getImage(pathOfImage));
+//        frame.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
+//        frame.setContentPane(UI.getRootPanel());
+//        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    //EXIT_ON_CLOSE, DISPOSE_ON_CLOSE
+//        frame.addWindowListener(new WindowAdapter() {
+//            @Override
+//            public void windowClosing(WindowEvent e) {
+//                if (JOptionPane.showConfirmDialog(UI.getRootPanel(), "시스템을 종료 하시겠습니까?", "시스템 종료", 0) == 0){
+//                    System.exit(0);
+//                } else {
+//                    frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
+//                }
+//            }
+//        });
+//
+//        frame.pack();
+//        frame.setBounds(100, 100, 860, 740);
+//        frame.setLocationRelativeTo(null);
+//        //frame.setResizable(false);
+//        frame.setVisible(true);
+//        //UI.initList();
+//
+//        JTextArea logArea = UI.getTaLog();
+//        JTextAreaOutputStream out = new JTextAreaOutputStream (logArea);
+//        System.setOut (new PrintStream(out));
+    }
+
     /*@PostConstruct
     private void init() {
         System.err.println("PostConstruct annotation으로 빈이 완전히 생성된 후에 한 번 수행될 메서드에 붙입니다.");

+ 1 - 1
src/main/java/com/its/vds/dao/mapper/BatchDaoService.java

@@ -47,7 +47,7 @@ public abstract class BatchDaoService {
         String mapperName = this.mapperName + this.mapper;
         Elapsed elapsed = new Elapsed();
         int total = 0;
-                SqlSession sqlSession = null;
+        SqlSession sqlSession = null;
         try {
             sqlSession = this.sqlSessionFactory.openSession(ExecutorType.SIMPLE, false);
             total = sqlSession.update(mapperName);

+ 4 - 0
src/main/java/com/its/vds/dao/mapper/batch/VdsCtlrDao.java

@@ -55,6 +55,8 @@ public class VdsCtlrDao extends BatchDaoService {
             total += updateBatch(this.mapper, getSttsList(req));
 
             sqlSession.commit();
+        } catch(Exception e) {
+            log.error("updateStts: Exception, {}, {}", req, e.getMessage());
         }
         finally {
             if (sqlSession != null) {
@@ -77,6 +79,8 @@ public class VdsCtlrDao extends BatchDaoService {
             total += insertBatch(this.mapper, getSttsList(req));
 
             sqlSession.commit();
+        } catch(Exception e) {
+            log.error("insertStts: Exception, {}, {}", req, e.getMessage());
         }
         finally {
             if (sqlSession != null) {

+ 4 - 0
src/main/java/com/its/vds/dao/mapper/batch/VdsDtctDao.java

@@ -55,6 +55,8 @@ public class VdsDtctDao extends BatchDaoService {
             total += updateBatch(this.mapper, getClctList(req));
 
             sqlSession.commit();
+        } catch(Exception e) {
+            log.error("updateClct: Exception, {}, {}", req, e.getMessage());
         }
         finally {
             if (sqlSession != null) {
@@ -77,6 +79,8 @@ public class VdsDtctDao extends BatchDaoService {
             total += insertBatch(this.mapper, getClctList(req));
 
             sqlSession.commit();
+        } catch(Exception e) {
+            log.error("insertClct: Exception, {}, {}", req, e.getMessage());
         }
         finally {
             if (sqlSession != null) {

+ 7 - 2
src/main/java/com/its/vds/webapp/controller/WebAppController.java

@@ -8,6 +8,7 @@ import com.its.vds.webapp.service.FileService;
 import com.its.vds.xnettcp.vds.handler.VdsTcpClientIdleHandler;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.StringUtils;
 import org.springframework.core.io.ResourceLoader;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
@@ -38,7 +39,9 @@ public class WebAppController {
         SortedMap<Integer, TbVdsCtlr> ctlrMap = new TreeMap<>();
         for (Map.Entry<String, TbVdsCtlr> e : AppRepository.getInstance().getCtlrMap().entrySet()) {
             TbVdsCtlr obj = e.getValue();
-            ctlrMap.put(Integer.valueOf(obj.getVDS_CTLR_NMBR()), obj);
+            if (StringUtils.equals("N", obj.getDEL_YN()) && StringUtils.equals("Y", obj.getVALD_YN())) {
+                ctlrMap.put(Integer.valueOf(obj.getVDS_CTLR_NMBR()), obj);
+            }
         }
         model.addAttribute("ServerConfig", this.processConfig);
         //model.addAttribute("list", AppRepository.getInstance().getCtlrMap().entrySet());
@@ -54,7 +57,9 @@ public class WebAppController {
         ConcurrentHashMap<Integer, TbVdsCtlr> ctlrMap = new ConcurrentHashMap<>();
         for (Map.Entry<String, TbVdsCtlr> e : AppRepository.getInstance().getCtlrMap().entrySet()) {
             TbVdsCtlr obj = e.getValue();
-            ctlrMap.put(Integer.valueOf(obj.getVDS_CTLR_NMBR()), obj);
+            if (StringUtils.equals("N", obj.getDEL_YN()) && StringUtils.equals("Y", obj.getVALD_YN())) {
+                ctlrMap.put(Integer.valueOf(obj.getVDS_CTLR_NMBR()), obj);
+            }
         }
         return ctlrMap;
 /*

+ 17 - 2
src/main/java/com/its/vds/xnettcp/vds/process/Job_Data.java

@@ -90,16 +90,31 @@ public class Job_Data implements JobProtocol {
 
 			String DETECT_LANE = Integer.toString(ii+1);
 
-			log.info("[{}]. Job_Data: Lane:{}, TFVL:{}, SPD:{}, OCC:{}, LEN:{}, HDR:{}, SOCC:{}, SSPD:{}",
+			log.info("[{}]. Job_Data: Lane:{}, TFVL:{}, SPED:{}, OCPY:{}, LNGT:{}, HDWY:{}, SPCE_OCPY:{}, SPCE_SPED:{}",
 					obj.getVDS_CTLR_ID(), DETECT_LANE, tfvl, spd, occ, lngt, hdwy, spc_occ, spc_spd);
 
 			TbVdsDtct dtct = obj.getVdsDtctMap().get(DETECT_LANE);
 			if (dtct == null) {
-				log.info("[{}]. Job_Data: Unknown Lane No {}.", obj.getVDS_CTLR_ID(), DETECT_LANE);
+				log.error("[{}]. Job_Data: Unknown Lane No {}.", obj.getVDS_CTLR_ID(), DETECT_LANE);
 			} else {
+				if (tfvl > dtct.getMAX_TFVL() || tfvl < dtct.getMIN_TFVL()) {
+					log.error("[{}]. Job_Data: TFVL Error Lane No {}. {}/{}/{}", obj.getVDS_CTLR_ID(), DETECT_LANE, tfvl, dtct.getMAX_TFVL(), dtct.getMIN_TFVL());
+					continue;
+				}
 				dtct.getClct().setTFVL(tfvl);
+
+				if (spd > dtct.getMAX_SPED() || spd < dtct.getMIN_SPED()) {
+					log.error("[{}]. Job_Data: SPED Error Lane No {}. {}/{}/{}", obj.getVDS_CTLR_ID(), DETECT_LANE, spd, dtct.getMAX_SPED(), dtct.getMIN_SPED());
+					continue;
+				}
 				dtct.getClct().setSPED(spd);
+
+				if (occ > dtct.getMAX_OCPY_RATE() || spd < dtct.getMIN_OCPY_RATE()) {
+					log.error("[{}]. Job_Data: OCPY Error Lane No {}. {}/{}/{}", obj.getVDS_CTLR_ID(), DETECT_LANE, occ, dtct.getMAX_OCPY_RATE(), dtct.getMIN_OCPY_RATE());
+					continue;
+				}
 				dtct.getClct().setAVRG_OCPY_RATE(occ);
+
 				dtct.getClct().setHDWY(hdwy);
 				dtct.getClct().setAVRG_LNGT(lngt);
 				dtct.getClct().setSPCE_OCPY_RATE(spc_occ);

+ 2 - 1
src/main/resources/logback-spring.xml

@@ -30,7 +30,8 @@
     <property name="LOG_PATTERN_SQL"         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_STATISTICS"  value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %msg%n"/>
-    <property name="LOG_PATTERN_CONSOLE"     value="[%d{HH:mm:ss.SSS}] %highlight([%5level]) %highlight(${PID:-}): %cyan(%msg) %n"/>
+<!--    <property name="LOG_PATTERN_CONSOLE"     value="[%d{HH:mm:ss.SSS}] %highlight([%5level]) %highlight(${PID:-}): %cyan(%msg) %n"/>-->
+    <property name="LOG_PATTERN_CONSOLE"     value="[%d{HH:mm:ss.SSS}] [%5level] ${PID:-}: %msg%n"/>
 
     <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
         <withJansi>true</withJansi>

+ 1 - 0
src/main/resources/mybatis/mapper/VdsCtlrMapper.xml

@@ -24,6 +24,7 @@
 		       A.DEL_YN
 		  FROM TB_VDS_CTLR A  
 		 WHERE A.DEL_YN = 'N'
+		   AND A.VALD_YN = 'Y'
 		 ORDER BY A.CTLR_MNGM_NMBR
     ]]>
     </select>

BIN
src/main/resources/static/image/application.png


BIN
src/main/resources/static/image/connect.png


BIN
src/main/resources/static/image/controller.png


BIN
src/main/resources/static/image/logging.png


BIN
src/main/resources/static/image/off.png


BIN
src/main/resources/static/image/on.png