shjung před 2 roky
rodič
revize
f49990052a
30 změnil soubory, kde provedl 505 přidání a 96 odebrání
  1. 1 0
      conf/vms-comm-server.pid
  2. 2 0
      src/main/java/com/its/vms/VmsCommServerApplication.java
  3. 8 0
      src/main/java/com/its/vms/dao/mapper/VmsSymbMapper.java
  4. 1 3
      src/main/java/com/its/vms/domain/VmsForm.java
  5. 7 6
      src/main/java/com/its/vms/domain/VmsFormManager.java
  6. 29 2
      src/main/java/com/its/vms/dto/TbVmsCtlrDto.java
  7. 3 0
      src/main/java/com/its/vms/dto/TbVmsScheduleDto.java
  8. 17 13
      src/main/java/com/its/vms/dto/TbVmsSymbLibDto.java
  9. 28 0
      src/main/java/com/its/vms/dto/VmsScheduleSymbDto.java
  10. 2 0
      src/main/java/com/its/vms/entity/TbVmsSchedule.java
  11. 2 4
      src/main/java/com/its/vms/entity/TbVmsSymbLibDnld.java
  12. 26 0
      src/main/java/com/its/vms/entity/VmsScheduleSymb.java
  13. 10 4
      src/main/java/com/its/vms/process/DbmsDataProcess.java
  14. 2 0
      src/main/java/com/its/vms/process/DbmsDataType.java
  15. 8 11
      src/main/java/com/its/vms/scheduler/SchedulerTask.java
  16. 1 1
      src/main/java/com/its/vms/service/AppRepositoryService.java
  17. 5 5
      src/main/java/com/its/vms/service/UnitSystService.java
  18. 1 1
      src/main/java/com/its/vms/service/VmsAtmpService.java
  19. 7 7
      src/main/java/com/its/vms/service/VmsCtlrService.java
  20. 2 2
      src/main/java/com/its/vms/service/VmsFontService.java
  21. 15 5
      src/main/java/com/its/vms/service/VmsFormService.java
  22. 2 2
      src/main/java/com/its/vms/service/VmsIfscService.java
  23. 21 12
      src/main/java/com/its/vms/service/VmsManageService.java
  24. 1 1
      src/main/java/com/its/vms/service/VmsParkService.java
  25. 178 11
      src/main/java/com/its/vms/service/VmsSymbService.java
  26. 5 0
      src/main/java/com/its/vms/xnettcp/vms/process/TcpServerSendDataProcess.java
  27. 49 2
      src/main/java/com/its/vms/xnettcp/vms/process/response/impl/VmsResDataDownload.java
  28. 7 3
      src/main/java/com/its/vms/xnettcp/vms/process/response/impl/VmsResParameter.java
  29. 49 1
      src/main/resources/mybatis/mapper/VmsSymbMapper.xml
  30. 16 0
      src/test/java/com/its/app/VmsCommServerApplicationTests.java

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

@@ -0,0 +1 @@
+139560

+ 2 - 0
src/main/java/com/its/vms/VmsCommServerApplication.java

@@ -169,6 +169,8 @@ public class VmsCommServerApplication implements CommandLineRunner, ApplicationL
 
         VmsSymbService vmsSymbService = (VmsSymbService)AppUtils.getBean(VmsSymbService.class);
         vmsSymbService.loadDb();
+        vmsSymbService.loadVmsSymbLibDnld();
+        vmsSymbService.loadVmsScheSymbLib();
 
         VmsAtmpService vmsAtmpService = (VmsAtmpService)AppUtils.getBean(VmsAtmpService.class);
         vmsAtmpService.loadDb();

+ 8 - 0
src/main/java/com/its/vms/dao/mapper/VmsSymbMapper.java

@@ -2,7 +2,10 @@ package com.its.vms.dao.mapper;
 
 import com.its.vms.entity.TbVmsSymbIfsc;
 import com.its.vms.entity.TbVmsSymbLib;
+import com.its.vms.entity.TbVmsSymbLibDnld;
+import com.its.vms.entity.VmsScheduleSymb;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
 
@@ -11,4 +14,9 @@ public interface VmsSymbMapper {
 
     List<TbVmsSymbLib> selectVmsSymbLib();
     List<TbVmsSymbIfsc> selectVmsSymbCellInfo();
+
+    List<TbVmsSymbLibDnld> selectVmsSymbLibDnld();
+    int updateVmsSymbLibDnld(@Param("obj") TbVmsSymbLibDnld obj);
+    List<VmsScheduleSymb> selectVmsScheSymbLib();
+
 }

+ 1 - 3
src/main/java/com/its/vms/domain/VmsForm.java

@@ -72,6 +72,7 @@ public class VmsForm implements Serializable {
     private byte[] imageData;
     private String vmsDsplMsgData;
     private String vmsDsplMsgTxt;
+    private int dnldFormNo;
 
     public VmsForm(Integer vmsFormId) {
         this.vmsFormId = vmsFormId;
@@ -102,9 +103,6 @@ public class VmsForm implements Serializable {
         this.width = width;
         this.height = height;
         this.formImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
-//        this.g2d = formImage.createGraphics();
-//        this.g2d.setColor(Color.BLACK);
-//        this.g2d.fillRect(0, 0, this.width, this.height);
     }
     public void initDownload(TbVmsCtlrDto vmsObj, TbVmsFormDto vmsForm, TbVmsScheduleDto schedule) {
         setSuccess(false);

+ 7 - 6
src/main/java/com/its/vms/domain/VmsFormManager.java

@@ -43,13 +43,13 @@ public class VmsFormManager implements Serializable {
         return null;
     }
 
-    public int addForm(VmsForm form) {
-        this.objects.add(form);
-        this.objectCount = this.objects.size();
-        return this.objectCount;
-    }
+//    public int addForm(VmsForm form) {
+//        this.objects.add(form);
+//        this.objectCount = this.objects.size();
+//        return this.objectCount;
+//    }
 
-    public VmsForm addForm(Integer vmsFormId) {
+    public VmsForm addForm(Integer vmsFormId, int dnldFormNo) {
         VmsForm form = null;
         if (this.objectCount < this.totalCount) {
             form = getItem(this.objectCount);
@@ -61,6 +61,7 @@ public class VmsFormManager implements Serializable {
             this.totalCount++;
         }
         this.objectCount++;
+        form.setDnldFormNo(dnldFormNo);
         return form;
     }
 

+ 29 - 2
src/main/java/com/its/vms/dto/TbVmsCtlrDto.java

@@ -134,6 +134,9 @@ public class TbVmsCtlrDto implements Serializable {
     private VmsDownloadFile downloadFile;           // 제어기로 다운로드할 파일정보(TB_VMS_DOWNLOAD)
     private VmsDownloadData downloadData;
     private ConcurrentHashMap<Integer, VmsDownloadForm> downloadFormMap = null;
+    private ConcurrentHashMap<Integer, TbVmsSymbLibDnldDto> dnldSymbMap = null;
+    private ConcurrentHashMap<Integer, VmsScheduleSymbDto> reqDnldSymbMap;
+    Integer dnldSymbLibNmbr;
 
     private ConcurrentHashMap<Long, TbVmsRltnIfscDto> rltnIfscMap = null;
 
@@ -153,6 +156,9 @@ public class TbVmsCtlrDto implements Serializable {
 
         this.downloadData = new VmsDownloadData();
         this.downloadFormMap = new ConcurrentHashMap<>();
+        this.dnldSymbMap = new ConcurrentHashMap<>();
+        this.reqDnldSymbMap = new ConcurrentHashMap<>();
+        this.dnldSymbLibNmbr = 0;
 
         this.registeredCommandsTimer = new ConcurrentHashMap<>();
         this.userCommands = new ConcurrentHashMap<>();
@@ -517,7 +523,6 @@ public class TbVmsCtlrDto implements Serializable {
             units[forms].setBkClr(pForm.getVmsFormColrCd());
 
             VmsDownloadForm downloadForm = this.downloadFormMap.get(vmsFormId);
-            //units[forms].setBitmapId((vmsFormId % 1000) + 1000);
             // 홍보폼이면서 신규폼이 아니면서 이전 다운로드 목록이 존재하는 경우에 다운로드 여부를 체크한다.
             if (vmsForm.getVmsFormTypeCd() == eVmsFormType.eFormTp_hongbo.getValue() && !vmsForm.isNewForm() && downloadForm != null) {
                 if (downloadForm.isAlreadyDownload()) {
@@ -570,7 +575,6 @@ public class TbVmsCtlrDto implements Serializable {
             //e_vms_blank                  = 0x9E,//    Blank                                   송신    schedule 표출                               센터 → VMS
             downloadAutoFixForm();
         }
-
         return true;
     }
 
@@ -813,4 +817,27 @@ public class TbVmsCtlrDto implements Serializable {
         return sendData(reqBlank.getByteBuffer(), 10, reqBlank.getOpCodeDesc());
     }
 
+    public boolean downloadSymbLib() {
+        this.dnldSymbLibNmbr = 0;
+        if (this.reqDnldSymbMap.size() == 0) {
+            return false;
+        }
+
+        VmsScheduleSymbDto dnldSymb = null;
+        for (Map.Entry<Integer, VmsScheduleSymbDto> e : this.reqDnldSymbMap.entrySet()) {
+            dnldSymb = e.getValue();
+            break;
+        }
+
+        if (dnldSymb != null) {
+            this.dnldSymbLibNmbr = dnldSymb.getDnldSymbLibNmbr();
+            String fileName = String.format("BID%04d.BMP", this.dnldSymbLibNmbr);
+            eVmsFileSaveLocation saveLoc = eVmsFileSaveLocation.LOC_DOWNLOAD_PROG_IMAGE;
+
+            VmsReqDataDownload dataDownload = new VmsReqDataDownload(this, saveLoc, fileName, dnldSymb.getImageData());
+            sendData(dataDownload.getByteBuffer(), 10, dataDownload.getOpCodeDesc());
+            return true;
+        }
+        return false;
+    }
 }

+ 3 - 0
src/main/java/com/its/vms/dto/TbVmsScheduleDto.java

@@ -40,6 +40,8 @@ public class TbVmsScheduleDto implements Serializable {
     private Integer vmsFormTypeCd;
     private Integer vmsFormSubTypeCd;
 
+    private int dnldFormId;
+
     private Long vmsIfscId;         // 돌발 및 이벤트 발생 IFSC_ID
     private TbVmsIncdDto event ;    // 돌발 및 이벤트 발생 정보
 
@@ -78,6 +80,7 @@ public class TbVmsScheduleDto implements Serializable {
                 .dsplCngsYn(this.dsplCngsYn)
                 .vmsFormTypeCd(this.vmsFormTypeCd)
                 .vmsFormSubTypeCd(this.vmsFormSubTypeCd)
+                .dnldFormId(this.dnldFormId)
                 .vmsIfscId(this.vmsIfscId)
                 .event(this.event)
                 .build();

+ 17 - 13
src/main/java/com/its/vms/dto/TbVmsSymbLibDto.java

@@ -1,6 +1,7 @@
 package com.its.vms.dto;
 
 import com.its.vms.entity.TbVmsSymbLib;
+import com.its.vms.service.VmsSymbService;
 import com.its.vms.xnettcp.vms.protocol.enums.eVmsImageType;
 import lombok.Builder;
 import lombok.Data;
@@ -26,6 +27,7 @@ public class TbVmsSymbLibDto implements Serializable {
 
     private String symbLibNmbr;
     private Integer orgSymbLibNmbr;
+    private Integer dnldSymbLibNmbr;
     private String rgstDt;
     private byte[] redData;
     private byte[] greenData;
@@ -75,36 +77,38 @@ public class TbVmsSymbLibDto implements Serializable {
     }
 
     public void setSymbInfo() {
-        setImagType(eVmsImageType.VMS_IMAGE_TYPE_BMP);
+
+        this.dnldSymbLibNmbr = VmsSymbService.getDnldSymbNmbr(this.symbLibNmbr);
+        this.imagType = eVmsImageType.VMS_IMAGE_TYPE_BMP;
 
         String symbFileName = "";
         if ("SBT3".equals(getSymbType())) {
-            symbFileName = getSymbFileNm();
-            setImagType(eVmsImageType.VMS_IMAGE_TYPE_VIDEO);
+            symbFileName = this.symbFileNm;
+            this.imagType = eVmsImageType.VMS_IMAGE_TYPE_VIDEO;
         }
         else {
             switch(getImagType()) {
-                case VMS_IMAGE_TYPE_BMP: symbFileName = getSymbLibNmbr()+".bmp"; break;
-                case VMS_IMAGE_TYPE_GIF: symbFileName = getSymbLibNmbr()+".gif"; break;
-                case VMS_IMAGE_TYPE_JPG: symbFileName = getSymbLibNmbr()+".jpg"; break;
-                case VMS_IMAGE_TYPE_PNG: symbFileName = getSymbLibNmbr()+".png"; break;
+                case VMS_IMAGE_TYPE_BMP: symbFileName = this.dnldSymbLibNmbr+".bmp"; break;
+                case VMS_IMAGE_TYPE_GIF: symbFileName = this.dnldSymbLibNmbr+".gif"; break;
+                case VMS_IMAGE_TYPE_JPG: symbFileName = this.dnldSymbLibNmbr+".jpg"; break;
+                case VMS_IMAGE_TYPE_PNG: symbFileName = this.dnldSymbLibNmbr+".png"; break;
                 default:
-                    if (getSymbFileNm() == null || getSymbFileNm().trim().length() == 0) {
-                        symbFileName = getSymbLibNmbr()+".avi";
+                    if (this.symbFileNm == null || this.symbFileNm.trim().length() == 0) {
+                        symbFileName = this.dnldSymbLibNmbr+".avi";
                     }
                     else {
-                        symbFileName = getSymbFileNm().trim();
+                        symbFileName = this.symbFileNm.trim();
                     }
                     break;
             }
         }
-        setSymbFileNm(symbFileName);
-        setLocalFileName(symbFileName);
+        this.symbFileNm = symbFileName;
+        this.localFileName = symbFileName;
     }
 
     public Image getImage() {
         if (this.imageData == null || this.imageData.length == 0) {
-            log.error("TbVmsSymbLibDto.getImage: Image Data null: {}", this.orgSymbLibNmbr);
+            log.error("TbVmsSymbLibDto.getImage: Image Data null: {}, {}", this.orgSymbLibNmbr, this.symbLibNmbr);
             return null;
         }
 

+ 28 - 0
src/main/java/com/its/vms/dto/VmsScheduleSymbDto.java

@@ -0,0 +1,28 @@
+package com.its.vms.dto;
+
+import io.swagger.annotations.ApiModel;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * VMS 스케쥴에 등록된 심볼 정보 Entity Class
+ */
+@ApiModel("VMS 심볼 제어기 다운로드 정보")
+@Getter
+@Builder
+@NoArgsConstructor//(access = AccessLevel.PROTECTED)
+@AllArgsConstructor
+public class VmsScheduleSymbDto implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private Long vmsCtlrNmbr;
+    private Integer dnldSymbLibNmbr;
+    private Integer symbLibNmbr;
+    private String updtDt;
+    private byte[] imageData;
+
+}

+ 2 - 0
src/main/java/com/its/vms/entity/TbVmsSchedule.java

@@ -1,6 +1,7 @@
 package com.its.vms.entity;
 
 import com.its.vms.dto.TbVmsScheduleDto;
+import com.its.vms.service.VmsFormService;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Data;
@@ -65,6 +66,7 @@ public class TbVmsSchedule implements Serializable {
                 .dsplCngsYn("Y".equals(this.dsplCngsYn))
                 .vmsFormTypeCd(this.vmsFormTypeCd)
                 .vmsFormSubTypeCd(this.vmsFormSubTypeCd)
+                .dnldFormId(VmsFormService.getDnldFormNo(this.vmsFormId))
                 .vmsIfscId(0L)
                 .event(null)
                 .build();

+ 2 - 4
src/main/java/com/its/vms/entity/TbVmsSymbLibDnld.java

@@ -2,10 +2,7 @@ package com.its.vms.entity;
 
 import com.its.vms.dto.TbVmsSymbLibDnldDto;
 import io.swagger.annotations.ApiModel;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
+import lombok.*;
 
 import java.io.Serializable;
 
@@ -15,6 +12,7 @@ import java.io.Serializable;
 @ApiModel("VMS 심볼 제어기 다운로드 정보")
 @Getter
 @Builder
+@ToString
 @NoArgsConstructor//(access = AccessLevel.PROTECTED)
 @AllArgsConstructor
 public class TbVmsSymbLibDnld implements Serializable {

+ 26 - 0
src/main/java/com/its/vms/entity/VmsScheduleSymb.java

@@ -0,0 +1,26 @@
+package com.its.vms.entity;
+
+import io.swagger.annotations.ApiModel;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * VMS 스케쥴에 등록된 심볼 정보 Entity Class
+ */
+@ApiModel("VMS 심볼 제어기 다운로드 정보")
+@Getter
+@Builder
+@NoArgsConstructor//(access = AccessLevel.PROTECTED)
+@AllArgsConstructor
+public class VmsScheduleSymb implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private Long vmsCtlrNmbr;
+    private Integer symbLibNmbr;
+    private String updtDt;
+
+}

+ 10 - 4
src/main/java/com/its/vms/process/DbmsDataProcess.java

@@ -4,15 +4,13 @@ import com.its.app.AppUtils;
 import com.its.vms.config.ThreadPoolInitializer;
 import com.its.vms.dao.mapper.UnitSystMapper;
 import com.its.vms.dao.mapper.VmsCtlrMapper;
+import com.its.vms.dao.mapper.VmsSymbMapper;
 import com.its.vms.dao.mapper.batch.VmsCtlrDao;
 import com.its.vms.dao.mapper.batch.VmsManageDao;
 import com.its.vms.domain.NET;
 import com.its.vms.domain.VmsForm;
 import com.its.vms.dto.TbVmsCtlrDto;
-import com.its.vms.entity.TbUnitSystStts;
-import com.its.vms.entity.TbVmsCtlrStts;
-import com.its.vms.entity.TbVmsCtrlHs;
-import com.its.vms.entity.TbVmsDsplPrst;
+import com.its.vms.entity.*;
 import com.its.vms.service.AppRepositoryService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -39,6 +37,7 @@ public class DbmsDataProcess {
 
     private final UnitSystMapper unitSystMapper;
     private final VmsCtlrMapper vmsCtlrMapper;
+    private final VmsSymbMapper symbMapper;
     private final AppRepositoryService repoService;
 
     private int maxCore = Runtime.getRuntime().availableProcessors();
@@ -137,6 +136,13 @@ public class DbmsDataProcess {
                         this.vmsManageDao.insertVmsDsplPrst(dsplPrstHsList);
                     }
                     break;
+                case DBMS_DATA_SYMB_DNLD:
+                    TbVmsSymbLibDnld symbLibDnld = (TbVmsSymbLibDnld)data.getData();
+                    if (symbLibDnld != null) {
+                        log.error("XXXXXXXXXXXXXXXXX: {}", symbLibDnld);
+                        this.symbMapper.updateVmsSymbLibDnld(symbLibDnld);
+                    }
+                    break;
                 default:
                     log.error("DbmsJobProcess.process: Unknown Request {}.", type);
                     break;

+ 2 - 0
src/main/java/com/its/vms/process/DbmsDataType.java

@@ -12,4 +12,6 @@ public enum DbmsDataType {
     DBMS_DATA_MULTIMEDIA_HS,
     DBMS_DATA_CTRL_HS,
 
+    DBMS_DATA_SYMB_DNLD,
+
 }

+ 8 - 11
src/main/java/com/its/vms/scheduler/SchedulerTask.java

@@ -2,10 +2,7 @@ package com.its.vms.scheduler;
 
 import com.its.app.utils.Elapsed;
 import com.its.vms.config.ApplicationConfig;
-import com.its.vms.service.AppRepositoryService;
-import com.its.vms.service.UnitSystService;
-import com.its.vms.service.VmsCtlrService;
-import com.its.vms.service.VmsManageService;
+import com.its.vms.service.*;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.scheduling.annotation.EnableScheduling;
@@ -24,6 +21,7 @@ public class SchedulerTask {
     private final UnitSystService unitSystService;
     private final VmsCtlrService vmsCtlrService;
     private final VmsManageService vmsManageService;
+    private final VmsSymbService symbService;
     private final AppRepositoryService repoService;
 
     @PreDestroy
@@ -68,16 +66,15 @@ public class SchedulerTask {
         log.info("scheduleVmsFormDownload..: ..end. {} ms. {}", elapsed.milliSeconds(), Thread.currentThread().getName());
     }
 
-    @Scheduled(cron = "50 4,9,14,19,24,29,34,39,44,49,54,59 * * * *")  // 5분주기 작업 실행
-    public void scheduleMakeSectTraf() {
+    @Scheduled(cron = "10 3,8,13,18,23,28,33,38,43,48,53,58 * * * *")  // 5분주기 작업 실행
+    public void scheduleVmsDnldSymb() {
         if (!this.config.isStartSchedule()) {
             return;
         }
-        //Elapsed elapsed = new Elapsed();
-        //log.info("makeSectTraf: start. {}", Thread.currentThread().getName());
-        //this.rseSectService.makeDsrcSectTraffic();
-        //log.info("makeSectTraf: ..end. {} ms. {}", elapsed.milliSeconds(), Thread.currentThread().getName());
+        Elapsed elapsed = new Elapsed();
+        log.info("scheduleVmsDnldSymb: start. {}", Thread.currentThread().getName());
+        this.symbService.loadVmsScheSymbLib();
+        log.info("scheduleVmsDnldSymb: ..end. {} ms. {}", elapsed.milliSeconds(), Thread.currentThread().getName());
     }
 
-
 }

+ 1 - 1
src/main/java/com/its/vms/service/AppRepositoryService.java

@@ -38,7 +38,7 @@ public class AppRepositoryService {
             }
         }
         catch (Exception e) {
-            log.error("AppRepositoryService.initCtlrInfo: Exception: {}", e.toString());
+            log.error("AppRepositoryService.initCtlrInfo: Exception: {}.", e.toString());
         }
     }
     public Set<Map.Entry<Long, TbVmsCtlrDto>> getEntrySetCtrl() {

+ 5 - 5
src/main/java/com/its/vms/service/UnitSystService.java

@@ -58,8 +58,8 @@ public class UnitSystService {
             log.error("UnitSystService.init: UnknownHostException");
         }
 
-        log.info("UnitSystService.init. _srcIpAddr: {}", UnitSystService._srcIpAddr);
-        log.info("UnitSystService.init. processId: {}", this.processId);
+        log.info("UnitSystService.init. _srcIpAddr: {}.", UnitSystService._srcIpAddr);
+        log.info("UnitSystService.init. processId: {}.", this.processId);
         log.info("UnitSystService.init: ..end.");
     }
 
@@ -89,8 +89,8 @@ public class UnitSystService {
                     this.unitSystStts.setSYST_ID(this.processId);
                     String localIp = unit.getSystIp1().trim();
                     long ipAddr = SysUtils.ipToLong(localIp);
-                    UnitSystService._srcIpAddr = String.format("%03d.%03d.%03d.%03d-", (ipAddr>>24)&0xFF, (ipAddr>>16)&0xFF, (ipAddr>>8)&0xFF, (ipAddr>>0)&0xFF);
-                    log.info("UnitSystService.loadMaster: _srcIpAddr: {}", UnitSystService._srcIpAddr);
+                    UnitSystService._srcIpAddr = String.format("%03d.%03d.%03d.%03d-", (ipAddr>>24)&0xFF, (ipAddr>>16)&0xFF, (ipAddr>>8)&0xFF, ipAddr&0xFF);
+                    log.info("UnitSystService.loadMaster: _srcIpAddr: {}.", UnitSystService._srcIpAddr);
                 }
 
                 if (unit.getSystType().contentEquals("UOT")) {
@@ -100,7 +100,7 @@ public class UnitSystService {
             }
         }
         catch (Exception e) {
-            log.error("UnitSystService.selectAll: Exception: {}", e.toString());
+            log.error("UnitSystService.selectAll: Exception: {}.", e.toString());
         }
     }
 

+ 1 - 1
src/main/java/com/its/vms/service/VmsAtmpService.java

@@ -57,7 +57,7 @@ public class VmsAtmpService {
             });
         }
         catch (Exception e) {
-            log.error("VmsAtmpService.loadVmsAtmpInfo: {}", e.toString());
+            log.error("VmsAtmpService.loadVmsAtmpInfo: {}.", e.toString());
         }
 
         if (nFailed.intValue() > 0 && nSuccess.intValue() > 0) {

+ 7 - 7
src/main/java/com/its/vms/service/VmsCtlrService.java

@@ -52,10 +52,10 @@ public class VmsCtlrService {
             List<TbVmsCtlr> infoList  = this.mapper.selectAll();
             log.info("VmsCtlrService.loadCtlrInfo: {} EA", infoList.size());
             for (TbVmsCtlr dto : infoList) {
-                log.info("VmsCtlrService.loadCtlrInfo: {}", dto);
+                log.info("VmsCtlrService.loadCtlrInfo: {}.", dto);
                 TbVmsCtlrDto vmsObj = dto.toDto();
                 if (vmsObj.getCtlrId().trim().equals("")) {
-                    log.error("VmsCtlrService.loadCtlrInfo: Controller Ip Address Error: {}", vmsObj);
+                    log.error("VmsCtlrService.loadCtlrInfo: Controller Ip Address Error: {}.", vmsObj);
                     continue;
                 }
 
@@ -66,7 +66,7 @@ public class VmsCtlrService {
                 vmsObj.getStts().initUnknown();
 
                 if (vmsObj.getMaxPhaseNum() > this.config.getMaxDownloadForms()) {
-                    log.error("VmsCtlrService.loadCtlrInfo: VMS {} Download Form Size Error: {}/{}", vmsObj.getVmsCtlrNmbr(), vmsObj.getMaxPhaseNum(), this.config.getMaxDownloadForms());
+                    log.error("VmsCtlrService.loadCtlrInfo: VMS {} Download Form Size Error: {}/{}.", vmsObj.getVmsCtlrNmbr(), vmsObj.getMaxPhaseNum(), this.config.getMaxDownloadForms());
                     vmsObj.setMaxPhaseNum(this.config.getMaxDownloadForms());
                 }
                 vmsObj.setLocalFormDir(this.config.getFtpFormDir() + File.separator + vmsObj.getVmsCtlrNmbr() + File.separator);
@@ -77,11 +77,11 @@ public class VmsCtlrService {
             }
         }
         catch (Exception e) {
-            log.error("VmsCtlrService.loadCtlrInfo: {}", e.toString());
+            log.error("VmsCtlrService.loadCtlrInfo: {}.", e.toString());
         }
 
         this.repoService.getCtlrMap().forEach((key, obj) -> {
-            log.info("VmsCtlrService.loadCtlrInfo:: {}", obj.toString());
+            log.info("VmsCtlrService.loadCtlrInfo:: {}.", obj.toString());
         });
         log.info("VmsCtlrService.loadCtlrInfo: {} ms.", elapsed.milliSeconds());
     }
@@ -101,7 +101,7 @@ public class VmsCtlrService {
             });
         }
         catch (Exception e) {
-            log.error("VmsCtlrService.loadCtlrSttsInfo: {}", e.toString());
+            log.error("VmsCtlrService.loadCtlrSttsInfo: {}.", e.toString());
         }
         log.info("VmsCtlrService.loadCtlrSttsInfo: {} ms.", elapsed.milliSeconds());
     }
@@ -157,7 +157,7 @@ public class VmsCtlrService {
             dbmsDataProcess.add(new DbmsData(DbmsDataType.DBMS_DATA_CTLR_STTS_LIST, insHs, ctlrSttsList));
         }
 
-        log.info("VmsCtlrService.updateCtlrStts: total {}, normal {}, error {}", normal + error, normal, error);
+        log.info("VmsCtlrService.updateCtlrStts: total {}, normal {}, error {}.", normal + error, normal, error);
     }
 
 }

+ 2 - 2
src/main/java/com/its/vms/service/VmsFontService.java

@@ -68,7 +68,7 @@ public class VmsFontService {
             }
         }
         catch (Exception e) {
-            log.error("VmsFontService.loadFontNameInfo: {}", e.getMessage());
+            log.error("VmsFontService.loadFontNameInfo: {}.", e.getMessage());
         }
         log.info("VmsFontService.loadFontNameInfo: {} ms.", elapsed.milliSeconds());
     }
@@ -84,7 +84,7 @@ public class VmsFontService {
             }
         }
         catch (Exception e) {
-            log.error("VmsFontService.loadFontColorInfo: {}", e.toString());
+            log.error("VmsFontService.loadFontColorInfo: {}.", e.toString());
         }
         log.info("VmsFontService.loadFontColorInfo: {} ms.", elapsed.milliSeconds());
     }

+ 15 - 5
src/main/java/com/its/vms/service/VmsFormService.java

@@ -98,7 +98,7 @@ public class VmsFormService {
             });
         }
         catch (Exception e) {
-            log.error("VmsFormService.loadVmsFormInfo: {}", e.toString());
+            log.error("VmsFormService.loadVmsFormInfo: {}.", e.toString());
         }
         log.info("VmsFormService.loadVmsFormInfo: {} ms.", elapsed.milliSeconds());
     }
@@ -112,7 +112,7 @@ public class VmsFormService {
                 TbVmsFormObjectDto obj = data.toDto();
                 TbVmsFormDto formObj = this.dataMap.get(obj.getVmsFormId());
                 if (formObj == null) {
-                    log.error("VmsFormService.loadVmsFormObjectInfo: Not Found VMS Form {}", obj.getVmsFormId());
+                    log.error("VmsFormService.loadVmsFormObjectInfo: Not Found VMS Form {}.", obj.getVmsFormId());
                     return;
                 }
 
@@ -172,14 +172,14 @@ public class VmsFormService {
                 {
                     TbVmsSymbLibDto vmsSymbLib = this.vmsSymbService.find(obj.getSymbLibNmbr()+"0");
                     if (vmsSymbLib == null) {
-                        log.error("VmsFormService.loadVmsFormObjectInfo: VMF Form Object Symbol Library not Found {}, {}", obj.getVmsFormId(), obj.getSymbLibNmbr());
+                        log.error("VmsFormService.loadVmsFormObjectInfo: VMF Form Object Symbol Library not Found {}, {}.", obj.getVmsFormId(), obj.getSymbLibNmbr());
                     }
                     obj.setVmsSymbLib(vmsSymbLib);
                 }
             });
         }
         catch (Exception e) {
-            log.error("VmsFormService.loadVmsFormObjectInfo: {}", e.toString());
+            log.error("VmsFormService.loadVmsFormObjectInfo: {}.", e.toString());
         }
         log.info("VmsFormService.loadVmsFormObjectInfo: {} ms.", elapsed.milliSeconds());
     }
@@ -195,9 +195,19 @@ public class VmsFormService {
             });
         }
         catch (Exception e) {
-            log.error("VmsFormService.loadVmsFormInfo: {}", e.toString());
+            log.error("VmsFormService.loadVmsFormInfo: {}.", e.toString());
         }
         log.info("VmsFormService.loadVmsFormColorInfo: {} ms.", elapsed.milliSeconds());
     }
 
+    /**
+     * 내부에서 사용하는 심벌 라이브러리 번호를 제어기로 다운로드하는 BitmapId 로 변환한다.
+     * @param formId : 10013 -> 1130
+     * @return
+     */
+    public static int getDnldFormNo(Integer formId) {
+        int id = formId % 10000;
+        return 1000 + (id * 10);
+    }
+
 }

+ 2 - 2
src/main/java/com/its/vms/service/VmsIfscService.java

@@ -71,7 +71,7 @@ public class VmsIfscService {
             });
         }
         catch (Exception e) {
-            log.error("VmsIfscService.loadVmsRltnIfsc: {}", e.toString());
+            log.error("VmsIfscService.loadVmsRltnIfsc: {}.", e.toString());
         }
         log.info("VmsIfscService.loadVmsRltnIfsc: {} ms.", elapsed.milliSeconds());
     }
@@ -101,7 +101,7 @@ public class VmsIfscService {
             });
         }
         catch (Exception e) {
-            log.error("VmsIfscService.loadVmsIfscTrafInfo: {}", e.toString());
+            log.error("VmsIfscService.loadVmsIfscTrafInfo: {}.", e.toString());
         }
         log.info("VmsIfscService.loadVmsIfscTrafInfo: {} ms.", elapsed.milliSeconds());
     }

+ 21 - 12
src/main/java/com/its/vms/service/VmsManageService.java

@@ -11,10 +11,7 @@ import com.its.vms.domain.VmsFormObject;
 import com.its.vms.domain.VmsSchedule;
 import com.its.vms.domain.enums.*;
 import com.its.vms.dto.*;
-import com.its.vms.entity.TbVmsIncd;
-import com.its.vms.entity.TbVmsOnOffTime;
-import com.its.vms.entity.TbVmsOperMode;
-import com.its.vms.entity.TbVmsSchedule;
+import com.its.vms.entity.*;
 import com.its.vms.process.DbmsData;
 import com.its.vms.process.DbmsDataProcess;
 import com.its.vms.process.DbmsDataType;
@@ -74,7 +71,7 @@ public class VmsManageService {
         result.forEach(obj -> {
             TbVmsCtlrDto vmsObj = this.repoService.getCtrlMap(obj.getVmsCtlrNmbr());
             if (vmsObj == null) {
-                log.error("VmsManageService.loadVmsOnOffTime: VMS Not Found {}", obj.getVmsCtlrNmbr());
+                log.error("VmsManageService.loadVmsOnOffTime: VMS Not Found {}.", obj.getVmsCtlrNmbr());
                 return;
             }
 
@@ -412,6 +409,7 @@ public class VmsManageService {
         else {
             for (int ii = 0; ii < ifscIds.size() && ii < fromMaxCnt; ii++) {
                 TbVmsScheduleDto trafSchedule = schedule.clone();
+                trafSchedule.setVmsFormId(schedule.getDnldFormId()+ii);
                 trafSchedule.initTrafId();
                 trafSchedule.setVmsIfscId(ifscIds.get(ii));
                 trafSchedule.setFrstVmsIfscId(ifscIds.get(ii));
@@ -487,6 +485,7 @@ public class VmsManageService {
                 return;
             }
 
+            final int[] formIdx = new int[1];
             TbVmsScheduleDto schedule = data.toDto();
             switch(vmsSchFormType) {
                 case eSchTp_traffic:    // 교통정보
@@ -494,8 +493,10 @@ public class VmsManageService {
                     break;
                 case eSchTp_incident:   // 돌발
                     // 돌발 스케줄인 경우 해당 VMS 에 발생한 모든 돌발 정보를 표출하도록 스케줄 추가
+                    formIdx[0] = 0;
                     vmsObj.getIncident().getUnits().forEach(incd -> {
                         TbVmsScheduleDto incdSchedule = schedule.clone();
+                        incdSchedule.setDnldFormId(schedule.getDnldFormId() + formIdx[0]++);
                         incdSchedule.setVmsIfscId(incd.getVmsIfscId());
                         incdSchedule.setEvent(incd);
                         vmsObj.getSchedule().add(incdSchedule);
@@ -503,8 +504,10 @@ public class VmsManageService {
                     break;
                 case eSchTp_gongsa:     // 공사/행사문안
                     // 공사/행사 스케줄인 경우 해당 VMS 에 발생한 모든 돌발 정보를 표출하도록 스케줄 추가
+                    formIdx[0] = 0;
                     vmsObj.getEvent().getUnits().forEach(event -> {
                         TbVmsScheduleDto eventSchedule = schedule.clone();
+                        eventSchedule.setDnldFormId(schedule.getDnldFormId() + formIdx[0]++);
                         eventSchedule.setVmsIfscId(event.getVmsIfscId());
                         eventSchedule.setEvent(event);
                         vmsObj.getSchedule().add(eventSchedule);
@@ -516,11 +519,13 @@ public class VmsManageService {
                     break;
                 case eSchTp_deture:     // 우회도로
                     // 돌발발생한 구간중 우회도로 구간이 있는경우
+                    formIdx[0] = 0;
                     vmsObj.getIncident().getUnits().forEach(incd -> {
                         if (incd.getDetrId() == 0L || incd.getVmsIfscId() == 0) {
                             return;
                         }
                         TbVmsScheduleDto detureSchedule1 = schedule.clone();
+                        detureSchedule1.setDnldFormId(schedule.getDnldFormId() + formIdx[0]++);
                         detureSchedule1.setVmsIfscId(incd.getVmsIfscId());
                         detureSchedule1.setEvent(incd);
                         vmsObj.getSchedule().add(detureSchedule1);
@@ -531,12 +536,14 @@ public class VmsManageService {
                             return;
                         }
                         TbVmsScheduleDto detureSchedule2 = schedule.clone();
+                        detureSchedule2.setDnldFormId(schedule.getDnldFormId() + formIdx[0]++);
                         detureSchedule2.setVmsIfscId(event.getVmsIfscId());
                         detureSchedule2.setEvent(event);
                         vmsObj.getSchedule().add(detureSchedule2);
                     });
                     break;
                 case eSchTp_congest:    // 정체상황
+                    formIdx[0] = 0;
                     vmsObj.getRltnIfscMap().forEach((key, cngs) -> {
                         if (!cngs.isUsed() || !cngs.isCngstCnfmYn()) {
                             // 정체판정이 아닌경우
@@ -551,6 +558,7 @@ public class VmsManageService {
                             vmsObj.setExistCngsForm(true);
 
                             TbVmsScheduleDto congestSchedule = schedule.clone();
+                            congestSchedule.setDnldFormId(schedule.getDnldFormId() + formIdx[0]++);
                             congestSchedule.setFrstVmsIfscId(cngs.getVmsIfscId());
                             congestSchedule.setVmsIfscId(cngs.getVmsIfscId());
                             vmsObj.getSchedule().add(congestSchedule);
@@ -827,13 +835,13 @@ public class VmsManageService {
                     if (vmsSchFormType != eVmsScheduleType.eSchTp_evehicle || vmsForm.getVmsFormDsplDrctCd() != 0) {
                         // 긴급차량우선신호 진행중 일때 스케쥴 유형 및 폼유형이 맞지 않으면 리턴
                         // 단일 메시지로 표출하는 경우
-                        log.info("VmsManageService.makeVmsProvideForm: VMS {}, FORM {}, EVehicle Ing {}. {} DsplDrctCd {}",
+                        log.info("VmsManageService.makeVmsProvideForm: VMS {}, FORM {}, EVehicle Ing {}. {} DsplDrctCd {}.",
                                 ctlrNmbr, vmsForm.getVmsFormId(), isEVehIngForm, vmsSchFormType, vmsForm.getVmsFormDsplDrctCd());
                         continue;
                     }
                 } else {
                     if (vmsSchFormType == eVmsScheduleType.eSchTp_evehicle && vmsForm.getVmsFormDsplDrctCd() == 0) {
-                        log.info("VmsManageService.makeVmsProvideForm: VMS {}, FORM {}, EVehicle Ing {}. {} DsplDrctCd {}",
+                        log.info("VmsManageService.makeVmsProvideForm: VMS {}, FORM {}, EVehicle Ing {}. {} DsplDrctCd {}.",
                                 ctlrNmbr, vmsForm.getVmsFormId(), isEVehIngForm, vmsSchFormType, vmsForm.getVmsFormDsplDrctCd());
                         continue;
                     }
@@ -849,7 +857,7 @@ public class VmsManageService {
 //                    }
                 } else {
                     if (vmsSchFormType == eVmsScheduleType.eSchTp_evehicle && vmsForm.getVmsFormDsplDrctCd() == 1) {
-                        log.info("VmsManageService.makeVmsProvideForm: VMS {}, FORM {}, EVehicle End {}. {} DsplDrctCd {}",
+                        log.info("VmsManageService.makeVmsProvideForm: VMS {}, FORM {}, EVehicle End {}. {} DsplDrctCd {}.",
                                 ctlrNmbr, vmsForm.getVmsFormId(), isEVehEndForm, vmsSchFormType, vmsForm.getVmsFormDsplDrctCd());
                         continue;
                     }
@@ -891,15 +899,16 @@ public class VmsManageService {
                         }
                     }
                     if (reqTraffic != setTraffic) {
-                        log.error("VmsManageService.makeVmsProvideForm: No Traffic: VMS({}), FormId({}), Req {}, Set {}",
+                        log.error("VmsManageService.makeVmsProvideForm: No Traffic: VMS({}), FormId({}), Req {}, Set {}.",
                                 ctlrNmbr, schedule.getVmsFormId(), reqTraffic, setTraffic);
                         continue;
                     }
                 } // 1,2,3,4 단 소통정보 표출 폼인 경우
 
                 // 스케줄에 따른 VMS FORM 을 생성한다.
-                VmsForm form = vmsObj.getFormManager().addForm(schedule.getVmsFormId());
+                VmsForm form = vmsObj.getFormManager().addForm(schedule.getVmsFormId(), schedule.getDnldFormId());
                 form.initDownload(vmsObj, vmsForm, schedule);
+
                 for (int objectIdx = 0; objectIdx < vmsForm.getObjects().size(); objectIdx++) {
                     if (objectIdx >= VmsConstants.VMS_MAX_FORM_OBJECTS) {
                         log.error("VmsManageService.makeVmsProvideForm: VMS({}), FormId({}), Form Object count overflow {} EA.",
@@ -1165,7 +1174,7 @@ public class VmsManageService {
                             try {
                                 ImageIO.write(formImage, "bmp", out);
                             } catch (IOException e) {
-                                log.error("VmsManageService.makeVmsProvideForm: Image Convert error: {}", formObj.getImageId());
+                                log.error("VmsManageService.makeVmsProvideForm: Image Convert error: {}.", formObj.getImageId());
                             }
                             g2d.dispose();
                             formObj.setImageData(out.toByteArray());
@@ -1516,7 +1525,7 @@ public class VmsManageService {
             }
             pForm.setSuccess(true);
 
-            log.info("VmsManagerService.makeVmsDatabaseFormData: VMS {}, FORM {}, Objects {}. ScheduleType {}, FileType {}, File/FtpName {}/{}",
+            log.info("VmsManagerService.makeVmsDatabaseFormData: VMS {}, FORM {}, Objects {}. ScheduleType {}, FileType {}, File/FtpName {}/{}.",
                     vmsObj.getVmsCtlrNmbr(), pForm.getVmsFormId(), pForm.count(), eVmsScheduleType.getValue(pForm.getVmsSchFormType()), pForm.getFileType(), pForm.getLocalFileName(), pForm.getFtpFileName());
         }
     }

+ 1 - 1
src/main/java/com/its/vms/service/VmsParkService.java

@@ -43,7 +43,7 @@ public class VmsParkService {
             });
         }
         catch (Exception e) {
-            log.error("VmsParkService.loadVmsParkInfo: {}", e.toString());
+            log.error("VmsParkService.loadVmsParkInfo: {}.", e.toString());
         }
         log.info("VmsParkService.loadVmsParkInfo: {} ms.", elapsed.milliSeconds());
     }

+ 178 - 11
src/main/java/com/its/vms/service/VmsSymbService.java

@@ -5,10 +5,13 @@ import com.its.app.utils.FloodFill;
 import com.its.app.utils.ItsUtils;
 import com.its.vms.config.ApplicationConfig;
 import com.its.vms.dao.mapper.VmsSymbMapper;
-import com.its.vms.dto.TbVmsSymbIfscDto;
-import com.its.vms.dto.TbVmsSymbLibDto;
+import com.its.vms.dto.*;
 import com.its.vms.entity.TbVmsSymbIfsc;
 import com.its.vms.entity.TbVmsSymbLib;
+import com.its.vms.entity.TbVmsSymbLibDnld;
+import com.its.vms.entity.VmsScheduleSymb;
+import com.its.vms.xnettcp.vms.process.TcpServerSendData;
+import com.its.vms.xnettcp.vms.protocol.enums.eVmsOpCode;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
@@ -21,6 +24,7 @@ import java.io.File;
 import java.io.IOException;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.ConcurrentHashMap;
 
 @Slf4j
@@ -29,6 +33,7 @@ import java.util.concurrent.ConcurrentHashMap;
 public class VmsSymbService {
 
     private final ApplicationConfig config;
+    private final AppRepositoryService repoService;
     private final VmsSymbMapper mapper;
 
     private final ConcurrentHashMap<String, TbVmsSymbLibDto> dataMap = new ConcurrentHashMap<>();
@@ -42,6 +47,9 @@ public class VmsSymbService {
         loadVmsSymbCellInfo();
     }
 
+    /**
+     * 심벌 라이브러리 이미지를 조회한다.
+     */
     public void loadVmsSymbLib() {
         // SBT0:일반심벌이미지,SBT1:소통정보배경,SBT2:소통정보이미지,SBT3:동영상,SBT4:대기환경등급, SBT9:동영상/스트리밍영상주소기본이미지
         Elapsed elapsed = new Elapsed();
@@ -49,8 +57,12 @@ public class VmsSymbService {
             List<TbVmsSymbLib> infoList  = this.mapper.selectVmsSymbLib();
             log.info("VmsSymbService.loadVmsSymbLib: {} EA", infoList.size());
             infoList.forEach(data -> {
-                // 심벌 유형(SBT0:일반심벌이미지,SBT1:소통정보배경,SBT2:소통정보이미지,SBT3:동영상,SBT4:대기환경등급)
+                // SBT0:일반심벌이미지,SBT1:소통정보배경,SBT2:소통정보이미지,SBT3:동영상,SBT4:대기환경등급, SBT9:동영상/스트리밍영상주소기본이미지
                 // 소통정보이미지 때문에 이미지번호에 "0" 을 추가하여 이미지번호로 사용함
+                if ("SBT9".equals(data.getSymbType())) {
+                    return;
+                }
+
                 String updtDt = "";
                 TbVmsSymbLibDto obj = data.toDto();
                 TbVmsSymbLibDto oldObj = this.dataMap.get(obj.getSymbLibNmbr());
@@ -73,7 +85,7 @@ public class VmsSymbService {
                 obj.setLocalFileName(this.config.getFtpImageDir() + obj.getSymbFileNm());
                 obj.setFtpFileName(ApplicationConfig.FTP_IMAGE + File.separator + obj.getSymbFileNm()); // Ftp 다운로드 명을 설정
 
-                // 심벌 유형(SBT0:일반심벌이미지,SBT1:소통정보배경,SBT2:소통정보이미지,SBT3:동영상,SBT4:대기환경등급)
+                // SBT0:일반심벌이미지,SBT1:소통정보배경,SBT2:소통정보이미지,SBT3:동영상,SBT4:대기환경등급, SBT9:동영상/스트리밍영상주소기본이미지
                 if ("SBT3".equals(obj.getSymbType())) {
                     //위에서 이미지저장하기 위해 파일명을 변경하기 때문에 여기서 동영상 파일명을 다시 읽어온다
                     obj.setSymbFileNm(data.getSymbFileNm()); //동영상인 경우 동영상 파일명
@@ -82,7 +94,7 @@ public class VmsSymbService {
                 }
 
                 if ("SBT2".equals(obj.getSymbType())) {
-                    //심벌 유형(SBT0:일반심벌이미지,SBT1:소통정보배경,SBT2:소통정보이미지,SBT3:동영상)
+                    // 심벌 유형(SBT0:일반심벌이미지,SBT1:소통정보배경,SBT2:소통정보이미지,SBT3:동영상,SBT4:대기환경등급)
                     //소통정보 등급에 따른 이미지를 새롭게 추가한다.
                     for (int nTrf = 1; nTrf <= 3; nTrf++) {
                         String trfUpdtDt = "";
@@ -97,7 +109,7 @@ public class VmsSymbService {
 
                         Image imgBmp = obj.getImage();  // 원천이미지를 가지고 온다.
                         if (imgBmp == null) {
-                            log.error("VmsSymbService.loadVmsSymbLib: Image Data Error: {}", trafSymbLibNmbr);
+                            log.error("VmsSymbService.loadVmsSymbLib: Image Data Error: {}.", trafSymbLibNmbr);
                             continue;
                         }
 
@@ -118,7 +130,7 @@ public class VmsSymbService {
                         try {
                             ImageIO.write(formImage, imagFmt, out);
                         } catch (IOException e) {
-                            log.error("VmsSymbService.loadVmsSymbLib: Image Convert error: {}", trafSymbLibNmbr);
+                            log.error("VmsSymbService.loadVmsSymbLib: Image Convert error: {}.", trafSymbLibNmbr);
                         }
                         g2d.dispose();
                         trfObj.setImageData(out.toByteArray());
@@ -142,11 +154,20 @@ public class VmsSymbService {
             });
         }
         catch (Exception e) {
-            log.error("VmsSymbService.loadVmsSymbLib: {}", e.toString());
+            log.error("VmsSymbService.loadVmsSymbLib: {}.", e.toString());
         }
+
+        this.dataMap.forEach((key, symb) -> {
+            log.info("VmsSymbService.loadVmsSymbLib: Symb {}, OrgSymb {}, Size {}.", symb.getSymbLibNmbr(), symb.getOrgSymbLibNmbr(), symb.getImageData().length);
+        });
+
+        log.info("VmsSymbService.loadVmsSymbLib: SymbLib {} EA.", this.dataMap.size());
         log.info("VmsSymbService.loadVmsSymbLib: {} ms.", elapsed.milliSeconds());
     }
 
+    /**
+     * 도형식 소통정보 및 소통정보 이미지를 셀 정보를 조회한다.
+     */
     public void loadVmsSymbCellInfo() {
         Elapsed elapsed = new Elapsed();
         try {
@@ -170,20 +191,24 @@ public class VmsSymbService {
             });
         }
         catch (Exception e) {
-            log.error("VmsSymbService.loadVmsSymbCellInfo: {}", e.getMessage());
+            log.error("VmsSymbService.loadVmsSymbCellInfo: {}.", e.getMessage());
         }
         log.info("VmsSymbService.loadVmsSymbCellInfo: {} ms.", elapsed.milliSeconds());
     }
 
     public void saveByteArrayToFile(TbVmsSymbLibDto obj, String updtDt) {
         File imagFile = new File(obj.getLocalFileName());
+        // 이미지 파일이 존재하지 않거나 이미지가 변경되었으면 삭제하고 다시 저장
         if (!imagFile.exists() || !obj.getUpdtDt().equals(updtDt)) {
             if (imagFile.exists()) {
-                boolean deleted = imagFile.delete();
-                log.info("VmsSymbService.saveImageFile: Old file deleted {}, {}", obj.getLocalFileName(), deleted);
+                // 이미지가 존재하면 삭제(이미지가 변경된 경우임)
+                imagFile.delete();
             }
             ItsUtils.saveByteArrayToFile(obj.getLocalFileName(), obj.getImageData());
         }
+        if ("".equals(updtDt)) {
+            updtDt = obj.getUpdtDt();
+        }
         obj.setUpdtDt(updtDt);  // 업데이트 시각을 업데이트 한다.
     }
 
@@ -201,4 +226,146 @@ public class VmsSymbService {
         return Color.GRAY;
     }
 
+    /**
+     * 제어기로 이미 다운로드 한 심벌 라이브러리 정보를 조회한다.
+     */
+    public void loadVmsSymbLibDnld() {
+        Elapsed elapsed = new Elapsed();
+        log.info("VmsSymbService.loadVmsSymbLibDnld: START.");
+        List<TbVmsSymbLibDnld> result = this.mapper.selectVmsSymbLibDnld();
+        result.forEach(obj -> {
+            TbVmsCtlrDto vmsObj = this.repoService.getCtrlMap(obj.getVmsCtlrNmbr());
+            if (vmsObj == null) {
+                log.error("VmsSymbService.loadVmsSymbLibDnld: VMS Not Found {}.", obj.getVmsCtlrNmbr());
+                return;
+            }
+            TbVmsSymbLibDnldDto dnldSymb = obj.toDto();
+            vmsObj.getDnldSymbMap().put(dnldSymb.getDnldSymbLibNmbr(), dnldSymb);
+        });
+
+        this.repoService.getCtlrMap().forEach((key, vmsObj) -> {
+            if (vmsObj.getDnldSymbMap().size() > 0) {
+                log.info("VmsSymbService.loadVmsSymbLibDnld: VMS {} Already Dnld Symb {} EA.", vmsObj.getVmsCtlrNmbr(), vmsObj.getDnldSymbMap().size());
+            }
+        });
+        log.info("VmsSymbService.loadVmsSymbLibDnld: ..END. {} ms.", elapsed.milliSeconds());
+    }
+
+    /**
+     * VMS 스케쥴에 등록된 심벌라이브러리 정보를 조회하고 제어기의 다운로드 정보를 작성한다.
+     */
+    public void loadVmsScheSymbLib() {
+        Elapsed elapsed = new Elapsed();
+        log.info("VmsSymbService.loadVmsScheduleSymbol: START.");
+        List<VmsScheduleSymb> result = this.mapper.selectVmsScheSymbLib();
+        result.forEach(obj -> {
+            TbVmsCtlrDto vmsObj = this.repoService.getCtrlMap(obj.getVmsCtlrNmbr());
+            if (vmsObj == null) {
+                log.error("VmsSymbService.loadVmsScheduleSymbol: VMS Not Found {}.", obj.getVmsCtlrNmbr());
+                return;
+            }
+
+            TbVmsSymbLibDto symb = this.dataMap.get(obj.getSymbLibNmbr()+"0");
+            if (symb == null) {
+                log.error("VmsSymbService.loadVmsScheduleSymbol: VMS {} Schedule Symb Not Found {}.", obj.getVmsCtlrNmbr(), obj.getSymbLibNmbr());
+                return;
+            }
+
+            if (checkDnldSymbol(vmsObj, symb.getSymbLibNmbr(), symb.getUpdtDt())) {
+                addReqDnldBitmapIdSymbol(vmsObj, symb);
+            }
+
+            if ("SBT2".equals(symb.getSymbType())) {
+                // SBT0:일반심벌이미지,SBT1:소통정보배경,SBT2:소통정보이미지,SBT3:동영상,SBT4:대기환경등급, SBT9:동영상/스트리밍영상주소기본이미지
+                for (int nTrf = 1; nTrf <= 3; nTrf++) {
+                    String trafSymbLibNmbr = obj.getSymbLibNmbr() + String.valueOf(nTrf);
+                    TbVmsSymbLibDto trfSymb = this.dataMap.get(trafSymbLibNmbr);
+                    if (trfSymb == null) {
+                        log.error("VmsSymbService.loadVmsScheduleSymbol: VMS {} Schedule Traffic Symb Not Found {}/{}.", obj.getVmsCtlrNmbr(), obj.getSymbLibNmbr(), trafSymbLibNmbr);
+                        continue;
+                    }
+                    if (checkDnldSymbol(vmsObj, trafSymbLibNmbr, trfSymb.getUpdtDt())) {
+                        addReqDnldBitmapIdSymbol(vmsObj, trfSymb);
+                    }
+                }
+            }
+            else if ("SBT4".equals(symb.getSymbType())) {
+                // SBT0:일반심벌이미지,SBT1:소통정보배경,SBT2:소통정보이미지,SBT3:동영상,SBT4:대기환경등급, SBT9:동영상/스트리밍영상주소기본이미지
+                for (String symbNmbr : symb.getGradSymbLibNmbrList()) {
+                    if (symbNmbr.equals(symb.getSymbLibNmbr())) {
+                        continue;
+                    }
+                    TbVmsSymbLibDto atmpSymb = this.dataMap.get(symbNmbr);
+                    if (atmpSymb == null) {
+                        log.error("VmsSymbService.loadVmsScheduleSymbol: VMS {} Schedule Atmp Symb Not Found {}, {}.",
+                                obj.getVmsCtlrNmbr(), symb.getSymbLibNmbr(), symbNmbr);
+                    }
+                    else {
+                        if (checkDnldSymbol(vmsObj, symbNmbr, atmpSymb.getUpdtDt())) {
+                            addReqDnldBitmapIdSymbol(vmsObj, atmpSymb);
+                        }
+                    }
+                }
+            }
+        });
+
+        this.repoService.getCtlrMap().forEach((key, vmsObj) -> {
+            if (vmsObj.getReqDnldSymbMap().size() > 0) {
+                vmsObj.addRequestData(new TcpServerSendData(eVmsOpCode.OP_VMS_DATA_DOWNLOAD, null));
+                log.info("VmsSymbService.loadVmsScheduleSymbol: VMS {} Req Dnld Symb {} EA.", vmsObj.getVmsCtlrNmbr(), vmsObj.getReqDnldSymbMap().size());
+            }
+        });
+        log.info("VmsSymbService.loadVmsScheduleSymbol: ..END. {} ms.", elapsed.milliSeconds());
+    }
+
+    /**
+     * 심벌 이미지가 이미 다운로드 되어 있어 다운로드가 필요한지 체크한다.
+     * @param vmsObj
+     * @param symbLibNmbr
+     * @param updtDt
+     * @return
+     */
+    private boolean checkDnldSymbol(TbVmsCtlrDto vmsObj, String symbLibNmbr, String updtDt) {
+        boolean result = true;
+        Integer dnldSymbLibNmbr = getDnldSymbNmbr(symbLibNmbr);
+        TbVmsSymbLibDnldDto dnldSymb = vmsObj.getDnldSymbMap().get(dnldSymbLibNmbr);
+        if (dnldSymb != null) {
+            if (Objects.equals(dnldSymb.getUpdtDt(), updtDt)) {
+                // 업데이트 시각이 동일하기 때문에 다운로드 하지 않음.
+                result = false;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * 다운로드 해야할 심벌 이미지 정보를 추가한다.
+     * @param vmsObj
+     * @param symb
+     */
+    private void addReqDnldBitmapIdSymbol(TbVmsCtlrDto vmsObj, TbVmsSymbLibDto symb) {
+        Integer dnldSymbLibNmbr = getDnldSymbNmbr(symb.getSymbLibNmbr());
+        VmsScheduleSymbDto dnldSymb = VmsScheduleSymbDto.builder()
+                .vmsCtlrNmbr(vmsObj.getVmsCtlrNmbr())
+                .dnldSymbLibNmbr(dnldSymbLibNmbr)
+                .symbLibNmbr(symb.getOrgSymbLibNmbr())
+                .updtDt(symb.getUpdtDt())
+                .imageData(symb.getImageData())
+                .build();
+        vmsObj.getReqDnldSymbMap().put(dnldSymbLibNmbr, dnldSymb);
+    }
+
+    /**
+     * 내부에서 사용하는 심벌 라이브러리 번호를 제어기로 다운로드하는 BitmapId 로 변환한다.
+     * @param symbLibNmbr : 8000 -> 8000 + "0", traffic image: 6020 -> 6020 + "0", 6020 + "1", 6020 + "2", 6020 + "3"
+     * @return
+     */
+    public static int getDnldSymbNmbr(String symbLibNmbr) {
+        int symbNo = Integer.parseInt(symbLibNmbr);
+        int key = (symbNo / 10000);
+        int id = symbNo % 10000;
+
+        return (key * 1000) + id;
+    }
+
 }

+ 5 - 0
src/main/java/com/its/vms/xnettcp/vms/process/TcpServerSendDataProcess.java

@@ -95,6 +95,11 @@ public class TcpServerSendDataProcess {
                         result = this.vmsObj.sendData(reqUploadScheduleFrom.getByteBuffer(), 10, reqUploadScheduleFrom.getOpCodeDesc());
                         break;
 
+                    case OP_VMS_DATA_DOWNLOAD:
+                        if (data.getData() == null) {
+                            this.vmsObj.downloadSymbLib();
+                        }
+                        break;
                     case OP_VMS_STATUS_CONTROL:
                         VmsReqStatusControl statusControl = (VmsReqStatusControl) data.getData();
                         result = this.vmsObj.sendData(statusControl.getByteBuffer(), 10, statusControl.getOpCodeDesc());

+ 49 - 2
src/main/java/com/its/vms/xnettcp/vms/process/response/impl/VmsResDataDownload.java

@@ -1,12 +1,20 @@
 package com.its.vms.xnettcp.vms.process.response.impl;
 
+import com.its.app.AppUtils;
+import com.its.app.utils.SysUtils;
+import com.its.vms.domain.NET;
 import com.its.vms.dto.TbVmsCtlrDto;
+import com.its.vms.dto.TbVmsSymbLibDnldDto;
+import com.its.vms.dto.VmsScheduleSymbDto;
+import com.its.vms.process.DbmsData;
+import com.its.vms.process.DbmsDataProcess;
+import com.its.vms.process.DbmsDataType;
 import com.its.vms.xnettcp.vms.process.response.VmsResponse;
 import com.its.vms.xnettcp.vms.protocol.VmsFramePacket;
+import com.its.vms.xnettcp.vms.protocol.VmsProtocolConst;
 import com.its.vms.xnettcp.vms.protocol.enums.eVmsErrorCode;
 import com.its.vms.xnettcp.vms.protocol.enums.eVmsOpCode;
 import com.its.vms.xnettcp.vms.protocol.impl.dle.VmsDleFramePacket;
-import com.its.vms.xnettcp.vms.protocol.VmsProtocolConst;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 
@@ -53,7 +61,46 @@ public class VmsResDataDownload implements VmsResponse {
         log.info("{}", toString());
 
         if (this.error == eVmsErrorCode.ERROR_NONE) {
-            this.vmsObj.downloadFile();
+            if (this.vmsObj.getReqDnldSymbMap().size() == 0 || this.vmsObj.getDnldSymbLibNmbr() == 0) {
+                this.vmsObj.downloadFile();
+            }
+            else {
+                if (this.vmsObj.getDnldSymbLibNmbr() != 0) {
+                    VmsScheduleSymbDto dnldSymb = this.vmsObj.getReqDnldSymbMap().get(this.vmsObj.getDnldSymbLibNmbr());
+                    if (dnldSymb != null) {
+                        TbVmsSymbLibDnldDto dnldDto = this.vmsObj.getDnldSymbMap().get(this.vmsObj.getDnldSymbLibNmbr());
+                        if (dnldDto == null) {
+                            dnldDto = TbVmsSymbLibDnldDto.builder()
+                                    .vmsCtlrNmbr(this.vmsObj.getVmsCtlrNmbr())
+                                    .dnldSymbLibNmbr(this.vmsObj.getDnldSymbLibNmbr())
+                                    .dnldDt(SysUtils.getSysTime())
+                                    .dnldCnt(1)
+                                    .symbLibNmbr(dnldSymb.getSymbLibNmbr())
+                                    .updtDt(dnldSymb.getUpdtDt())
+                                    .build();
+                            this.vmsObj.getDnldSymbMap().put(dnldDto.getDnldSymbLibNmbr(), dnldDto);
+                        }
+                        else {
+                            dnldDto.setDnldDt(SysUtils.getSysTime());
+                            dnldDto.setDnldCnt(dnldDto.getDnldCnt() + 1);
+                            dnldDto.setUpdtDt(dnldSymb.getUpdtDt());
+                        }
+                        this.vmsObj.getReqDnldSymbMap().remove(this.vmsObj.getDnldSymbLibNmbr());
+
+                        DbmsDataProcess dbmsDataProcess = (DbmsDataProcess)AppUtils.getBean(DbmsDataProcess.class);
+                        dbmsDataProcess.add(new DbmsData(DbmsDataType.DBMS_DATA_SYMB_DNLD, false, dnldDto.toEntity()));
+                    }
+                }
+                if (this.vmsObj.downloadSymbLib()) {
+                    // 더이상 다운로드 할 심벌 라이브러리가 없는 경우....
+                    if (this.vmsObj.getNetState() == NET.LOGIN_REQ) {
+                        // 최초 접속후, 상태정보->파워모듈상태->표출모듈상태->파라미터정보 조회 완료후
+                        // 네트워크 로그인 상태로 설정하고 스케쥴을 다운로드 하도록 한다.
+                        this.vmsObj.setNetState(NET.LOGINED);
+                        this.vmsObj.downloadForm(false);
+                    }
+                }
+            }
         }
         return true;
     }

+ 7 - 3
src/main/java/com/its/vms/xnettcp/vms/process/response/impl/VmsResParameter.java

@@ -82,10 +82,14 @@ public class VmsResParameter implements VmsResponse {
         if (this.vmsObj.getNetState() == NET.LOGIN_REQ) {
             // 최초 접속후, 상태정보->파워모듈상태->표출모듈상태->파라미터정보 조회 완료후
             // 네트워크 로그인 상태로 설정하고 스케쥴을 다운로드 하도록 한다.
-            this.vmsObj.setNetState(NET.LOGINED);
-            this.vmsObj.downloadForm(false);
+            if (this.vmsObj.getReqDnldSymbMap().size() > 0) {
+                this.vmsObj.downloadSymbLib();
+            }
+            else {
+                this.vmsObj.setNetState(NET.LOGINED);
+                this.vmsObj.downloadForm(false);
+            }
         }
-
         return true;
     }
 

+ 49 - 1
src/main/resources/mybatis/mapper/VmsSymbMapper.xml

@@ -44,7 +44,7 @@
         ]]>
     </select>
 
-    <select id="selectVmsSymbol" resultType="com.its.vms.entity.TbVmsSymbIfsc" fetchSize="200">
+    <select id="selectVmsScheSymbLib" resultType="com.its.vms.entity.VmsScheduleSymb" fetchSize="200">
     <![CDATA[
         select a.vms_ctlr_nmbr as vmsCtlrNmbr,
                b.symb_lib_nmbr as symbLibNmbr,
@@ -66,5 +66,53 @@
     ]]>
     </select>
 
+    <select id="selectVmsSymbLibDnld" resultType="com.its.vms.entity.TbVmsSymbLibDnld" fetchSize="500">
+    <![CDATA[
+        select t1.vms_ctlr_nmbr      AS vmsCtlrNmbr,
+               t1.dnld_symb_lib_nmbr AS dnldSymbLibNmbr,
+               t1.dnld_dt            AS dnldDt,
+               t1.dnld_cnt           AS dnldCnt,
+               t1.symb_lib_nmbr      AS symbLibNmbr,
+               t1.updt_dt            AS updtDt
+        from tb_vms_symb_lib_dnld t1
+        ]]>
+    </select>
+
+    <update id="updateVmsSymbLibDnld" parameterType="com.its.vms.entity.TbVmsSymbLibDnld">
+    <![CDATA[
+        merge into tb_vms_symb_lib_dnld L
+            using (select
+                       #{obj.vmsCtlrNmbr}     AS vms_ctlr_nmbr,
+                       #{obj.dnldSymbLibNmbr} AS dnld_symb_lib_nmbr,
+                       #{obj.dnldDt}          AS dnld_dt,
+                       #{obj.dnldCnt}         AS dnld_cnt,
+                       #{obj.symbLibNmbr}     AS symb_lib_nmbr,
+                       #{obj.updtDt}          AS updt_dt
+                   from dual) M
+                on (L.vms_ctlr_nmbr = M.vms_ctlr_nmbr
+                and L.dnld_symb_lib_nmbr = M.dnld_symb_lib_nmbr)
+            when matched then
+                update set
+                    L.dnld_dt       = M.dnld_dt,
+                    L.dnld_cnt      = M.dnld_cnt+1,
+                    L.symb_lib_nmbr = M.symb_lib_nmbr,
+                    L.updt_dt       = M.updt_dt
+            when not matched then
+                insert (
+                        vms_ctlr_nmbr,
+                        dnld_symb_lib_nmbr,
+                        dnld_dt,
+                        dnld_cnt,
+                        symb_lib_nmbr,
+                        updt_dt )
+                    values (
+                       M.vms_ctlr_nmbr,
+                       M.dnld_symb_lib_nmbr,
+                       M.dnld_dt,
+                       M.dnld_cnt,
+                       M.symb_lib_nmbr,
+                       M.updt_dt )
+        ]]>
+    </update>
 
 </mapper>

+ 16 - 0
src/test/java/com/its/app/VmsCommServerApplicationTests.java

@@ -1,6 +1,8 @@
 package com.its.app;
 
 import com.its.app.utils.SysUtils;
+import com.its.vms.service.VmsFormService;
+import com.its.vms.service.VmsSymbService;
 import com.its.vms.xnettcp.vms.protocol.enums.eVmsOpCode;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang.StringUtils;
@@ -92,4 +94,18 @@ public class VmsCommServerApplicationTests {
         byte[] arr2 = SysUtils.stringToByteArr(str);
         log.error("{}, {}, {}", str.length(), arr1.length, arr2.length);
     }
+
+    @Test
+    void getDnldNmbr() {
+        log.info("{}", VmsSymbService.getDnldSymbNmbr("60100"));
+        log.info("{}", VmsSymbService.getDnldSymbNmbr("80061"));
+        log.info("{}", VmsSymbService.getDnldSymbNmbr("80060"));
+        log.info("{}", VmsSymbService.getDnldSymbNmbr("80021"));
+        log.info("{}", VmsSymbService.getDnldSymbNmbr("8002"));
+
+        log.info("{}", VmsFormService.getDnldFormNo(10013));
+        log.info("{}", VmsFormService.getDnldFormNo(10054));
+        log.info("{}", VmsFormService.getDnldFormNo(10186));
+        log.info("{}", VmsFormService.getDnldFormNo(13));
+    }
 }