Эх сурвалжийг харах

add esb vms simple message send protocol

shjung 2 жил өмнө
parent
commit
68db157bfa
32 өөрчлөгдсөн 1141 нэмэгдсэн , 42 устгасан
  1. 3 3
      conf/debug.properties
  2. 53 0
      src/main/java/com/its/app/utils/ItsUtils.java
  3. 46 2
      src/main/java/com/its/app/utils/SysUtils.java
  4. 38 0
      src/main/java/com/its/vms/api/controller/EsbVmsController.java
  5. 2 0
      src/main/java/com/its/vms/api/controller/VmsControlController.java
  6. 1 0
      src/main/java/com/its/vms/config/ApplicationConfig.java
  7. 2 0
      src/main/java/com/its/vms/config/CommunicationConfig.java
  8. 5 3
      src/main/java/com/its/vms/config/SwaggerConfig.java
  9. 19 0
      src/main/java/com/its/vms/dao/mapper/EsbVmsMapper.java
  10. 178 0
      src/main/java/com/its/vms/dto/TbEsbVmsShortMsgDto.java
  11. 18 0
      src/main/java/com/its/vms/entity/NewIdSeq.java
  12. 66 0
      src/main/java/com/its/vms/entity/TbEsbVmsShortMsg.java
  13. 26 0
      src/main/java/com/its/vms/entity/TbEsbVmsShortMsgResult.java
  14. 106 0
      src/main/java/com/its/vms/esb/client/EsbVmsTcpClient.java
  15. 32 0
      src/main/java/com/its/vms/esb/protocol/EsbFrameHead.java
  16. 18 0
      src/main/java/com/its/vms/esb/protocol/EsbFramePacket.java
  17. 55 0
      src/main/java/com/its/vms/esb/protocol/EsbFrameTail.java
  18. 83 0
      src/main/java/com/its/vms/esb/protocol/EsbReqVmsShortMsg.java
  19. 150 0
      src/main/java/com/its/vms/esb/service/EsbVmsTcpService.java
  20. 31 0
      src/main/java/com/its/vms/scheduler/SchedulerTask.java
  21. 7 0
      src/main/java/com/its/vms/service/UnitSystService.java
  22. 3 1
      src/main/java/com/its/vms/service/VmsManageService.java
  23. 2 1
      src/main/java/com/its/vms/ui/SubUI.java
  24. 9 7
      src/main/resources/application.yml
  25. 95 0
      src/main/resources/mybatis/mapper/EsbVmsMapper.xml
  26. 1 1
      src/main/resources/mybatis/mapper/VmsAtmpMapper.xml
  27. 13 13
      src/main/resources/mybatis/mapper/VmsCtlrMapper.xml
  28. 1 1
      src/main/resources/mybatis/mapper/VmsFormMapper.xml
  29. 2 2
      src/main/resources/mybatis/mapper/VmsIfscMapper.xml
  30. 3 3
      src/main/resources/mybatis/mapper/VmsManageMapper.xml
  31. 5 5
      src/main/resources/mybatis/mapper/VmsSymbMapper.xml
  32. 68 0
      src/test/java/com/its/app/VmsCommServerApplicationTests.java

+ 3 - 3
conf/debug.properties

@@ -1,5 +1,5 @@
 #system debug setting configuration...
-#Fri Aug 18 09:22:19 KST 2023
-packet-info=10005
-packet-dump=x
+#Tue Aug 22 14:44:54 KST 2023
+packet-info=1001
+packet-dump=1001
 system-debug=true

+ 53 - 0
src/main/java/com/its/app/utils/ItsUtils.java

@@ -408,4 +408,57 @@ public final class ItsUtils
 		return Integer.parseInt(strValue);
 	}
 
+	/**
+	 * 바이너리 문자열을 short 크기에 맞춰 문자열을 처리한다.
+	 * @param binary
+	 * @return
+	 */
+	public static String shortToBinaryString(String binary) {
+		String result = binary;
+		if (result.length() > 16) {
+			return result.substring(16, 32);
+		}
+		if (binary.length() < 16) {
+			int cnt = 16 - binary.length();
+			String tmp = "";
+			for (int ii = 0; ii < cnt; ii++) {
+				tmp += "0";
+			}
+			return tmp + binary;
+		}
+		return binary;
+	}
+
+	/**
+	 * 주어진 값에 대한 2의 보수 값을 리턴한다.(2s complement)
+	 * @param value
+	 * @return
+	 */
+	public static short orgToTwoComplement(short value) {
+		/**
+		 * 원천값의 보수값을 구한다.(1s complement)
+		 */
+		short result = (short) ~value;
+
+		/**
+		 * 원천값의 보수값에 1의 값을 더한다.(2s complement)
+		 */
+		return (short) (result + 1);
+	}
+
+	/**
+	 * 2의 보수값(2s complement)을 원래의 값으로 변환한다.
+	 * @param value
+	 * @return
+	 */
+	public static short twoComplementToOrg(short value) {
+		/**
+		 * 원천값에서 1의 값을 뺀다
+		 */
+		short result = (short)(value - 1);
+		/**
+		 * 1의 값을 뺀값에 대한 보수값을 리턴한다.
+		 */
+		return (short) ~result;
+	}
 }

+ 46 - 2
src/main/java/com/its/app/utils/SysUtils.java

@@ -120,8 +120,42 @@ public final class SysUtils
 		return sb.toString();
 	}
 
-	public static String byteArrayToHex(byte[] AData)
-	{
+	public static String byteArrayToHex(byte[] AData) {
+		if ((AData == null) || (AData.length == 0)) {
+			return "";
+		}
+
+		int ALen = AData.length;
+		int line = ALen / 16;
+		int pos;
+
+		StringBuffer sb = new StringBuffer((ALen*3)+line);
+		sb.append("\r\n");
+		for (int ii = 0; ii < ALen; ii += 16)
+		{
+			for (int jj = 0; jj < 16; jj++) {
+				pos = ii + jj;
+				if (pos < ALen) {
+					String hexNumber = "0" + Integer.toHexString(0xFF & AData[pos]).toUpperCase();
+					sb.append(hexNumber.substring(hexNumber.length() - 2));
+					sb.append(" ");
+				}
+				else {
+					break;
+				}
+			}
+			sb.append("\r\n");
+		}
+		return sb.toString();
+	}
+
+	public static boolean isPrint(int c) {
+		if ( c >= 0x20 && c <= 0x7e )
+			return true;
+		return false;
+	}
+
+	public static String byteArrayToHexAscii(byte[] AData) {
 		if ((AData == null) || (AData.length == 0)) {
 			return "";
 		}
@@ -134,17 +168,27 @@ public final class SysUtils
 		sb.append("\r\n");
 		for (int ii = 0; ii < ALen; ii += 16)
 		{
+			String ascii = "";
 			for (int jj = 0; jj < 16; jj++) {
 				pos = ii + jj;
 				if (pos < ALen) {
 					String hexNumber = "0" + Integer.toHexString(0xFF & AData[pos]).toUpperCase();
 					sb.append(hexNumber.substring(hexNumber.length() - 2));
 					sb.append(" ");
+					int c = 0xFF & AData[pos];
+					if (isPrint(c)) {
+						ascii += String.format("%c", c);
+					}
+					else {
+						ascii += ".";
+					}
 				}
 				else {
 					break;
 				}
 			}
+			sb.append("      ;");
+			sb.append(ascii);
 			sb.append("\r\n");
 		}
 		return sb.toString();

+ 38 - 0
src/main/java/com/its/vms/api/controller/EsbVmsController.java

@@ -0,0 +1,38 @@
+package com.its.vms.api.controller;
+
+import com.its.vms.dto.TbEsbVmsShortMsgDto;
+import com.its.vms.esb.service.EsbVmsTcpService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.validation.Valid;
+
+@Slf4j
+@Api(tags = "1.VMS-1.ESB 연계")
+@Validated
+@RestController
+@RequiredArgsConstructor
+@RequestMapping("/api/vms/esb")
+public class EsbVmsController {
+
+    private final EsbVmsTcpService esbService;
+
+    @ApiOperation(value = "ESB VMS 단문 메시지 즉시 전송", response = TbEsbVmsShortMsgDto.TbEsbVmsShortMsgReqRes.class)
+    @PostMapping(value = "/send/short-msg", produces = {"application/json; charset=utf8"})
+    public TbEsbVmsShortMsgDto.TbEsbVmsShortMsgReqRes sendVmsShortMsg(
+            @ApiParam(name = "req", value = "단문 메시지 정보", example = "", required = true)
+            @RequestBody @Valid final TbEsbVmsShortMsgDto.TbEsbVmsShortMsgReq req,
+            HttpServletRequest request) {
+        return this.esbService.sendShortMsg(req);
+    }
+
+}

+ 2 - 0
src/main/java/com/its/vms/api/controller/VmsControlController.java

@@ -2,6 +2,7 @@ package com.its.vms.api.controller;
 
 import com.its.vms.api.dto.VmsControlDto;
 import com.its.vms.api.service.VmsControlService;
+import com.its.vms.esb.service.EsbVmsTcpService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
@@ -22,6 +23,7 @@ import javax.validation.Valid;
 public class VmsControlController {
 
     private final VmsControlService service;
+    private final EsbVmsTcpService esbService;
 
     @ApiOperation(value = "VMS 제어기 리셋", response = VmsControlDto.VmsControlRes.class)
     @PostMapping(value = "/reset/{ctlrNmbr}", produces = {"application/json; charset=utf8"})

+ 1 - 0
src/main/java/com/its/vms/config/ApplicationConfig.java

@@ -77,6 +77,7 @@ public class ApplicationConfig {
     private float fontSizeRatio = 1.35f;
     private boolean checkNewForm = true;
     private boolean downloadBitmapForm = false;
+    private boolean useParking = false;
 
     @PostConstruct
     private void init() {

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

@@ -40,6 +40,8 @@ public class CommunicationConfig {
     private boolean subscriptionStatus = true;
     private int subscriptionStatusCycle = 30;
 
+    private String esbServer;
+    private int esbPort;
 
     @PostConstruct
     private void init() {

+ 5 - 3
src/main/java/com/its/vms/config/SwaggerConfig.java

@@ -5,7 +5,6 @@ import org.springframework.context.annotation.Configuration;
 import org.springframework.http.HttpHeaders;
 import springfox.documentation.builders.ApiInfoBuilder;
 import springfox.documentation.builders.ParameterBuilder;
-import springfox.documentation.builders.PathSelectors;
 import springfox.documentation.builders.RequestHandlerSelectors;
 import springfox.documentation.schema.ModelRef;
 import springfox.documentation.service.ApiInfo;
@@ -17,6 +16,8 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2;
 import java.util.ArrayList;
 import java.util.List;
 
+import static springfox.documentation.builders.PathSelectors.regex;
+
 @Configuration
 @EnableSwagger2
 public class SwaggerConfig {
@@ -39,8 +40,9 @@ public class SwaggerConfig {
                 .apiInfo(this.apiInfo())
                 .select()
                 .apis(RequestHandlerSelectors.basePackage("com.its.vms.api.controller"))
-                .paths(PathSelectors.any())
-                //.paths(PathSelectors.ant("/api/**"))
+                //.paths(PathSelectors.any())
+                //.paths(PathSelectors.ant("/api/vms/control/**"))
+                .paths(regex("/api/vms/(control|esb)/.*"))
                 .build();
     }
 

+ 19 - 0
src/main/java/com/its/vms/dao/mapper/EsbVmsMapper.java

@@ -0,0 +1,19 @@
+package com.its.vms.dao.mapper;
+
+import com.its.vms.entity.NewIdSeq;
+import com.its.vms.entity.TbEsbVmsShortMsg;
+import com.its.vms.entity.TbEsbVmsShortMsgResult;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+@Mapper
+public interface EsbVmsMapper {
+
+    NewIdSeq selectNextMsgId();
+    List<TbEsbVmsShortMsg> selectVmsShortMsg();
+    int insertVmsShortMsg(@Param("obj") TbEsbVmsShortMsg obj);
+    int updateVmsShortMsgResult(@Param("obj") TbEsbVmsShortMsgResult obj);
+
+}

+ 178 - 0
src/main/java/com/its/vms/dto/TbEsbVmsShortMsgDto.java

@@ -0,0 +1,178 @@
+package com.its.vms.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.its.vms.entity.TbEsbVmsShortMsg;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.*;
+
+import javax.validation.constraints.PositiveOrZero;
+import javax.validation.constraints.Size;
+import java.io.Serializable;
+
+/**
+ * ESB 연계 긴급 단문메시지 전송 DTO Class
+ */
+@Data
+@Builder
+@ApiModel("TbEsbVmsShortMsgDto(ESB 연계 긴급 단문메시지 전송)")
+public class TbEsbVmsShortMsgDto implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private Long msgId;
+    private String rgstDt;
+    private Integer msgTp;
+    private String dsplStrtDt;
+    private String dsplEndDt;
+    private Integer fontNameCd;
+    private Integer fontColrCd;
+    private Integer fontSize;
+    private Integer fontBold;
+    private String dsplMsgLn1;
+    private String dsplMsgLn2;
+    private String dsplMsgLn3;
+    private String combineId;
+    private String userId;
+    private String sendYn;
+    private String sendDt;
+    private Long tryCnt;
+    private String lastTryDt;
+
+    @ApiModel("TbEsbVmsShortMsgReq(ESB 연계 긴급 단문메시지 전송 요청)")
+    @Getter
+    @Setter
+    @ToString
+    @NoArgsConstructor//(access = AccessLevel.PROTECTED)
+    public static class TbEsbVmsShortMsgReq {
+        @ApiModelProperty("메시지유형(1:1단 메시지, 2:2단 메시지, 3:3단 메시지), 1단 메시지만 사용함, Nullable = Y, NUMBER(1)")  // Y NUMBER(1)
+        @JsonProperty("msg_tp")
+        @PositiveOrZero
+        private Integer msgTp;
+
+        @ApiModelProperty("표출 시작시각, 예비, Nullable = Y, VARCHAR(14)")  // Y VARCHAR(14)
+        @JsonProperty("dspl_strt_dt")
+        @Size(min=14, max=14)
+        private String dsplStrtDt;
+
+        @ApiModelProperty("표출 종료시각, 예비, Nullable = Y, VARCHAR(14)")  // Y VARCHAR(14)
+        @JsonProperty("dspl_end_dt")
+        @Size(min=14, max=14)
+        private String dsplEndDt;
+
+        @ApiModelProperty("글자유형(0:굴림체, 1:바탕체), Nullable = Y, NUMBER(1)")  // Y NUMBER(1)
+        @JsonProperty("font_name_cd")
+        @PositiveOrZero
+        private Integer fontNameCd;
+
+        @ApiModelProperty("글자색상(0:흑색-Black, 1:적색-Red, 2:라임-Lime, 3:황색-Yellow), Nullable = Y, NUMBER(1)")  // Y NUMBER(1)
+        @JsonProperty("font_colr_cd")
+        @PositiveOrZero
+        private Integer fontColrCd;
+
+        @ApiModelProperty("글자크기(픽셀단위:16, 24, 32, 48 등), Nullable = Y, NUMBER(3)")  // Y NUMBER(3)
+        @JsonProperty("font_size")
+        @PositiveOrZero
+        private Integer fontSize;
+
+        @ApiModelProperty("글꼴 방식(0:Normal,1:Bold), 예비, Nullable = Y, NUMBER(1)")  // Y NUMBER(1)
+        @JsonProperty("font_bold")
+        @PositiveOrZero
+        private Integer fontBold;
+
+        @ApiModelProperty("1단 문자열, Nullable = N, VARCHAR(50)")  // N VARCHAR(50)
+        @JsonProperty("dspl_msg_ln1")
+        @Size(min=1, max=50)
+        private String dsplMsgLn1;
+
+        @ApiModelProperty("2단 문자열, Nullable = Y, VARCHAR(50)")  // Y VARCHAR(50)
+        @JsonProperty("dspl_msg_ln2")
+        @Size(max=50)
+        private String dsplMsgLn2;
+
+        @ApiModelProperty("3단 문자열, Nullable = Y, VARCHAR(50)")  // Y VARCHAR(50)
+        @JsonProperty("dspl_msg_ln3")
+        @Size(max=50)
+        private String dsplMsgLn3;
+
+        @ApiModelProperty("통합플랫폼 ID, Nullable = N, VARCHAR(15)")  // N VARCHAR(15)
+        @JsonProperty("combine_id")
+        @Size(min=15, max=15)
+        private String combineId;
+
+        @ApiModelProperty("사용자 ID, Nullable = Y, VARCHAR(20)")  // Y VARCHAR(20)
+        @JsonProperty("user_id")
+        @Size(min=1, max=20)
+        private String userId;
+
+        @Builder
+        public TbEsbVmsShortMsgReq(Integer msg_tp, String dspl_strt_dt, String dspl_end_dt, Integer font_name_cd, Integer font_colr_cd, Integer font_size, Integer font_bold, String dspl_msg_ln1, String dspl_msg_ln2, String dspl_msg_ln3, String combine_id, String user_id) {
+            this.msgTp = msg_tp;
+            this.dsplStrtDt = dspl_strt_dt;
+            this.dsplEndDt = dspl_end_dt;
+            this.fontNameCd = font_name_cd;
+            this.fontColrCd = font_colr_cd;
+            this.fontSize = font_size;
+            this.fontBold = font_bold;
+            this.dsplMsgLn1 = dspl_msg_ln1;
+            this.dsplMsgLn2 = dspl_msg_ln2;
+            this.dsplMsgLn3 = dspl_msg_ln3;
+            this.combineId = combine_id;
+            this.userId = user_id;
+        }
+    }
+
+    @ApiModel("TbEsbVmsShortMsgReqRes(ESB 연계 긴급 단문메시지 전송 요청 응답)")
+    @Getter
+    @Setter
+    @ToString
+    @NoArgsConstructor//(access = AccessLevel.PROTECTED)
+    public static class TbEsbVmsShortMsgReqRes {
+
+        @ApiModelProperty("메시지 id")
+        @JsonProperty("msg_id")
+        private Long msgId;
+
+        @ApiModelProperty("제어결과(0: 성공, 기타: 오류")
+        @JsonProperty("error")
+        private Integer error;
+
+        @ApiModelProperty("제어결과메시지")
+        @JsonProperty("message")
+        private String message;
+
+        public void setResult(Integer error, String message) {
+            this.error = error;
+            this.message = message;
+        }
+        @Builder
+        public TbEsbVmsShortMsgReqRes(Long msgId, Integer error, String message) {
+            this.msgId = msgId;
+            this.error = error;
+            this.message = message;
+        }
+    }
+
+    public TbEsbVmsShortMsg toEntity() {
+        return TbEsbVmsShortMsg.builder()
+                .msgId(this.msgId)
+                .rgstDt(this.rgstDt)
+                .msgTp(this.msgTp)
+                .dsplStrtDt(this.dsplStrtDt)
+                .dsplEndDt(this.dsplEndDt)
+                .fontNameCd(this.fontNameCd)
+                .fontColrCd(this.fontColrCd)
+                .fontSize(this.fontSize)
+                .fontBold(this.fontBold)
+                .dsplMsgLn1(this.dsplMsgLn1)
+                .dsplMsgLn2(this.dsplMsgLn2)
+                .dsplMsgLn3(this.dsplMsgLn3)
+                .combineId(this.combineId)
+                .userId(this.userId)
+                .sendYn(this.sendYn)
+                .sendDt(this.sendDt)
+                .tryCnt(this.tryCnt)
+                .lastTryDt(this.lastTryDt)
+                .build();
+    }
+
+}

+ 18 - 0
src/main/java/com/its/vms/entity/NewIdSeq.java

@@ -0,0 +1,18 @@
+package com.its.vms.entity;
+
+import lombok.Builder;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * Long New ID DTO Class
+ */
+@Data
+@Builder
+public class NewIdSeq implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private Long id;
+
+}

+ 66 - 0
src/main/java/com/its/vms/entity/TbEsbVmsShortMsg.java

@@ -0,0 +1,66 @@
+package com.its.vms.entity;
+
+import com.its.vms.dto.TbEsbVmsShortMsgDto;
+import io.swagger.annotations.ApiModel;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * ESB 연계 긴급 단문메시지 전송 Entity Class
+ */
+@ApiModel("ESB 연계 긴급 단문메시지 전송")
+@Getter
+@Builder
+@NoArgsConstructor//(access = AccessLevel.PROTECTED)
+@AllArgsConstructor
+public class TbEsbVmsShortMsg implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private Long msgId;
+    private String rgstDt;
+    private Integer msgTp;
+    private String dsplStrtDt;
+    private String dsplEndDt;
+    private Integer fontNameCd;
+    private Integer fontColrCd;
+    private Integer fontSize;
+    private Integer fontBold;
+    private String dsplMsgLn1;
+    private String dsplMsgLn2;
+    private String dsplMsgLn3;
+    private String combineId;
+    private String userId;
+    private String sendYn;
+    private String sendDt;
+    private Long tryCnt;
+    private String lastTryDt;
+
+    public TbEsbVmsShortMsgDto toDto() {
+        return TbEsbVmsShortMsgDto.builder()
+                .msgId(this.msgId)
+                .rgstDt(this.rgstDt)
+                .msgTp(this.msgTp)
+                .dsplStrtDt(this.dsplStrtDt)
+                .dsplEndDt(this.dsplEndDt)
+                .fontNameCd(this.fontNameCd)
+                .fontColrCd(this.fontColrCd)
+                .fontSize(this.fontSize)
+                .fontBold(this.fontBold)
+                .dsplMsgLn1(this.dsplMsgLn1)
+                .dsplMsgLn2(this.dsplMsgLn2)
+                .dsplMsgLn3(this.dsplMsgLn3)
+                .combineId(this.combineId)
+                .userId(this.userId)
+                .sendYn(this.sendYn)
+                .sendDt(this.sendDt)
+                .tryCnt(this.tryCnt)
+                .lastTryDt(this.lastTryDt)
+                .build();
+    }
+
+
+}

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

@@ -0,0 +1,26 @@
+package com.its.vms.entity;
+
+import io.swagger.annotations.ApiModel;
+import lombok.*;
+
+import java.io.Serializable;
+
+/**
+ * ESB 연계 긴급 단문메시지 전송 Entity Class
+ */
+@ApiModel("ESB 연계 긴급 단문메시지 전송")
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor//(access = AccessLevel.PROTECTED)
+@AllArgsConstructor
+public class TbEsbVmsShortMsgResult implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private Long msgId;
+    private String sendYn;
+    private String sendDt;
+    private Long tryCnt;
+    private String lastTryDt;
+
+}

+ 106 - 0
src/main/java/com/its/vms/esb/client/EsbVmsTcpClient.java

@@ -0,0 +1,106 @@
+package com.its.vms.esb.client;
+
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.nio.ByteOrder;
+
+@Slf4j
+public class EsbVmsTcpClient {
+    public static final ByteOrder byteOrder = ByteOrder.BIG_ENDIAN;
+
+    /**
+     * 통신 서버와 통신 연결
+     * @param ipAddress
+     * @param port
+     * @param connTimeout
+     * @param readTimeout
+     * @return
+     * @throws IOException
+     */
+    public static Socket connectServer(String ipAddress, int port, int connTimeout, int readTimeout) throws IOException {
+        SocketAddress socketAddress = new InetSocketAddress(ipAddress, port);
+        Socket socket = null;
+        try {
+            socket = new Socket();
+            socket.setSoTimeout(readTimeout);            /* InputStream 에서 데이터읽을때의 timeout */
+            socket.connect(socketAddress, connTimeout);  /* socket 연결 자체에대한 timeout */
+        } catch (IOException e) {
+            String errMessage = "서버에 연결 할 수 없습니다.";
+            log.error("EsbVmsTcpClient.connectServer: {}::{}, {}", ipAddress, port, errMessage);
+            throw e;
+        }
+        return socket;
+    }
+
+    /**
+     * 연결 소켓 Close
+     * @param socket
+     * @param waitMillis
+     */
+    public static void closeSocket(Socket socket, int waitMillis) {
+        try {
+            if (socket != null) {
+                if (waitMillis > 0) {
+                    try {
+                        Thread.sleep(waitMillis);
+                    } catch (InterruptedException e) {
+                    }
+                }
+                socket.close();
+            }
+        } catch (IOException e) {
+        }
+    }
+
+    /**
+     * 소켓 입력 버퍼로 부터 데이터 길이만큼 읽어 온다
+     * @param socket
+     * @param buffSize
+     * @return
+     * @throws IOException
+     */
+    public static byte[] receiveBytes(Socket socket, int buffSize) throws IOException {
+        byte[] buffer;
+        int bytesRead = 0;
+        int readThisTime;
+        buffer = new byte[buffSize];
+        InputStream inStream = socket.getInputStream();
+        while (bytesRead < buffSize)
+        {
+            readThisTime = inStream.read(buffer, bytesRead, buffSize - bytesRead);
+            if (readThisTime == -1)
+            {
+                log.error("EsbVmsTcpClient.receiveBytes: {}, readThisTime: {}", socket, readThisTime);
+                throw new IOException("Socket.receive(): Socket closed unexpectedly");
+            }
+            bytesRead += readThisTime;
+        }
+        return buffer;
+    }
+
+    /**
+     * 소켓으로 데이터 전송
+     * @param socket
+     * @param data
+     * @return
+     */
+    public static boolean sendData(Socket socket, byte[] data) {
+        try {
+            OutputStream os = socket.getOutputStream();
+            os.write(data);
+            os.flush();
+        } catch (IOException e) {
+            String errMessage = "데이터 전송 오류";
+            log.error("EsbVmsTcpClient.sendData: {}, {}", socket, errMessage);
+            return false;
+        }
+        return true;
+    }
+
+}

+ 32 - 0
src/main/java/com/its/vms/esb/protocol/EsbFrameHead.java

@@ -0,0 +1,32 @@
+package com.its.vms.esb.protocol;
+
+import com.its.app.utils.SysUtils;
+import com.its.vms.esb.client.EsbVmsTcpClient;
+
+import java.io.Serializable;
+import java.nio.ByteBuffer;
+
+public class EsbFrameHead implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private final String id;          // 20 byte
+    private final String sendTime;    // 14 byte
+    //private int length;               // 4 byte
+
+    public EsbFrameHead() {
+        this.id = "TRGBG00600900VMS0001";
+        this.sendTime = SysUtils.getSysTime();
+    }
+
+    public ByteBuffer getByteBuffer(int length) {
+        ByteBuffer bf = ByteBuffer.allocate(38);
+        bf.order(EsbVmsTcpClient.byteOrder);
+
+        bf.put(this.id.getBytes());
+        bf.put(this.sendTime.getBytes());
+        bf.putInt(length);
+
+        return bf;
+    }
+
+}

+ 18 - 0
src/main/java/com/its/vms/esb/protocol/EsbFramePacket.java

@@ -0,0 +1,18 @@
+package com.its.vms.esb.protocol;
+
+import java.nio.ByteBuffer;
+
+public abstract class EsbFramePacket {
+
+    protected EsbFrameHead head;
+    protected EsbReqVmsShortMsg body;
+    protected EsbFrameTail tail;
+
+    EsbFramePacket() {
+        this.head = new EsbFrameHead();
+        this.tail = new EsbFrameTail();
+    }
+
+    public abstract ByteBuffer getByteBuffer();
+
+}

+ 55 - 0
src/main/java/com/its/vms/esb/protocol/EsbFrameTail.java

@@ -0,0 +1,55 @@
+package com.its.vms.esb.protocol;
+
+import java.io.Serializable;
+import java.nio.ByteBuffer;
+
+public class EsbFrameTail implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    //private short crc;
+
+    public short getCrc(ByteBuffer head, ByteBuffer body) {
+        byte[] headBytes = head.array();
+        byte[] bodyBytes = body.array();
+
+        short sum = 0;
+        for (byte b: headBytes) {
+            sum += b;
+        }
+
+        for (byte b: bodyBytes) {
+            sum += b;
+        }
+
+        short crc = (short) ~sum;
+        crc += 1;
+        return crc;
+    }
+
+    public static short getCrc(byte[] data) {
+        short sum = 0;
+        for (byte b: data) {
+            sum += b;
+        }
+
+        short crc = (short) ~sum;
+        crc += 1;
+        return crc;
+    }
+
+    public static byte[] hexToByteArray(String hex) {
+        if (hex == null || hex.length() == 0) {
+            return null;
+        }
+
+        if (hex.toString().length() % 2 == 1) {
+            hex = "0" + hex;
+        }
+        hex = hex.replaceAll(" ", "");
+        byte[] ba = new byte[hex.length() / 2];
+        for (int i = 0; i < ba.length; i++) {
+            ba[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16);
+        }
+        return ba;
+    }
+}

+ 83 - 0
src/main/java/com/its/vms/esb/protocol/EsbReqVmsShortMsg.java

@@ -0,0 +1,83 @@
+package com.its.vms.esb.protocol;
+
+import com.its.app.utils.SysUtils;
+import com.its.vms.esb.client.EsbVmsTcpClient;
+import lombok.extern.slf4j.Slf4j;
+
+import java.nio.ByteBuffer;
+
+@Slf4j
+public class EsbReqVmsShortMsg extends EsbFramePacket {
+
+    private static int esbPktNmbr = 1;
+
+    private final short pktNmbr;          // 2 byte
+    private final String facilityId;      // 15 byte
+    private final int fontTypeCd;         // 1 byte
+    private final int fontColrCd;         // 1 byte
+    private final int fontSize;           // 1 byte
+    private final short msgTxtLength;     // 2 byte
+    private final byte[] msgTxt;          // n byte
+
+    public static short getNextPktNmbr() {
+        short pktNmbr = (short)esbPktNmbr;
+        esbPktNmbr++;
+        if (esbPktNmbr > Short.MAX_VALUE) {
+            esbPktNmbr = 1;
+        }
+        return pktNmbr;
+    }
+
+    public EsbReqVmsShortMsg(String facilityId, int fontTypeCd, int fontColrCd, int fontSize, String msgTxt) {
+        super();
+        this.pktNmbr = getNextPktNmbr();
+        this.facilityId = facilityId;
+        this.fontTypeCd = fontTypeCd;
+        this.fontColrCd = fontColrCd;
+        this.fontSize = fontSize;
+        this.msgTxt = SysUtils.stringToByteArr(msgTxt);
+        this.msgTxtLength = (short)this.msgTxt.length;
+    }
+
+    @Override
+    public ByteBuffer getByteBuffer() {
+        // Body Buffer
+        int bodyLength = 22 + this.msgTxtLength;
+        ByteBuffer body = ByteBuffer.allocate(bodyLength);
+        body.order(EsbVmsTcpClient.byteOrder);
+
+        body.putShort(this.pktNmbr);
+        byte[] facilityIds = this.facilityId.getBytes();
+        if (facilityIds.length == 15) {
+            body.put(facilityIds);
+        }
+        else {
+            // 여기 들어오면 안된다.
+            int facilityIdSize = Math.min(facilityIds.length, 15);
+            byte[] newFacilityIds = new byte[15];
+            System.arraycopy(facilityIds, 0, newFacilityIds, 0, facilityIdSize);
+            body.put(newFacilityIds);
+        }
+        body.put((byte)(this.fontTypeCd & 0xFF));
+        body.put((byte)(this.fontColrCd & 0xFF));
+        body.put((byte)(this.fontSize & 0xFF));
+        body.putShort(this.msgTxtLength);
+        body.put(this.msgTxt);
+
+//        log.info("{}", SysUtils.byteArrayToHex(body.array()));
+
+        // Head Buffer
+        ByteBuffer head = this.head.getByteBuffer(bodyLength);
+//        log.info("{}", SysUtils.byteArrayToHex(head.array()));
+
+        // CRC
+        short crc = this.tail.getCrc(head, body);
+
+        ByteBuffer packet = ByteBuffer.allocate(head.capacity() + body.capacity() + 2);
+        packet.put(head.array());
+        packet.put(body.array());
+        packet.putShort(crc);
+        return packet;
+    }
+
+}

+ 150 - 0
src/main/java/com/its/vms/esb/service/EsbVmsTcpService.java

@@ -0,0 +1,150 @@
+package com.its.vms.esb.service;
+
+import com.its.app.utils.Elapsed;
+import com.its.app.utils.SysUtils;
+import com.its.vms.config.CommunicationConfig;
+import com.its.vms.dao.mapper.EsbVmsMapper;
+import com.its.vms.dto.TbEsbVmsShortMsgDto;
+import com.its.vms.entity.NewIdSeq;
+import com.its.vms.entity.TbEsbVmsShortMsg;
+import com.its.vms.entity.TbEsbVmsShortMsgResult;
+import com.its.vms.esb.client.EsbVmsTcpClient;
+import com.its.vms.esb.protocol.EsbReqVmsShortMsg;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.nio.ByteBuffer;
+import java.util.List;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class EsbVmsTcpService {
+
+    private final CommunicationConfig config;
+    private final EsbVmsMapper mapper;
+    private final int readTimeout = 5000;   // 밀리세컨드
+    private final int connTimeout = 5000;   // 밀리세컨즈
+
+    /**
+     * ESB 서버로 VMS 단문 메시지를 전송한다.
+     * @param req
+     * @return
+     */
+    public TbEsbVmsShortMsgDto.TbEsbVmsShortMsgReqRes sendShortMsg(TbEsbVmsShortMsgDto.TbEsbVmsShortMsgReq req) {
+        TbEsbVmsShortMsgDto.TbEsbVmsShortMsgReqRes result = new TbEsbVmsShortMsgDto.TbEsbVmsShortMsgReqRes(0L, 0, "success");
+        EsbReqVmsShortMsg shortMsg = new EsbReqVmsShortMsg(req.getCombineId(), req.getFontNameCd(), req.getFontColrCd(), req.getFontSize(), req.getDsplMsgLn1());
+        ByteBuffer cmdBuffer = shortMsg.getByteBuffer();
+
+        String ipAddress = this.config.getEsbServer();
+        int port = this.config.getEsbPort();
+
+        Socket socket = null;
+        try {
+            socket = EsbVmsTcpClient.connectServer(ipAddress, port, this.connTimeout, this.readTimeout);
+            if (EsbVmsTcpClient.sendData(socket, cmdBuffer.array())) {
+            }
+            else {
+                result.setResult(3, "ESB VMS 연계 서버에 단순 메시지 표출 명령을 정상적으로 전송하지 못하였습니다.");
+            }
+        } catch (IOException e) {
+            log.error("EsbVmsTcpService.sendShortMsg: {}, {}, IOException", ipAddress, port);
+            String errMsg = "[ESB VMS 연계 서버: " + ipAddress + "." + port + "]";
+            result.setResult(2, "ESB VMS 연계 서버와 통신이 실패하였습니다.\r\n" + errMsg);
+            return result;
+        }
+        finally {
+            String sysDate = SysUtils.getSysTime();
+            NewIdSeq idDto = this.mapper.selectNextMsgId();
+            TbEsbVmsShortMsg data = TbEsbVmsShortMsg.builder()
+                    .msgId(idDto.getId())
+                    .rgstDt(sysDate)
+                    .msgTp(req.getMsgTp())
+                    .dsplStrtDt(req.getDsplStrtDt())
+                    .dsplEndDt(req.getDsplEndDt())
+                    .fontNameCd(req.getFontNameCd())
+                    .fontColrCd(req.getFontColrCd())
+                    .fontSize(req.getFontSize())
+                    .fontBold(req.getFontBold())
+                    .dsplMsgLn1(req.getDsplMsgLn1())
+                    .dsplMsgLn2(req.getDsplMsgLn2())
+                    .dsplMsgLn3(req.getDsplMsgLn3())
+                    .combineId(req.getCombineId())
+                    .userId(req.getUserId())
+                    .sendYn(result.getError() == 0 ? "Y" : "N")
+                    .sendDt(result.getError() == 0 ? sysDate : "")
+                    .tryCnt(1L)
+                    .lastTryDt(sysDate)
+                    .build();
+
+            this.mapper.insertVmsShortMsg(data);
+            EsbVmsTcpClient.closeSocket(socket, 0);
+        }
+        return result;
+    }
+
+    public void loadVmsShorMsg() {
+        Elapsed elapsed = new Elapsed();
+        Socket socket = null;
+        try {
+            List<TbEsbVmsShortMsg> result  = this.mapper.selectVmsShortMsg();
+            log.info("EsbVmsTcpService.loadVmsShorMsg: {} EA", result.size());
+            if (result.isEmpty()) {
+                return;
+            }
+
+            String ipAddress = this.config.getEsbServer();
+            int port = this.config.getEsbPort();
+
+            try {
+                socket = EsbVmsTcpClient.connectServer(ipAddress, port, this.connTimeout, this.readTimeout);
+            } catch (IOException e) {
+                log.error("EsbVmsTcpService.loadVmsShorMsg: ESB VMS 연계 서버와 통신이 실패하였습니다. [ESB VMS 연계 서버: {}::{}", ipAddress, port);
+
+                String sysDate = SysUtils.getSysTime();
+                for (TbEsbVmsShortMsg data : result) {
+                    TbEsbVmsShortMsgResult sendResult = TbEsbVmsShortMsgResult.builder()
+                            .msgId(data.getMsgId())
+                            .sendYn("N")
+                            .sendDt(sysDate)
+                            .tryCnt(data.getTryCnt()+1)
+                            .lastTryDt("")
+                            .build();
+                    this.mapper.updateVmsShortMsgResult(sendResult);
+                }
+                return;
+            }
+
+            for (TbEsbVmsShortMsg data : result) {
+                EsbReqVmsShortMsg shortMsg = new EsbReqVmsShortMsg(data.getCombineId(), data.getFontNameCd(), data.getFontColrCd(), data.getFontSize(), data.getDsplMsgLn1());
+                ByteBuffer cmdBuffer = shortMsg.getByteBuffer();
+
+                String sysDate = SysUtils.getSysTime();
+                TbEsbVmsShortMsgResult sendResult = TbEsbVmsShortMsgResult.builder()
+                        .msgId(data.getMsgId())
+                        .sendYn("Y")
+                        .sendDt(sysDate)
+                        .tryCnt(data.getTryCnt()+1)
+                        .lastTryDt(sysDate)
+                        .build();
+
+                if (!EsbVmsTcpClient.sendData(socket, cmdBuffer.array())) {
+                    sendResult.setSendYn("N");
+                    sendResult.setSendDt("");
+                }
+                this.mapper.updateVmsShortMsgResult(sendResult);
+            }
+        }
+        catch (Exception e) {
+            log.error("EsbVmsTcpService.loadVmsShorMsg: {}.", e.getMessage());
+        }
+        finally {
+            EsbVmsTcpClient.closeSocket(socket, 0);
+            log.info("EsbVmsTcpService.loadVmsShorMsg: {} ms.", elapsed.milliSeconds());
+        }
+    }
+
+}

+ 31 - 0
src/main/java/com/its/vms/scheduler/SchedulerTask.java

@@ -4,6 +4,7 @@ import com.its.app.AppUtils;
 import com.its.app.utils.Elapsed;
 import com.its.vms.config.ApplicationConfig;
 import com.its.vms.config.DebugConfig;
+import com.its.vms.esb.service.EsbVmsTcpService;
 import com.its.vms.service.*;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -25,6 +26,7 @@ public class SchedulerTask {
     private final VmsManageService vmsManageService;
     private final VmsDisplayOnOffService displayOnOffService;
     private final VmsSymbService symbService;
+    private final EsbVmsTcpService esbVmsTcpService;
     private final AppRepositoryService repoService;
 
     @PreDestroy
@@ -34,6 +36,9 @@ public class SchedulerTask {
         debug.saveDebugInfo();
     }
 
+    /**
+     * 프로세스와 제어기 상태정보를 업데이트 한다.
+     */
     @Scheduled(cron = "5 * * * * *")  // 1분주기 작업 실행
     public void scheduleUnitSystStts() {
         if (!this.config.isStartSchedule()) {
@@ -48,6 +53,9 @@ public class SchedulerTask {
         log.info("scheduleUnitSystStts: ..end. {} ms. {}", elapsed.milliSeconds(), Thread.currentThread().getName());
     }
 
+    /**
+     * 제어기의 상태정보 제어기로 전송한다.
+     */
     @Scheduled(cron = "8 * * * * *")  // 1분주기 작업 실행
     public void scheduleVmsStatusRequest() {
         if (!this.config.isStartSchedule()) {
@@ -59,6 +67,9 @@ public class SchedulerTask {
         log.info("scheduleVmsStatusRequest: ..end. {} ms. {}", elapsed.milliSeconds(), Thread.currentThread().getName());
     }
 
+    /**
+     * 제어기 전광판 On/Off 시각에 명령을 전송한다.
+     */
     //@Scheduled(cron = "${application.atmp.crontab:40 0/30 * * * *}")
     @Scheduled(cron = "15 * * * * *")  // 1분주기 작업 실행
     public void scheduleVmsOnOffControl() {
@@ -71,6 +82,9 @@ public class SchedulerTask {
         log.info("scheduleVmsOnOffControl: ..end. {} ms. {}", elapsed.milliSeconds(), Thread.currentThread().getName());
     }
 
+    /**
+     * 정주기 VMS 다운로드 메시지를 생성하고 제어기로 다운로드 한다.
+     */
     @Scheduled(cron = "30 0/5 * * * *")    // 정주기 5분 30초에 스케쥴 실행
     public void scheduleVmsFormDownload() {
         if (!this.config.isStartSchedule()) {
@@ -83,6 +97,9 @@ public class SchedulerTask {
         log.info("scheduleVmsFormDownload..: ..end. {} ms. {}", elapsed.milliSeconds(), Thread.currentThread().getName());
     }
 
+    /**
+     * VMS 심벌 다운로드 정보를 조회하여 제어기로 다운로드 한다.
+     */
     @Scheduled(cron = "10 3,8,13,18,23,28,33,38,43,48,53,58 * * * *")  // 5분주기 작업 실행
     public void scheduleVmsDnldSymb() {
         if (!this.config.isStartSchedule()) {
@@ -94,4 +111,18 @@ public class SchedulerTask {
         log.info("scheduleVmsDnldSymb: ..end. {} ms. {}", elapsed.milliSeconds(), Thread.currentThread().getName());
     }
 
+    /**
+     * ESB VMS 연계 서버에 전송할 단문 메시지가 존재하는 지 1분 주기로 체크하여 데이터를 전송한다.
+     */
+    @Scheduled(cron = "15 * * * * *")  // 1분주기 작업 실행
+    public void scheduleEsbVmsShortMsg() {
+        if (!this.config.isStartSchedule()) {
+            return;
+        }
+        Elapsed elapsed = new Elapsed();
+        log.info("scheduleEsbVmsShortMsg: start. {}", Thread.currentThread().getName());
+        this.esbVmsTcpService.loadVmsShorMsg();
+        log.info("scheduleEsbVmsShortMsg: ..end. {} ms. {}", elapsed.milliSeconds(), Thread.currentThread().getName());
+    }
+
 }

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

@@ -3,6 +3,7 @@ package com.its.vms.service;
 import com.its.app.AppUtils;
 import com.its.app.utils.SysUtils;
 import com.its.vms.config.ApplicationConfig;
+import com.its.vms.config.CommunicationConfig;
 import com.its.vms.dao.mapper.UnitSystMapper;
 import com.its.vms.entity.TbUnitSyst;
 import com.its.vms.entity.TbUnitSystStts;
@@ -32,6 +33,7 @@ import java.util.concurrent.ConcurrentHashMap;
 @Transactional(rollbackFor = {Exception.class})
 public class UnitSystService {
 
+    private final CommunicationConfig config;
     private final DbmsDataProcess dbmsDataProcess;
     private final UnitSystMapper mapper;
     private final ConcurrentHashMap<String, TbUnitSyst> dataMap = new ConcurrentHashMap<>();
@@ -97,6 +99,11 @@ public class UnitSystService {
                     unit.setSystIp1(unit.getSystIp1().trim());
                     this.dataMap.put(unit.getSystId(), unit);
                 }
+
+                if (("ESB01").equals(unit.getSystId())) {
+                    this.config.setEsbServer(unit.getSystIp1());
+                    this.config.setEsbPort(unit.getPrgmPort());
+                }
             }
         }
         catch (Exception e) {

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

@@ -722,7 +722,9 @@ public class VmsManageService {
         }
 
         this.atmpService.loadDb();  // 기상정보
-        this.parkService.loadDb();  // 주차정보
+        if (this.config.isUseParking()) {
+            this.parkService.loadDb();  // 주차정보
+        }
         loadEventOccrInfo();  // 돌발정보조회
         this.ifscService.loadDb();  // VMS 정보제공구간 교통정보
 

+ 2 - 1
src/main/java/com/its/vms/ui/SubUI.java

@@ -86,7 +86,8 @@ public abstract class SubUI {
         btnReserved.addActionListener(new ActionListener() {
             @Override
             public void actionPerformed(ActionEvent e) {
-                selObj.addRequestData(new TcpServerSendData(eVmsOpCode.OP_VMS_DISPLAY_DEFAULT_FORM, null));
+                selObj.downloadSymbLib();
+                //selObj.addRequestData(new TcpServerSendData(eVmsOpCode.OP_VMS_DISPLAY_MODULE_STATUS_REQ, null));
             }
         });
         btnLogClear.addActionListener(new ActionListener() {

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

@@ -25,6 +25,7 @@ application:
   font-size-ratio: 1.35
   check-new-form: true
   download-bitmap-form: false
+  use-parking: false
 
 communication:
   listen-port: 30200
@@ -32,6 +33,8 @@ communication:
   dump-send: true
   subscription-status: true
   subscription-status-cycle: 30
+  esb-server: 192.168.20.99
+  esb-port: 9904
 
 server:
   port: 8904
@@ -78,8 +81,8 @@ spring:
     hikari:
       driver-class-name: com.tmax.tibero.jdbc.TbDriver
       jdbc-url: jdbc:tibero:thin:@115.91.94.42:8629:tibero
-      username: gmutis
-      password: gmutis
+      username: adits
+      password: adits
 
 ---
 spring:
@@ -88,9 +91,8 @@ spring:
       on-profile: prod
   datasource:
     hikari:
-      driver-class-name: oracle.jdbc.OracleDriver
-      #jdbc-url: jdbc:oracle:thin:@172.19.10.26:1521:ptatms
-      jdbc-url: jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=172.19.10.25)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=172.19.10.26)(PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=ptatms)))
-      username: ptatms
-      password: ptatms
+      driver-class-name: com.tmax.tibero.jdbc.TbDriver
+      jdbc-url: jdbc:tibero:thin:@115.91.94.42:8629:tibero
+      username: adits
+      password: adits
 

+ 95 - 0
src/main/resources/mybatis/mapper/EsbVmsMapper.xml

@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="com.its.vms.dao.mapper.EsbVmsMapper">
+
+    <select id="selectVmsShortMsg" resultType="com.its.vms.entity.TbEsbVmsShortMsg" fetchSize="20">
+    <![CDATA[
+        select t1.msg_id       AS msgId,
+               t1.rgst_dt      AS rgstDt,
+               t1.msg_tp       AS msgTp,
+               t1.dspl_strt_dt AS dsplStrtDt,
+               t1.dspl_end_dt  AS dsplEndDt,
+               t1.font_name_cd AS fontNameCd,
+               t1.font_colr_cd AS fontColrCd,
+               t1.font_size    AS fontSize,
+               t1.font_bold    AS fontBold,
+               t1.dspl_msg_ln1 AS dsplMsgLn1,
+               t1.dspl_msg_ln2 AS dsplMsgLn2,
+               t1.dspl_msg_ln3 AS dsplMsgLn3,
+               t1.combine_id   AS combineId,
+               t1.user_id      AS userId,
+               t1.send_yn      AS sendYn,
+               t1.send_dt      AS sendDt,
+               t1.try_cnt      AS tryCnt,
+               t1.last_try_dt  AS lastTryDt
+        from tb_esb_vms_short_msg t1
+        where t1.send_yn = 'N'
+          and to_char(sysdate, 'YYYYMMDDHH24MISS') >= t1.dspl_strt_dt
+          and to_char(sysdate, 'YYYYMMDDHH24MISS') <= t1.dspl_end_dt
+    ]]>
+    </select>
+
+    <insert id="insertVmsShortMsg" parameterType="com.its.vms.entity.TbEsbVmsShortMsg">
+    <![CDATA[
+        insert into tb_esb_vms_short_msg (
+            msg_id,
+            rgst_dt,
+            msg_tp,
+            dspl_strt_dt,
+            dspl_end_dt,
+            font_name_cd,
+            font_colr_cd,
+            font_size,
+            font_bold,
+            dspl_msg_ln1,
+            dspl_msg_ln2,
+            dspl_msg_ln3,
+            combine_id,
+            user_id,
+            send_yn,
+            send_dt,
+            try_cnt,
+            last_try_dt )
+        values (
+                   #{obj.msgId},
+                   #{obj.rgstDt},
+                   #{obj.msgTp},
+                   #{obj.dsplStrtDt},
+                   #{obj.dsplEndDt},
+                   #{obj.fontNameCd},
+                   #{obj.fontColrCd},
+                   #{obj.fontSize},
+                   #{obj.fontBold},
+                   #{obj.dsplMsgLn1},
+                   #{obj.dsplMsgLn2},
+                   #{obj.dsplMsgLn3},
+                   #{obj.combineId},
+                   #{obj.userId},
+                   #{obj.sendYn},
+                   #{obj.sendDt},
+                   #{obj.tryCnt},
+                   #{obj.lastTryDt}
+               )
+        ]]>
+    </insert>
+
+    <update id="updateVmsShortMsgResult" parameterType="com.its.vms.entity.TbEsbVmsShortMsgResult">
+    <![CDATA[
+        update tb_esb_vms_short_msg
+        set
+            send_yn      = #{obj.sendYn},
+            send_dt      = #{obj.sendDt},
+            try_cnt      = #{obj.tryCnt},
+            last_try_dt  = #{obj.lastTryDt}
+        where msg_id = #{obj.msgId}
+        ]]>
+    </update>
+
+    <select id="selectNextMsgId" resultType="com.its.vms.entity.NewIdSeq">
+       <![CDATA[
+        SELECT VMS_SHORT_MSG_SEQ.NEXTVAL AS id FROM DUAL
+        ]]>
+    </select>
+
+</mapper>

+ 1 - 1
src/main/resources/mybatis/mapper/VmsAtmpMapper.xml

@@ -31,7 +31,7 @@
                nvl(trim(t2.pm25_1hh_grad), '0')  AS pm251hhGrad,
                nvl(trim(t2.updt_dt), '')         AS updtDt
         from tb_atmp_pltn_sttn t1
-         left outer join tb_atmp_pltn_rt_pnst t2
+         left outer join tb_atmp_pltn_pnst t2
          on t1.atmp_sttn_nmbr = t2.atmp_sttn_nmbr
          and t2.msrm_dt >= to_char(sysdate-120/1440, 'YYYYMMDDHH24MISS')
         ]]>

+ 13 - 13
src/main/resources/mybatis/mapper/VmsCtlrMapper.xml

@@ -10,10 +10,10 @@
                t1.vms_ctlr_id         AS vmsCtlrId,
                t1.vms_nm              AS vmsNm,
                t1.vms_ctlr_ip         AS vmsCtlrIp,
-               t1.vms_usag_type_cd    AS vmsUsagTypeCd,
-               t1.vms_frm_type_cd     AS vmsFrmTypeCd,
+               'VUTP'                 AS vmsUsagTypeCd,
+               'FRM1'                 AS vmsFrmTypeCd,
                t1.vms_type_cd         AS vmsTypeCd,
-               t1.vms_modl_type_cd    AS vmsModlTypeCd,
+               'VMM1'                 AS vmsModlTypeCd,
                t1.vms_ctlr_port       AS vmsCtlrPort,
                t1.oper_mode           AS operMode,
                t1.cmnc_fail_rate      AS cmncFailRate,
@@ -21,26 +21,26 @@
                t1.brgh_week_step      AS brghWeekStep,
                t1.def_phse_chng_cycl  AS defPhseChngCycl,
                t1.modl_err_rate       AS modlErrRate,
-               t1.cmncfail_slot_nmbr  AS cmncfailSlotNmbr,
-               t1.pwer_fail_slot_nmbr AS pwerFailSlotNmbr,
-               t1.cmtrinfr_cnct_yn    AS cmtrinfrCnctYn,
-               t1.wthrinfr_cnct_yn    AS wthrinfrCnctYn,
-               t1.envrinfr_cnct_yn    AS envrinfrCnctYn,
+               0                      AS cmncfailSlotNmbr,
+               0                      AS pwerFailSlotNmbr,
+               'Y'                    AS cmtrinfrCnctYn,
+               'Y'                    AS wthrinfrCnctYn,
+               'Y'                    AS envrinfrCnctYn,
+               'Y'                    AS trfcStrgUseYn,
                t1.vms_max_phse_num    AS vmsMaxPhseNum,
                t1.panl_on_time        AS panlOnTime,
                t1.panl_off_time       AS panlOffTime,
                t1.panl_pwer_mode      AS panlPwerMode,
                t1.brgh_mode           AS brghMode,
                t1.istl_lctn_nm        AS istlLctnNm,
-               t1.trfc_strg_use_yn    AS trfcStrgUseYn,
-               t1.vms_loc_ifsc_id     AS vmsLocIfscId,
+               0                      AS vmsLocIfscId,
                t1.fan_run_tmpr        AS fanRunTmpr,
                t1.hetr_run_tmpr       AS hetrRunTmpr,
                t1.fan_mode            AS fanMode,
                t1.hetr_mode           AS hetrMode,
                t1.brgh_curr_step      AS brghCurrStep,
                t1.istl_lctn_addr      AS istlLctnAddr,
-               t1.protocol_ver        AS protocolVer,
+               2                      AS protocolVer,
                t1.del_yn              AS delYn,
                t2.vms_wdth            AS vmsWidth,
                t2.vms_hght            AS vmsHeight,
@@ -50,8 +50,8 @@
                t2.powr_col_num        AS powrColNum
         from tb_vms_ctlr t1
         inner join tb_vms_type t2
-            on t1.del_yn = 'N'
-            and t1.vms_type_cd = t2.vms_type_cd
+                on t1.del_yn = 'N'
+               and t1.vms_type_cd = t2.vms_type_cd
         order by t1.vms_ctlr_nmbr
     ]]>
     </select>

+ 1 - 1
src/main/resources/mybatis/mapper/VmsFormMapper.xml

@@ -15,7 +15,7 @@
                t1.symb_lib_nmbr                 AS symbLibNmbr,
                t1.vms_form_imag                 AS vmsFormImag,
                t1.vms_form_dspl_mthd_cd         AS vmsFormDsplMthdCd,
-               t1.cctv_mngm_nmbr                AS cctvMngmNmbr,
+               0                                AS cctvMngmNmbr,
                t1.updt_dt                       AS updtDt,
                t1.valid_yn                      AS validYn
         from tb_vms_form t1

+ 2 - 2
src/main/resources/mybatis/mapper/VmsIfscMapper.xml

@@ -33,14 +33,14 @@
                a.spot_nm                AS spotNm,
                a.detr_id                AS detrId,
                a.axis_yn                AS axisYn,
-               nvl(b.rgst_dt,       '') AS prcnDt,
+               nvl(b.prcn_dt,       '') AS prcnDt,
                nvl(b.cmtr_grad_cd, '0') AS cmtrGradCd,
                nvl(b.sped,           0) AS sped,
                nvl(b.trvl_hh,        0) AS trvlHh
         from tb_vms_ifsc a,
              (select *
               from tb_vms_ifsc_traf
-              where rgst_dt >= to_char(sysdate-10/1440, 'yyyymmddhh24miss') ) b
+              where prcn_dt >= to_char(sysdate-10/1440, 'yyyymmddhh24miss') ) b
         where a.vms_ifsc_id = b.vms_ifsc_id(+)
         ]]>
     </select>

+ 3 - 3
src/main/resources/mybatis/mapper/VmsManageMapper.xml

@@ -5,9 +5,9 @@
 
     <insert id="initVmsDsplPrst" parameterType="java.util.Map">
     <![CDATA[
-        INSERT INTO TB_VMS_DSPL_PRST(VMS_CTLR_NMBR, PHASE, DSPL_DT, DNLD_YN)
-        SELECT VMS_CTLR_NMBR, PHASE, DSPL_DT, DNLD_YN
-        FROM (SELECT A.VMS_CTLR_NMBR, B.ORD AS PHASE, '19700101000000' AS DSPL_DT, 'N' AS DNLD_YN
+        INSERT INTO TB_VMS_DSPL_PRST(VMS_CTLR_NMBR, PHASE, DSPL_DT, VMS_SCH_TYPE, DNLD_YN)
+        SELECT VMS_CTLR_NMBR, PHASE, DSPL_DT, VMS_SCH_TYPE, DNLD_YN
+        FROM (SELECT A.VMS_CTLR_NMBR, B.ORD AS PHASE, '19700101000000' AS DSPL_DT, 'A' AS VMS_SCH_TYPE, 'N' AS DNLD_YN
               FROM TB_VMS_CTLR A,
                    (SELECT LEVEL AS ORD FROM DUAL CONNECT BY LEVEL < #{maxPhase}) B
              ) X

+ 5 - 5
src/main/resources/mybatis/mapper/VmsSymbMapper.xml

@@ -11,8 +11,8 @@
                t1.green_data     AS greenData,
                t1.symb_expl      AS symbExpl,
                t1.imag_data      AS imagData,
-               t1.vms_type_cd    AS vmsTypeCd,
-               nvl(t1.symb_imag_type, 'BMP') AS symbImagType,
+               'VMS1'            AS vmsTypeCd,
+               'BMP'             AS symbImagType,
                t1.symb_file_nm   AS symbFileNm,
                t1.symb_type      AS symbType,
                t1.avi_data       AS aviData,
@@ -24,8 +24,8 @@
                nvl(t2.posy, 0)   AS posY
         from tb_vms_symb_lib t1
         left outer join tb_vms_symb_ifsc t2
-        on t1.symb_lib_nmbr = t2.symb_lib_nmbr
-        and t2.cell_id = 1
+                     on t1.symb_lib_nmbr = t2.symb_lib_nmbr
+                    and t2.cell_id = 1
         ]]>
     </select>
 
@@ -58,7 +58,7 @@
               group by vms_form_id, symb_lib_nmbr) b,
              (select symb_lib_nmbr, updt_dt
               from tb_vms_symb_lib
-              where symb_type in ('SBT2', 'SBT4')) c
+              where symb_type in ('SBT0', 'SBT2', 'SBT4')) c
         where a.vms_form_id = b.vms_form_id
           and b.symb_lib_nmbr = c.symb_lib_nmbr
         group by a.vms_ctlr_nmbr, b.symb_lib_nmbr

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

@@ -1,6 +1,9 @@
 package com.its.app;
 
+import com.its.app.utils.ItsUtils;
 import com.its.app.utils.SysUtils;
+import com.its.vms.esb.protocol.EsbFrameTail;
+import com.its.vms.esb.protocol.EsbReqVmsShortMsg;
 import com.its.vms.service.VmsFormService;
 import com.its.vms.service.VmsSymbService;
 import com.its.vms.xnettcp.vms.protocol.enums.eVmsOpCode;
@@ -9,6 +12,7 @@ import org.apache.commons.lang.StringUtils;
 import org.junit.jupiter.api.Test;
 
 import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
 
 @Slf4j
 //@SpringBootTest(classes = VmsCommServerApplication.class)
@@ -108,4 +112,68 @@ public class VmsCommServerApplicationTests {
         log.info("{}", VmsFormService.getDnldFormNo(10186));
         log.info("{}", VmsFormService.getDnldFormNo(13));
     }
+
+    String shortToBinaryString(String binary) {
+        String result = binary;
+        if (result.length() > 16) {
+            return result.substring(16, 32);
+        }
+        if (binary.length() < 16) {
+            int cnt = 16 - binary.length();
+            String tmp = "";
+            for (int ii = 0; ii < cnt; ii++) {
+                tmp += "0";
+            }
+            return tmp + binary;
+        }
+        return binary;
+    }
+
+    @Test
+    void crcTest() {
+        // 2의 보수(2s complement)
+        short n = 10;
+        short result = ItsUtils.orgToTwoComplement(n);
+        String binary = ItsUtils.shortToBinaryString(Integer.toBinaryString(result));
+        log.info("{}, {}, {}", binary, n, (int)result);
+
+        short result1 = (short) ~n;
+        log.info("{}, {}", result1, (result1 + 1));
+
+        // 2s complement 를 원래의 값으로...
+        short o = ItsUtils.twoComplementToOrg(result);
+        String binary5 = shortToBinaryString(Integer.toBinaryString(o));
+        log.info("{}, {}", binary5, o);
+    }
+
+    @Test
+    void arrayCopy() {
+        byte[] facilityIds = new byte[5];
+
+        int facilityIdSize = 15;
+        byte[] newFacilityIds = new byte[facilityIdSize];
+        if (facilityIds.length < facilityIdSize) {
+            facilityIdSize = facilityIds.length;
+        }
+        System.arraycopy(facilityIds, 0, newFacilityIds, 0, facilityIdSize);
+        log.info("{}", facilityIds);
+    }
+
+    @Test
+    void esbPacket() {
+        EsbReqVmsShortMsg vmsShortMsg = new EsbReqVmsShortMsg("ADTRVMS00100001", 1, 2, 24, "가나다123AB CD");
+        ByteBuffer byteBuffer = vmsShortMsg.getByteBuffer();
+        byte[] packet = byteBuffer.array();
+        log.info("{}", SysUtils.byteArrayToHexAscii(packet));
+    }
+
+
+    @Test
+    void esbCrcTest() {
+        byte[] bbCrc = EsbFrameTail.hexToByteArray("00 20".replace(" ", ""));
+        byte[] bb = EsbFrameTail.hexToByteArray("54 52 53 44 46 30 30 39 30 30 36 30 30 56 4d 53 30 30 30 31 32 30 31 36 30 38 32 35 32 30 34 37 30 32 00 00 00 11 02 00 50 00 00 00 0f 30 30 30 36".replace(" ", ""));
+        short crc = EsbFrameTail.getCrc(bb);
+        log.info("{}", crc);
+    }
+
 }