shjung 3 年之前
父節點
當前提交
bd5bb1e789
共有 24 個文件被更改,包括 417 次插入38 次删除
  1. 7 0
      src/main/java/com/its/api/its/controller/vms/TbVmsFormController.java
  2. 25 3
      src/main/java/com/its/api/its/controller/vms/TbVmsMsgDsplSchAutoController.java
  3. 1 1
      src/main/java/com/its/api/its/global/CctvManager.java
  4. 1 1
      src/main/java/com/its/api/its/global/CodeManager.java
  5. 1 1
      src/main/java/com/its/api/its/global/UnitSystManager.java
  6. 1 1
      src/main/java/com/its/api/its/global/VdsManager.java
  7. 4 1
      src/main/java/com/its/api/its/global/VmsIfscManager.java
  8. 1 1
      src/main/java/com/its/api/its/global/VmsManager.java
  9. 1 1
      src/main/java/com/its/api/its/global/VmsSymbLibManager.java
  10. 116 0
      src/main/java/com/its/api/its/model/dto/vms/VmsFormIfscDto.java
  11. 24 0
      src/main/java/com/its/api/its/model/dto/vms/VmsFormNewIdDto.java
  12. 4 1
      src/main/java/com/its/api/its/model/entity/vms/TbVmsForm.java
  13. 4 4
      src/main/java/com/its/api/its/model/entity/vms/TbVmsMsgDsplSch.java
  14. 3 0
      src/main/java/com/its/api/its/repository/vms/TbVmsFormRepository.java
  15. 3 0
      src/main/java/com/its/api/its/repository/vms/TbVmsMsgDsplSchRepository.java
  16. 1 0
      src/main/java/com/its/api/its/service/incident/TbIncdOcrrService.java
  17. 16 0
      src/main/java/com/its/api/its/service/vms/TbVmsFormService.java
  18. 31 4
      src/main/java/com/its/api/its/service/vms/TbVmsMsgDsplSchService.java
  19. 114 1
      src/main/java/com/its/api/utils/NettyUtils.java
  20. 21 6
      src/main/java/com/its/api/xnettcp/client/NettyTcpClient.java
  21. 19 10
      src/main/java/com/its/api/xnettcp/client/NettyTcpClientVdsBootstrapFactory.java
  22. 6 0
      src/main/java/com/its/api/xnettcp/client/listener/NettyTcpClientCloseListener.java
  23. 7 0
      src/main/java/com/its/api/xnettcp/client/listener/NettyTcpClientConnectListener.java
  24. 6 2
      src/main/java/com/its/api/xnettcp/client/service/VdsCommClientService.java

+ 7 - 0
src/main/java/com/its/api/its/controller/vms/TbVmsFormController.java

@@ -2,6 +2,7 @@ package com.its.api.its.controller.vms;
 
 import com.its.api.its.model.dto.vms.TbVmsFormDto;
 import com.its.api.its.model.dto.vms.TbVmsFormObjectDetlDto;
+import com.its.api.its.model.dto.vms.VmsFormNewIdDto;
 import com.its.api.its.service.vms.TbVmsFormService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -69,4 +70,10 @@ public class TbVmsFormController {
         return this.service.deleteByIds(ids);
     }
 
+    @ApiOperation(value = "신규 VMS FORM ID 조회(TB_VMS_FORM)", response = VmsFormNewIdDto.class)
+    @GetMapping(value = "/new-id", produces = {"application/json; charset=utf8"})
+    public VmsFormNewIdDto getNewVmsFormId() {
+        return this.service.getNewVmsFormId();
+    }
+
 }

+ 25 - 3
src/main/java/com/its/api/its/controller/vms/TbVmsMsgDsplSchAutoController.java

@@ -2,6 +2,7 @@ package com.its.api.its.controller.vms;
 
 import com.its.api.its.model.dto.vms.TbVmsMsgDsplSchDto;
 import com.its.api.its.model.dto.vms.VmsFormDrawTrafDto;
+import com.its.api.its.model.dto.vms.VmsFormIfscDto;
 import com.its.api.its.service.vms.TbVmsMsgDsplSchService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -36,13 +37,34 @@ public class TbVmsMsgDsplSchAutoController {
     ) {
         return this.service.findAllVmsDsplSchedule(id);
     }
+
+    /**
+     * 교통정보 폼 스케쥴 정보제공구간 요청
+     * @param id
+     * @param type
+     * @return
+     */
+    @ApiOperation(value = "VMS 제어기 유형별 폼 스케줄 목록 조회(TB_VMS_TRFC_INFR_DSPL_SCH)", response = VmsFormIfscDto.class)
+    @GetMapping(value = "/form/ifsc/{id}/{type}/{phase}", produces = {"application/json; charset=utf8"})
+    public VmsFormIfscDto findAllVmsFormIfsc(
+            @ApiParam(name = "id", value = "VMS 제어기 관리번호", example = "10005", required = true)
+            @PathVariable final Long id,
+            @ApiParam(name = "type", value = "VMS 스케쥴 코드(0:교통정보,1:돌발,2:공사/행사,3:홍보,4:우회도로,7:정체,8:재난안전)", example = "0", required = true)
+            @PathVariable final String type,
+            @ApiParam(name = "phase", value = "스케쥴 PHASE", example = "1", required = true)
+            @PathVariable final Integer phase
+    ) {
+        return this.service.findAllVmsFormIfsc(id, type, phase);
+    }
+
+
     @ApiOperation(value = "VMS 제어기 유형별 폼 스케줄 목록 조회(TB_VMS_TRFC_INFR_DSPL_SCH)", response = TbVmsMsgDsplSchDto.class, responseContainer = "ArrayList")
     @GetMapping(value = "/list-form/{id}/{type}", produces = {"application/json; charset=utf8"})
     public List<TbVmsMsgDsplSchDto> findAllVmsDsplSchedule(
             @ApiParam(name = "id", value = "VMS 제어기 관리번호", example = "10005", required = true)
             @PathVariable final Long id,
-            @ApiParam(name = "kind", value = "VMS 폼유형 코드(0:교통정보,1:돌발,2:공사/행사,3:홍보,4:우회도로,7:정체,8:재난안전)", example = "0", required = true)
-            @PathVariable final String kind
+            @ApiParam(name = "type", value = "VMS 스케쥴 코드(0:교통정보,1:돌발,2:공사/행사,3:홍보,4:우회도로,7:정체,8:재난안전)", example = "0", required = true)
+            @PathVariable final String type
     ) {
         // 교통정보 ("0");
         // 돌발 ("1");
@@ -51,7 +73,7 @@ public class TbVmsMsgDsplSchAutoController {
         // 우회도로 ("4");
         // 정체 ("7");
         // 재난안전 ("8");
-        List<String> trfcSituTypeCd = Arrays.asList(kind);
+        List<String> trfcSituTypeCd = Arrays.asList(type);
         return this.service.findAllVmsDsplSchedule(id, trfcSituTypeCd);
     }
     // 교통정보 폼 그리기

+ 1 - 1
src/main/java/com/its/api/its/global/CctvManager.java

@@ -32,7 +32,7 @@ public class CctvManager {
         objList.forEach(obj -> {
             objMap.put(obj.getCctvMngmNmbr(), obj);
         });
-        log.info("=== {}", objMap);
+        //log.info("=== {}", objMap);
     }
 
     public static TbCctvCtlr get(Long id) {

+ 1 - 1
src/main/java/com/its/api/its/global/CodeManager.java

@@ -119,7 +119,7 @@ public class CodeManager {
 
     public void load() {
         loadAllCode();
-        log.info("=== {}", codes);
+        //log.info("=== {}", codes);
     }
 
     private void loadSectGradStup() {

+ 1 - 1
src/main/java/com/its/api/its/global/UnitSystManager.java

@@ -32,7 +32,7 @@ public class UnitSystManager {
         objList.forEach(obj -> {
             objMap.put(obj.getSystId(), obj);
         });
-        log.info("=== {}", objMap);
+        //log.info("=== {}", objMap);
     }
 
     public static TbUnitSyst get(String id) {

+ 1 - 1
src/main/java/com/its/api/its/global/VdsManager.java

@@ -32,7 +32,7 @@ public class VdsManager {
         objList.forEach(obj -> {
             objMap.put(obj.getCtlrMngmNmbr(), obj);
         });
-        log.info("=== {}", objMap);
+        //log.info("=== {}", objMap);
     }
 
     public static TbVdsCtlr get(String id) {

+ 4 - 1
src/main/java/com/its/api/its/global/VmsIfscManager.java

@@ -32,10 +32,13 @@ public class VmsIfscManager {
         objList.forEach(obj -> {
             ifsc.put(obj.getVmsIfscId(), obj);
         });
-        log.info("=== {}", ifsc);
+        //log.info("=== {}", ifsc);
     }
 
     public static TbVmsIfsc get(Long id) {
+        if (id == null) {
+            return null;
+        }
         return ifsc.get(id);
     }
 

+ 1 - 1
src/main/java/com/its/api/its/global/VmsManager.java

@@ -32,7 +32,7 @@ public class VmsManager {
         objList.forEach(obj -> {
             objMap.put(obj.getVmsCtlrNmbr(), obj);
         });
-        log.info("=== {}", objMap);
+        //log.info("=== {}", objMap);
     }
 
     public static TbVmsCtlr get(Long id) {

+ 1 - 1
src/main/java/com/its/api/its/global/VmsSymbLibManager.java

@@ -49,7 +49,7 @@ public class VmsSymbLibManager {
             ifscMap.put(obj.getCellId(), obj);
         });
 
-        log.info("=== {}", lib);
+        //log.info("=== {}", lib);
     }
 
     public static TbVmsSymbLib get(Integer id) {

+ 116 - 0
src/main/java/com/its/api/its/model/dto/vms/VmsFormIfscDto.java

@@ -0,0 +1,116 @@
+package com.its.api.its.model.dto.vms;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.its.api.its.model.entity.vms.TbVmsIfsc;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Builder;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * VMS 교통 정보 표출 일정 DTO Class
+ */
+@Data
+@Builder
+@ApiModel("VmsFormIfscDto(VMS 교통 정보 폼 정보제공구간 정보)")
+public class VmsFormIfscDto implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty("VMS 제어기 번호")  // N NUMBER(10)
+    @JsonProperty("vms_ctlr_nmbr")
+    private Long vmsCtlrNmbr;
+
+    @ApiModelProperty("스케줄 유형 코드(0:교통정보,1:돌발,2:공사/행사문안,3:홍보문안,4:우회도로,5:고정스케줄, 6:기본스케줄)")  // N VARCHAR(7)
+    @JsonProperty("trfc_situ_type_cd")
+    private String trfcSituTypeCd;
+
+    @ApiModelProperty("PHASE")  // N NUMBER(2)
+    @JsonProperty("phase")
+    private Integer phase;
+
+    @ApiModelProperty("VMS FORM ID")  // Y NUMBER(5)
+    @JsonProperty("vms_form_id")
+    private Integer vmsFormId;
+
+    @ApiModelProperty("VMS FORM 유형 코드")  // N NUMBER(3)
+    @JsonProperty("vms_form_type_cd")
+    private Integer vmsFormTypeCd;
+
+    @ApiModelProperty("1단 VMS 정보제공구간")  // Y NUMBER(10)
+    @JsonProperty("frst_vms_ifsc")
+    private FormIfscInfo frstVmsIfsc;
+
+    @ApiModelProperty("2단 VMS 정보제공구간")  // Y NUMBER(10)
+    @JsonProperty("secd_vms_ifsc")
+    private FormIfscInfo secdVmsIfsc;
+
+    @ApiModelProperty("3단 VMS 정보제공구간")  // Y NUMBER(10)
+    @JsonProperty("thir_vms_ifsc")
+    private FormIfscInfo thirVmsIfsc;
+
+    @ApiModelProperty("4단 VMS 정보제공구간")  // Y NUMBER(10)
+    @JsonProperty("four_vms_ifsc")
+    private FormIfscInfo fourVmsIfsc;
+
+    @ApiModelProperty("1단 이미지 정보제공구간")  // Y NUMBER(10)
+    @JsonProperty("frst_img_ifsc")
+    private FormIfscInfo frstImgIfsc;
+
+    @ApiModelProperty("2단 이미지 정보제공구간")  // Y NUMBER(10)
+    @JsonProperty("secd_img_ifsc")
+    private FormIfscInfo secdImgIfsc;
+
+    @ApiModelProperty("3단 이미지 정보제공구간")  // Y NUMBER(10)
+    @JsonProperty("thir_img_ifsc")
+    private FormIfscInfo thirImgIfsc;
+
+    @ApiModelProperty("4단 이미지 정보제공구간")  // Y NUMBER(10)
+    @JsonProperty("four_img_ifsc")
+    private FormIfscInfo fourImgIfsc;
+
+    public static class FormIfscInfo {
+
+        @ApiModelProperty("VMS 정보제공구간 ID")  // N NUMBER(10)
+        @JsonProperty("vms_ifsc_id")
+        private Long vmsIfscId;
+
+        @ApiModelProperty("VMS 정보제공구간 명")  // Y VARCHAR(60)
+        @JsonProperty("vms_ifsc_nm")
+        private String vmsIfscNm;
+
+        @ApiModelProperty("표출 시작 노드 명")  // Y VARCHAR(30)
+        @JsonProperty("dspl_strt_node_nm")
+        private String dsplStrtNodeNm;
+
+        @ApiModelProperty("표출 종료 노드 명")  // Y VARCHAR(30)
+        @JsonProperty("dspl_end_node_nm")
+        private String dsplEndNodeNm;
+
+        @ApiModelProperty("도로명")  // Y VARCHAR(30)
+        @JsonProperty("road_nm")
+        private String roadNm;
+
+        @ApiModelProperty("지점명")  // Y VARCHAR(30)
+        @JsonProperty("spot_nm")
+        private String spotNm;
+
+        @ApiModelProperty("축정보 생성용")  // Y CHAR(1)
+        @JsonProperty("axis_yn")
+        private String axisYn;
+
+         public FormIfscInfo(TbVmsIfsc ifsc) {
+            if (ifsc != null) {
+                this.vmsIfscId = ifsc.getVmsIfscId();
+                this.vmsIfscNm = ifsc.getVmsIfscNm();
+                this.dsplStrtNodeNm = ifsc.getDsplStrtNodeNm();
+                this.dsplEndNodeNm = ifsc.getDsplEndNodeNm();
+                this.roadNm = ifsc.getRoadNm();
+                this.spotNm = ifsc.getSpotNm();
+                this.axisYn = ifsc.getAxisYn();
+            }
+        }
+
+    }
+}

+ 24 - 0
src/main/java/com/its/api/its/model/dto/vms/VmsFormNewIdDto.java

@@ -0,0 +1,24 @@
+package com.its.api.its.model.dto.vms;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Builder;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 돌발상황 발생 DTO Class
+ */
+@Data
+@Builder
+@ApiModel("VmsFormNewIdDto(신규 VMS FORM ID 정보)")
+public class VmsFormNewIdDto implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty("VMS FORM ID")  // N NUMBER(5)
+    @JsonProperty("vms_form_id")
+    private Integer vmsFormId;
+
+}

+ 4 - 1
src/main/java/com/its/api/its/model/entity/vms/TbVmsForm.java

@@ -1,6 +1,7 @@
 package com.its.api.its.model.entity.vms;
 
 import com.its.api.its.model.dto.vms.TbVmsFormDto;
+import com.its.api.utils.ItsUtils;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.*;
@@ -77,7 +78,9 @@ public class TbVmsForm implements Serializable {
                 .vmsFormExpl(this.vmsFormExpl)
                 .vmsMsgDsplDrctCd(this.vmsMsgDsplDrctCd)
                 .symbLibNmbr(this.symbLibNmbr)
-                .vmsFormImag(this.vmsFormImag)
+                //.vmsFormImag(this.vmsFormImag)
+                .vmsFormImag(ItsUtils.convertBmpToPng(this.vmsFormImag))
+                .imagFmt("png")
                 .vmsMsgDsplMthdCd(this.vmsMsgDsplMthdCd)
                 .cctvMngmNmbr(this.cctvMngmNmbr)
                 .build();

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

@@ -97,15 +97,15 @@ public class TbVmsMsgDsplSch implements Serializable {
     @Column(name = "FOUR_IMG_IFSC_ID", columnDefinition = "NUMBER", length = 10)
     private Long fourImgIfscId;
 
-    public void setPhase(int phase) {
-        this.phase = phase;
-    }
-
     @OneToOne
     @JoinColumn(insertable=false, updatable=false, name="VMS_FORM_ID", referencedColumnName = "VMS_FORM_ID")
     @NotFound(action = NotFoundAction.IGNORE)
     private TbVmsForm form = new TbVmsForm();
 
+    public void setPhase(int phase) {
+        this.phase = phase;
+    }
+
     public TbVmsMsgDsplSchDto toDto() {
         TbVmsMsgDsplSchDto dto = TbVmsMsgDsplSchDto.builder()
                 .vmsCtlrNmbr(this.vmsCtlrNmbr)

+ 3 - 0
src/main/java/com/its/api/its/repository/vms/TbVmsFormRepository.java

@@ -79,4 +79,7 @@ public interface TbVmsFormRepository extends JpaRepository<TbVmsForm, Integer>,
         " where d.vmsFormId = :formId" +
         " order by a.formObjectId asc")
     List<TbVmsFormObjectDetlInf> findByVmsFormObject(@Param("formId") Integer formId);
+
+    @Query(value = "SELECT NVL(MAX(VMS_FORM_ID), 9999)+1 AS NEWID FROM TB_VMS_FORM", nativeQuery = true)
+    Integer getNewVmsFormId();
 }

+ 3 - 0
src/main/java/com/its/api/its/repository/vms/TbVmsMsgDsplSchRepository.java

@@ -17,6 +17,9 @@ public interface TbVmsMsgDsplSchRepository extends JpaRepository<TbVmsMsgDsplSch
     @Query("select p from TbVmsMsgDsplSch p inner join fetch p.form form")
     List<TbVmsMsgDsplSch> findAll();
 
+    @Query("select p from TbVmsMsgDsplSch p inner join fetch p.form form where p.vmsCtlrNmbr = :id and p.trfcSituTypeCd = :type and p.phase = :phase")
+    TbVmsMsgDsplSch findScheduleForm(@Param("id") Long id, @Param("type") String type, @Param("phase") Integer phase);
+
     @Modifying
     @Query("delete from TbVmsMsgDsplSch p where p.vmsCtlrNmbr = :vmsCtlrNmbr and p.trfcSituTypeCd in :trfcSituTypeCd")
     void deleteDataByVmsCtrlTrfcSituTypeCd(@Param("vmsCtlrNmbr") Long vmsCtlrNmbr, @Param("trfcSituTypeCd") List<String> trfcSituTypeCd);

+ 1 - 0
src/main/java/com/its/api/its/service/incident/TbIncdOcrrService.java

@@ -119,6 +119,7 @@ public class TbIncdOcrrService {
      * @param
      * @return
      */
+    @Transactional(readOnly = true)
     public IncdNewIdDto getNewIncdId() {
         String centerId = this.processConfig.getCenterId();
         String newId = this.repo.getNewIncdId(centerId);

+ 16 - 0
src/main/java/com/its/api/its/service/vms/TbVmsFormService.java

@@ -2,6 +2,8 @@ package com.its.api.its.service.vms;
 
 import com.its.api.its.model.dto.vms.TbVmsFormDto;
 import com.its.api.its.model.dto.vms.TbVmsFormObjectDetlDto;
+import com.its.api.its.model.dto.vms.TbVmsFormTypeDto;
+import com.its.api.its.model.dto.vms.VmsFormNewIdDto;
 import com.its.api.its.model.entity.vms.TbVmsForm;
 import com.its.api.its.model.entity.vms.TbVmsFormObjectDetlInf;
 import com.its.api.its.repository.vms.TbVmsFormRepository;
@@ -213,4 +215,18 @@ public class TbVmsFormService {
         });
         return result;
     }
+
+    /**
+     * 신규 VMS FORM ID 조회
+     * @return
+     */
+    @Transactional(readOnly = true)
+    public VmsFormNewIdDto getNewVmsFormId() {
+        Integer newId = this.repo.getNewVmsFormId();
+        VmsFormNewIdDto result = VmsFormNewIdDto.builder()
+                .vmsFormId(newId)
+                .build();
+        return result;
+    }
+
 }

+ 31 - 4
src/main/java/com/its/api/its/service/vms/TbVmsMsgDsplSchService.java

@@ -2,10 +2,7 @@ package com.its.api.its.service.vms;
 
 import com.its.api.its.global.VmsIfscManager;
 import com.its.api.its.global.VmsManager;
-import com.its.api.its.model.dto.vms.TbVmsFormObjectDetlDto;
-import com.its.api.its.model.dto.vms.TbVmsMsgDsplSchDto;
-import com.its.api.its.model.dto.vms.TbVmsMsgDsplSchVmsListDto;
-import com.its.api.its.model.dto.vms.VmsFormDrawTrafDto;
+import com.its.api.its.model.dto.vms.*;
 import com.its.api.its.model.entity.vms.TbVmsCtlr;
 import com.its.api.its.model.entity.vms.TbVmsIfsc;
 import com.its.api.its.model.entity.vms.TbVmsMsgDsplSch;
@@ -534,4 +531,34 @@ public class TbVmsMsgDsplSchService {
         return result;
     }
 
+    /**
+     * VMS 교통정보 스케쥴 폼 의 정보제공구간 정보 조회
+     * @param id
+     * @param type
+     * @param phase
+     * @return
+     */
+    public VmsFormIfscDto findAllVmsFormIfsc(Long id, String type, Integer phase) {
+        VmsFormIfscDto result = VmsFormIfscDto.builder()
+                .vmsCtlrNmbr(id)
+                .trfcSituTypeCd(type)
+                .phase(phase)
+                .build();
+        TbVmsMsgDsplSch data = this.repo.findScheduleForm(id, type, phase);
+        if (data != null) {
+            result.setVmsFormId(data.getVmsFormId());
+            if (data.getForm() != null) {
+                result.setVmsFormTypeCd(data.getForm().getVmsFormTypeCd());
+            }
+            result.setFrstVmsIfsc(new VmsFormIfscDto.FormIfscInfo(VmsIfscManager.get(data.getFrstVmsIfscId())));
+            result.setSecdVmsIfsc(new VmsFormIfscDto.FormIfscInfo(VmsIfscManager.get(data.getSecdVmsIfscId())));
+            result.setThirVmsIfsc(new VmsFormIfscDto.FormIfscInfo(VmsIfscManager.get(data.getThirVmsIfscId())));
+            result.setFourVmsIfsc(new VmsFormIfscDto.FormIfscInfo(VmsIfscManager.get(data.getFourVmsIfscId())));
+            result.setFrstImgIfsc(new VmsFormIfscDto.FormIfscInfo(VmsIfscManager.get(data.getFrstImgIfscId())));
+            result.setSecdImgIfsc(new VmsFormIfscDto.FormIfscInfo(VmsIfscManager.get(data.getSecdImgIfscId())));
+            result.setThirImgIfsc(new VmsFormIfscDto.FormIfscInfo(VmsIfscManager.get(data.getThirImgIfscId())));
+            result.setFourImgIfsc(new VmsFormIfscDto.FormIfscInfo(VmsIfscManager.get(data.getFourImgIfscId())));
+        }
+        return result;
+    }
 }

+ 114 - 1
src/main/java/com/its/api/utils/NettyUtils.java

@@ -2,7 +2,9 @@ package com.its.api.utils;
 
 import io.netty.channel.Channel;
 
-import java.net.InetSocketAddress;
+import java.net.*;
+import java.util.ArrayList;
+import java.util.Enumeration;
 
 public final class NettyUtils {
 
@@ -69,4 +71,115 @@ public final class NettyUtils {
             port = inetAddr.getPort();
         return port;
     }
+
+    public static final String OS_NAME = System.getProperty("os.name");
+    private static boolean isLinuxPlatform = false;
+    private static boolean isWindowsPlatform = false;
+
+    static {
+        if (OS_NAME != null && OS_NAME.toLowerCase().contains("linux")) {
+            isLinuxPlatform = true;
+        }
+
+        if (OS_NAME != null && OS_NAME.toLowerCase().contains("windows")) {
+            isWindowsPlatform = true;
+        }
+    }
+
+    public static String getLocalAddress() {
+        try {
+            // Traversal Network interface to get the first non-loopback and non-private address
+            Enumeration<NetworkInterface> enumeration = NetworkInterface.getNetworkInterfaces();
+            ArrayList<String> ipv4Result = new ArrayList<String>();
+            ArrayList<String> ipv6Result = new ArrayList<String>();
+            while (enumeration.hasMoreElements()) {
+                final NetworkInterface networkInterface = enumeration.nextElement();
+                final Enumeration<InetAddress> en = networkInterface.getInetAddresses();
+                while (en.hasMoreElements()) {
+                    final InetAddress address = en.nextElement();
+                    if (!address.isLoopbackAddress()) {
+                        if (address instanceof Inet6Address) {
+                            ipv6Result.add(normalizeHostAddress(address));
+                        } else {
+                            ipv4Result.add(normalizeHostAddress(address));
+                        }
+                    }
+                }
+            }
+
+            // prefer ipv4
+            if (!ipv4Result.isEmpty()) {
+                for (String ip : ipv4Result) {
+                    if (ip.startsWith("127.0") || ip.startsWith("192.168")) {
+                        continue;
+                    }
+
+                    return ip;
+                }
+
+                return ipv4Result.get(ipv4Result.size() - 1);
+            } else if (!ipv6Result.isEmpty()) {
+                return ipv6Result.get(0);
+            }
+            //If failed to find,fall back to localhost
+            final InetAddress localHost = InetAddress.getLocalHost();
+            return normalizeHostAddress(localHost);
+        } catch (Exception e) {
+        }
+
+        return null;
+    }
+
+    public static String normalizeHostAddress(final InetAddress localHost) {
+        if (localHost instanceof Inet6Address) {
+            return "[" + localHost.getHostAddress() + "]";
+        } else {
+            return localHost.getHostAddress();
+        }
+    }
+
+    public static SocketAddress string2SocketAddress(final String addr) {
+        String[] s = addr.split(":");
+        InetSocketAddress isa = new InetSocketAddress(s[0], Integer.parseInt(s[1]));
+        return isa;
+    }
+
+    public static String socketAddress2String(final SocketAddress addr) {
+        StringBuilder sb = new StringBuilder();
+        InetSocketAddress inetSocketAddress = (InetSocketAddress) addr;
+        sb.append(inetSocketAddress.getAddress().getHostAddress());
+        sb.append(":");
+        sb.append(inetSocketAddress.getPort());
+        return sb.toString();
+    }
+
+    public static String parseChannelRemoteAddr(final Channel channel) {
+        if (null == channel) {
+            return "";
+        }
+        SocketAddress remote = channel.remoteAddress();
+        final String addr = remote != null ? remote.toString() : "";
+
+        if (addr.length() > 0) {
+            int index = addr.lastIndexOf("/");
+            if (index >= 0) {
+                return addr.substring(index + 1);
+            }
+
+            return addr;
+        }
+
+        return "";
+    }
+
+    public static String parseSocketAddressAddr(SocketAddress socketAddress) {
+        if (socketAddress != null) {
+            final String addr = socketAddress.toString();
+
+            if (addr.length() > 0) {
+                return addr.startsWith("/") ? addr.substring(1) : addr;
+            }
+        }
+        return "";
+    }
 }

+ 21 - 6
src/main/java/com/its/api/xnettcp/client/NettyTcpClient.java

@@ -22,18 +22,33 @@ public class NettyTcpClient implements Callable<Object> {
     private final String ipAddress;
     private final int    port;
     private final int    reconnectTime;
-    private final NettyTcpClientBootstrapFactory bootstrapFactory;
-    private Channel channel;
+    private final NettyTcpClientVdsBootstrapFactory bootstrapFactory;
+    private Channel channel = null;
+    private Bootstrap clientBootstrap = null;
+    private NettyTcpClientConnectListener connectListener = null;
+    private NettyTcpClientCloseListener closeListener = null;
 
     @Override
     public Object call() throws Exception {
         log.info("NettyTcpClient start: {}, {}", this.ipAddress, this.port);
         try {
-            Bootstrap clientBootstrap = this.bootstrapFactory.createBootstrap();
-            ChannelFuture connectChannelFuture = clientBootstrap.connect(new InetSocketAddress(this.ipAddress, this.port));
-            this.channel = connectChannelFuture.addListener(new NettyTcpClientConnectListener(this))
-                    .channel().closeFuture().addListener(new NettyTcpClientCloseListener(this))
+            if (this.clientBootstrap == null) {
+                this.clientBootstrap = this.bootstrapFactory.createBootstrap();
+            }
+            if (this.connectListener == null) {
+                this.connectListener = new NettyTcpClientConnectListener(this);
+            }
+            if (this.closeListener == null) {
+                this.closeListener = new NettyTcpClientCloseListener(this);
+            }
+            ChannelFuture channelFuture = this.clientBootstrap.connect(new InetSocketAddress(this.ipAddress, this.port));
+            this.channel = channelFuture
+                    .addListener(this.connectListener)
+                    .channel()
+                    .closeFuture()
+                    .addListener(this.closeListener)
                     .channel();
+            //this.bootstrapFactory.addChannelFuture(channelFuture);
         } catch (Exception e) {
             log.error("Exception: {}", e.getMessage());
             throw e;

+ 19 - 10
src/main/java/com/its/api/xnettcp/client/NettyTcpClientBootstrapFactory.java → src/main/java/com/its/api/xnettcp/client/NettyTcpClientVdsBootstrapFactory.java

@@ -5,6 +5,7 @@ import com.its.api.xnettcp.client.codec.NettyTcpClientEncoder;
 import com.its.api.xnettcp.client.handler.NettyTcpClientIdleHandler;
 import com.its.api.xnettcp.client.handler.NettyTcpClientInboundHandler;
 import io.netty.bootstrap.Bootstrap;
+import io.netty.channel.ChannelFuture;
 import io.netty.channel.ChannelInitializer;
 import io.netty.channel.ChannelOption;
 import io.netty.channel.EventLoopGroup;
@@ -18,20 +19,24 @@ import java.util.concurrent.TimeUnit;
 
 @Slf4j
 @RequiredArgsConstructor
-public class NettyTcpClientBootstrapFactory {
+public class NettyTcpClientVdsBootstrapFactory {
 
     private final int workerThread;
     private final int connectTimeout;
+    private EventLoopGroup nioEventLoopGroup = null;
+    //private List<ChannelFuture> channelFutures = new ArrayList<>();
 
-    public Bootstrap createBootstrap() throws Exception {
-
-        EventLoopGroup nioEventLoopGroup = new NioEventLoopGroup(this.workerThread);
+    public Bootstrap createBootstrap() {
+        if (this.nioEventLoopGroup == null) {
+            this.nioEventLoopGroup = new NioEventLoopGroup(this.workerThread);
+        }
         Bootstrap bootstrap = new Bootstrap();
+        bootstrap.group(this.nioEventLoopGroup);
+
         bootstrap.channel(NioSocketChannel.class);
-        bootstrap.group(nioEventLoopGroup);
         bootstrap.option(ChannelOption.AUTO_READ, true);
         bootstrap.option(ChannelOption.TCP_NODELAY, true);
-        bootstrap.option(ChannelOption.SO_KEEPALIVE, false);
+        bootstrap.option(ChannelOption.SO_KEEPALIVE, true);//false);
         bootstrap.option(ChannelOption.SO_RCVBUF, 8192);
         bootstrap.option(ChannelOption.SO_SNDBUF, 8192);
         bootstrap.option(ChannelOption.SO_KEEPALIVE, false);
@@ -41,13 +46,17 @@ public class NettyTcpClientBootstrapFactory {
         bootstrap.handler(new ChannelInitializer<SocketChannel>() {
             @Override
             public void initChannel(SocketChannel ch) throws Exception {
-                ch.pipeline().addLast("tcpClientIdleHandler", new NettyTcpClientIdleHandler(0, 0, 0, TimeUnit.SECONDS));
-                ch.pipeline().addLast("tcpClientEncoder",        new NettyTcpClientEncoder());            // Encoding handler
-                ch.pipeline().addLast("tcpClientDecoder",        new NettyTcpClientDecoder());            // Decoding handler
-                ch.pipeline().addLast("tcpClientInboundHandler", new NettyTcpClientInboundHandler());    // Packet Inbound handler
+                ch.pipeline().addLast("vdsClientIdleHandler",    new NettyTcpClientIdleHandler(0, 0, 0, TimeUnit.SECONDS));
+                ch.pipeline().addLast("vdsClientEncoder",        new NettyTcpClientEncoder());            // Encoding handler
+                ch.pipeline().addLast("vdsClientDecoder",        new NettyTcpClientDecoder());            // Decoding handler
+                ch.pipeline().addLast("vdsClientInboundHandler", new NettyTcpClientInboundHandler());     // Packet Inbound handler
             }
         });
 
         return bootstrap;
     }
+
+    public void addChannelFuture(ChannelFuture future) {
+        //this.channelFutures.add(future);
+    }
 }

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

@@ -14,9 +14,15 @@ public class NettyTcpClientCloseListener implements ChannelFutureListener {
 
     private final NettyTcpClient client;
 
+    /**
+     * 채널이 종료(close) 되었을 때 발생하는 이벤트 핸들러
+     * @param channelFuture
+     * @throws Exception
+     */
     @Override
     public void operationComplete(ChannelFuture channelFuture) throws Exception {
         log.error("NettyTcpClientCloseListener: {}", channelFuture.channel().toString());
+        // 채널이 종료되었으므로 재 연결 스케쥴을 등록한다.
         channelFuture.channel().close();
         channelFuture.channel().eventLoop().schedule(this.client, this.client.getReconnectTime(), TimeUnit.SECONDS);
     }

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

@@ -12,9 +12,16 @@ public class NettyTcpClientConnectListener implements ChannelFutureListener {
 
     private final NettyTcpClient client;
 
+    /**
+     * 최초 서버와 접속이 실패할 경우 이벤트 핸들러
+     * @param channelFuture
+     * @throws Exception
+     */
     @Override
     public void operationComplete(ChannelFuture channelFuture) throws Exception {
         if (!channelFuture.isSuccess()) {
+            // 연결이 안되었으므로 채널을 close 한다.
+            // channel 을 close 하면 NettyTcpClientCloseListener 의 이벤트가 발생한다.
             log.error("NettyTcpClientConnectListener:  !SUCCESS, {}, cause,{}", channelFuture.channel().toString(), channelFuture.cause().toString());
             channelFuture.channel().close();
             //channelFuture.channel().eventLoop().schedule(this.client, this.client.getReconnectTime(), TimeUnit.SECONDS);

+ 6 - 2
src/main/java/com/its/api/xnettcp/client/service/VdsCommClientService.java

@@ -4,7 +4,7 @@ import com.its.api.config.VdsServerConfig;
 import com.its.api.its.global.UnitSystManager;
 import com.its.api.its.model.entity.unit.TbUnitSyst;
 import com.its.api.xnettcp.client.NettyTcpClient;
-import com.its.api.xnettcp.client.NettyTcpClientBootstrapFactory;
+import com.its.api.xnettcp.client.NettyTcpClientVdsBootstrapFactory;
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -43,7 +43,11 @@ public class VdsCommClientService {
         }
         log.info("{}", this.vdsServerConfig);
 
-        this.vdsClient = new NettyTcpClient(vdsServerConfig.getIpAddress(), vdsServerConfig.getPort(), vdsServerConfig.getReconnectTime(), new NettyTcpClientBootstrapFactory(1, 5));
+        this.vdsClient = new NettyTcpClient(
+                this.vdsServerConfig.getIpAddress(),
+                this.vdsServerConfig.getPort(),
+                this.vdsServerConfig.getReconnectTime(),
+                new NettyTcpClientVdsBootstrapFactory(1, 5));
         this.clientTasks.add(this.vdsClient);
         try {
             List<Future<Object>> futures = this.executorService.invokeAll(this.clientTasks);