Jelajahi Sumber

ggits tsinfo process state update logic add

hante 2 bulan lalu
induk
melakukan
d40c1fa5d5
19 mengubah file dengan 454 tambahan dan 27 penghapusan
  1. 10 0
      .idea/material_theme_project_new.xml
  2. 1 0
      conf/ggits-etlp-server.pid
  3. 2 0
      conf/ggits-etlp-server.yml
  4. 1 0
      ggits-comm-server/src/main/java/com/sig/ggits/comm/server/dto/IntDto.java
  5. 5 0
      ggits-etlp-condition.txt
  6. 2 0
      ggits-etlp-server/conf/ggits-etlp-server.yml
  7. 5 1
      ggits-etlp-server/src/main/java/com/sig/ggits/etlp/server/config/SchedulingConfig.java
  8. 2 0
      ggits-etlp-server/src/main/java/com/sig/ggits/etlp/server/dao/mapper/sig/ProcessMapper.java
  9. 22 0
      ggits-etlp-server/src/main/java/com/sig/ggits/etlp/server/dto/ProcessStateRestDto.java
  10. 11 0
      ggits-etlp-server/src/main/java/com/sig/ggits/etlp/server/scheduler/GgitsEtlpScheduler.java
  11. 52 0
      ggits-etlp-server/src/main/java/com/sig/ggits/etlp/server/service/UnitSystService.java
  12. 198 0
      ggits-etlp-server/src/main/java/com/sig/ggits/etlp/server/url/RequestUrlData.java
  13. 27 0
      ggits-etlp-server/src/main/java/com/sig/ggits/etlp/server/url/RequestUrlDataError.java
  14. 23 0
      ggits-etlp-server/src/main/java/com/sig/ggits/etlp/server/url/RequestUrlDataResult.java
  15. 2 0
      ggits-etlp-server/src/main/resources/application.yml
  16. 20 0
      ggits-etlp-server/src/main/resources/mybatis/mapper/sig/ProcessMapper.xml
  17. 27 0
      ggits-tsinfo-server/src/main/java/com/sig/ggits/tsinfo/server/controller/GgitsTsinfoServerController.java
  18. 18 0
      ggits-tsinfo-server/src/main/java/com/sig/ggits/tsinfo/server/dto/ProcessStateRestDto.java
  19. 26 26
      sig-consumer/src/main/java/com/sig/comm/consumer/kafka/KafkaConsumerWorker.java

+ 10 - 0
.idea/material_theme_project_new.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="MaterialThemeProjectNewConfig">
+    <option name="metadata">
+      <MTProjectMetadataState>
+        <option name="userId" value="3baf6998:195f521edd6:-7ff2" />
+      </MTProjectMetadataState>
+    </option>
+  </component>
+</project>

+ 1 - 0
conf/ggits-etlp-server.pid

@@ -0,0 +1 @@
+5896

+ 2 - 0
conf/ggits-etlp-server.yml

@@ -11,4 +11,6 @@ application:
   page-count: 0
   scheduling:
     process-ggits-etlp: 10 3 3 * * *
+    ggits-tsinfo-process-id: 81050
+    ggits-tsinfo-url: http://192.168.24.22:9871/info/ps
 

+ 1 - 0
ggits-comm-server/src/main/java/com/sig/ggits/comm/server/dto/IntDto.java

@@ -7,6 +7,7 @@ import lombok.NoArgsConstructor;
 
 import java.io.Serializable;
 
+
 @Data
 @Builder
 @NoArgsConstructor//(access = AccessLevel.PROTECTED)

+ 5 - 0
ggits-etlp-condition.txt

@@ -0,0 +1,5 @@
+교차로이동류_연계, SCS_T_CON_INTFLOW	=> TB_INT_PHASE
+	INT_RING(링번호) 				=> 1(A링) or 2(B링)
+	INT_PHASE_NO(현시번호) 	=> 1,2,3,4,5,6,7
+
+

+ 2 - 0
ggits-etlp-server/conf/ggits-etlp-server.yml

@@ -11,4 +11,6 @@ application:
   page-count: 0
   scheduling:
     process-ggits-etlp: 10 3 3 * * *
+    ggits-tsinfo-process-id: 81050
+    ggits-tsinfo-url: http://192.168.24.22:9871/info/ps
 

+ 5 - 1
ggits-etlp-server/src/main/java/com/sig/ggits/etlp/server/config/SchedulingConfig.java

@@ -17,6 +17,9 @@ import javax.annotation.PostConstruct;
 public class SchedulingConfig implements SchedulingConfigurer {
 
     private int poolSize = 0;
+    private boolean useGgitsTsinfoUrl = true;
+    private String ggitsTsinfoProcessId = "81050";
+    private String ggitsTsinfoUrl;
 
     @PostConstruct
     private void init() {
@@ -25,7 +28,8 @@ public class SchedulingConfig implements SchedulingConfigurer {
             log.warn("[{}] poolSize size set as default: {} EA.", this.getClass().getSimpleName(), this.poolSize);
             this.poolSize = 10;
         }
-        log.info("[{}] poolSize: {} EA.", this.getClass().getSimpleName(), this.poolSize);
+        log.info("[{}]       poolSize: {} EA", this.getClass().getSimpleName(), this.poolSize);
+        log.info("[{}]    ggitsTsinfo: {}, {}, {}", this.getClass().getSimpleName(), this.useGgitsTsinfoUrl, this.ggitsTsinfoProcessId, this.ggitsTsinfoUrl);
     }
 
     @Override

+ 2 - 0
ggits-etlp-server/src/main/java/com/sig/ggits/etlp/server/dao/mapper/sig/ProcessMapper.java

@@ -9,4 +9,6 @@ public interface ProcessMapper {
     int updateProcessState(@Param("processId") String processId);
     int updateProcessStateStart(@Param("processId") String processId);
     int updateProcessStateStop(@Param("processId") String processId);
+    int updateGgitsProcessStateStop(@Param("processId") String processId);
+    int updateGgitsProcessState(@Param("processId") String processId, @Param("strDate") String strDate, @Param("errDesc") String errDesc);
 }

+ 22 - 0
ggits-etlp-server/src/main/java/com/sig/ggits/etlp/server/dto/ProcessStateRestDto.java

@@ -0,0 +1,22 @@
+package com.sig.ggits.etlp.server.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class ProcessStateRestDto implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    public String processId;
+    public String strDate;
+    public int onlineCount;
+    public int offlineCount;
+
+}

+ 11 - 0
ggits-etlp-server/src/main/java/com/sig/ggits/etlp/server/scheduler/GgitsEtlpScheduler.java

@@ -2,6 +2,7 @@ package com.sig.ggits.etlp.server.scheduler;
 
 import com.its.common.utils.Elapsed;
 import com.sig.ggits.etlp.server.config.ApplicationConfig;
+import com.sig.ggits.etlp.server.config.SchedulingConfig;
 import com.sig.ggits.etlp.server.service.GgitsEtlpService;
 import com.sig.ggits.etlp.server.service.UnitSystService;
 import lombok.RequiredArgsConstructor;
@@ -18,6 +19,7 @@ import org.springframework.stereotype.Component;
 public class GgitsEtlpScheduler {
 
     private final ApplicationConfig config;
+    private final SchedulingConfig schedulingConfig;
     private final UnitSystService unitSystService;
     private final GgitsEtlpService service;
     // 초(0-59) 분(0-59) 시간(0-23) 일(1-31) 월(1-12) 요일(0-6) (0: 일, 1: 월, 2:화, 3:수, 4:목, 5:금, 6:토)
@@ -31,6 +33,15 @@ public class GgitsEtlpScheduler {
         catch(Exception e) {
             log.error("ApplicationScheduler.updateUnitSystStts: Exception {}", e.getMessage());
         }
+
+        try {
+            if (this.schedulingConfig.isUseGgitsTsinfoUrl()) {
+                this.unitSystService.updateGgitsTsinfoUnitSystStts(this.schedulingConfig.getGgitsTsinfoProcessId(), this.schedulingConfig.getGgitsTsinfoUrl());
+            }
+        }
+        catch(Exception e) {
+            log.error("ApplicationScheduler.updateGgitsTsinfoUnitSystStts: Exception {}", e.getMessage());
+        }
     }
 
     @Async

+ 52 - 0
ggits-etlp-server/src/main/java/com/sig/ggits/etlp/server/service/UnitSystService.java

@@ -1,7 +1,12 @@
 package com.sig.ggits.etlp.server.service;
 
+import com.fasterxml.jackson.core.type.TypeReference;
 import com.sig.ggits.etlp.server.config.ApplicationConfig;
 import com.sig.ggits.etlp.server.dao.mapper.sig.ProcessMapper;
+import com.sig.ggits.etlp.server.dto.ProcessStateRestDto;
+import com.sig.ggits.etlp.server.url.RequestUrlData;
+import com.sig.ggits.etlp.server.url.RequestUrlDataError;
+import com.sig.ggits.etlp.server.url.RequestUrlDataResult;
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -21,6 +26,8 @@ public class UnitSystService {
     private final ApplicationConfig config;
     private final ProcessMapper mapper;
 
+    private boolean isGgitsTsinfoRun = true;
+
     @PostConstruct
     private void init() {
         log.info("UnitSystService.init: start.");
@@ -45,4 +52,49 @@ public class UnitSystService {
     public void updateUnitSystStts() {
         this.mapper.updateProcessState(this.config.getProcessId());
     }
+
+    public void updateGgitsTsinfoUnitSystStts(String processId, String url) {
+
+        boolean isRun = false;
+        String ggitsTsinfoProcessId = processId;
+        String strDate = "";
+        String errDesc = "";
+
+        TypeReference<ProcessStateRestDto> typeRef = new TypeReference<ProcessStateRestDto>() {};
+        RequestUrlDataResult<ProcessStateRestDto> response = RequestUrlData.fetchJsonDataFromUrl(
+                url,
+                5,
+                5,
+                1,
+                5,
+                typeRef);
+        if (response.getErrorCode() == RequestUrlDataError.SUCCESS) {
+            ProcessStateRestDto responseData = response.getData();
+
+            if (responseData != null) {
+                isRun = true;
+                ggitsTsinfoProcessId = responseData.getProcessId();
+                strDate = responseData.getStrDate();
+                errDesc = "online: " + responseData.getOnlineCount() + ", offLine: " + responseData.getOfflineCount();
+            }
+        }
+        log.info("UnitSystService.ggitsTsinfo: processId: {}, isRun(prev): {}({}), strDate: {}, errDesc: {}",
+                ggitsTsinfoProcessId, isRun, this.isGgitsTsinfoRun, strDate, errDesc);
+
+        if (!isRun) {
+            if (this.isGgitsTsinfoRun) {
+                // 첫번째로 실행중이 아님을 확인했음.
+                this.mapper.updateProcessStateStop(ggitsTsinfoProcessId);
+            }
+            else {
+                // 계속 실행중이 아님을 확인했음.
+                this.mapper.updateGgitsProcessStateStop(ggitsTsinfoProcessId);
+            }
+        }
+        else {
+            this.mapper.updateGgitsProcessState(ggitsTsinfoProcessId, strDate, errDesc);
+        }
+        this.isGgitsTsinfoRun = isRun;
+    }
+
 }

+ 198 - 0
ggits-etlp-server/src/main/java/com/sig/ggits/etlp/server/url/RequestUrlData.java

@@ -0,0 +1,198 @@
+package com.sig.ggits.etlp.server.url;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.extern.slf4j.Slf4j;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.StringReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.stream.Collectors;
+@Slf4j
+public final class RequestUrlData {
+
+    private static final ObjectMapper objectMapper = new ObjectMapper()
+            .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+
+    public static <T> RequestUrlDataResult<T> fetchJsonDataFromUrl(String urlString, int connectTimeout, int readTimeout, int maxRetries, int retryDelaySeconds, TypeReference<T> responseType) {
+        return executeRequestWithRetries(urlString, connectTimeout, readTimeout, maxRetries, retryDelaySeconds, responseType, null);
+    }
+
+    public static <T> RequestUrlDataResult<T> fetchXmlDataFromUrl(
+            String urlString, int connectTimeout, int readTimeout, int maxRetries, int retryDelaySeconds, Class<T> responseType) {
+        return executeRequestWithRetries(urlString, connectTimeout, readTimeout, maxRetries, retryDelaySeconds, null, responseType); // ✅ rootElement 추가
+    }
+
+    private static void retryWithDelay(int retryDelaySeconds) {
+        if (retryDelaySeconds > 0) {
+            try {
+                log.info("{}초 동안 대기 후 재시도...", retryDelaySeconds);
+                Thread.sleep(retryDelaySeconds * 1000L);
+            } catch (InterruptedException ex) {
+                Thread.currentThread().interrupt();
+                log.error("재시도 대기 중 인터럽트 발생: {}", ex.getMessage());
+            }
+        }
+    }
+
+    private static <T> RequestUrlDataResult<T> executeRequestWithRetries(
+            final String urlString,
+            final int connectTimeout,
+            final int readTimeout,
+            final int maxRetries,
+            final int retryDelaySeconds,
+            final TypeReference<T> jsonType,
+            final Class<T> xmlType) {
+
+        int attempt = 0;
+
+        while (attempt < maxRetries) {
+            attempt++;
+            HttpURLConnection connection = null;
+
+            try {
+                connection = createConnection(urlString, connectTimeout, readTimeout);
+                int responseCode = connection.getResponseCode();
+                String contentType = getContentType(connection);
+                String response = readResponse(connection);
+
+//                log.info("Content-Type: {}, Response Code: {}", contentType, responseCode);
+                if (responseCode == HttpURLConnection.HTTP_OK) {
+//                    log.info("Response: {}", response);
+                    if ("application/json".equalsIgnoreCase(contentType) && jsonType != null) {
+                        // JSON 응답 처리
+                        return new RequestUrlDataResult<>(RequestUrlDataError.SUCCESS, "SUCCESS", parseJson(response, jsonType));
+                    }
+                    else if ("application/xml".equalsIgnoreCase(contentType) && xmlType != null) {
+                        // XML 응답 처리
+                        return new RequestUrlDataResult<>(RequestUrlDataError.SUCCESS, "SUCCESS", parseXml(response, xmlType));
+                    }
+                    else if ("text/xml".equalsIgnoreCase(contentType) && xmlType != null) {
+                        // XML 응답 처리
+                        return new RequestUrlDataResult<>(RequestUrlDataError.SUCCESS, "SUCCESS", parseXml(response, xmlType));
+                    }
+                    else {
+                        String errorMessage = String.format("지원되지 않는 Content-Type: %s", contentType);
+                        log.warn("{}.", errorMessage);
+                        return new RequestUrlDataResult<>(RequestUrlDataError.UNSUPPORTED_CONTENT_TYPE, errorMessage, null);
+                    }
+                }
+
+                // 오류 응답 처리
+                if (attempt < maxRetries && shouldRetry(responseCode)) {
+                    int retryDelay = (responseCode == 429) ? getRetryDelay(connection, retryDelaySeconds) : retryDelaySeconds;
+                    log.info("서버에서 오류 발생[RESPONSE: {}]. {}초 후 재시도... ({}/{})", responseCode, retryDelay, attempt, maxRetries);
+                    retryWithDelay(retryDelay);
+                }
+                else {
+                    break;
+                }
+            }
+            catch (Exception e) {
+                log.error("요청 오류 발생 ({}/{}): [{}] -> {}", attempt, maxRetries, urlString, e.getMessage());
+                if (attempt < maxRetries) {
+                    log.info("네트워크 요청 오류 발생. {}초 후 재시도... ({}/{})", retryDelaySeconds, attempt, maxRetries);
+                    retryWithDelay(retryDelaySeconds);
+                }
+                else {
+                    return new RequestUrlDataResult<>(RequestUrlDataError.NETWORK_ERROR, e.getMessage(), null);
+                }
+            }
+            finally {
+                if (connection != null) {
+                    connection.disconnect();
+                }
+            }
+        }
+
+        log.warn("최대 재시도 횟수({})를 초과했습니다: [{}]", maxRetries, urlString);
+        return new RequestUrlDataResult<>(RequestUrlDataError.RETRY_LIMIT_EXCEEDED, "재시도 횟수 초과", null);
+    }
+
+    private static boolean shouldRetry(int responseCode) {
+        return (responseCode >= 500 && responseCode <= 504) || responseCode == 429;
+    }
+    private static int getRetryDelay(HttpURLConnection connection, int retryDelaySeconds) {
+        String retryAfter = connection.getHeaderField("Retry-After");
+        if (retryAfter != null) {
+            try {
+                int retrySeconds = Integer.parseInt(retryAfter);
+                return Math.min(retrySeconds, retryDelaySeconds); // 최대 제한 적용
+            } catch (NumberFormatException e) {
+                log.warn("Retry-After 값 파싱 오류: {}", e.getMessage());
+            }
+        }
+        return 0; // Retry-After 값이 없거나 오류가 발생한 경우 기본값 반환
+    }
+    private static boolean shouldRetry(int responseCode, HttpURLConnection connection) {
+        if (responseCode >= 500 && responseCode <= 504) {
+            return true; // 서버 오류로 인해 재시도 가능
+        }
+
+        if (responseCode == 429) {
+            String retryAfter = connection.getHeaderField("Retry-After");
+            if (retryAfter != null) {
+                try {
+                    int retrySeconds = Integer.parseInt(retryAfter);
+                    log.info("서버 요청 제한(429). {}초 후 재시도 권장.", retrySeconds);
+                    Thread.sleep(retrySeconds * 1000L);
+                    return true;
+                } catch (NumberFormatException | InterruptedException e) {
+                    log.warn("Retry-After 값을 파싱하는 중 오류 발생: {}", e.getMessage());
+                    Thread.currentThread().interrupt();
+                }
+            }
+            return false; // Retry-After 정보가 없으면 재시도하지 않음
+        }
+        return false; // 기타 오류 코드에 대해서는 재시도하지 않음
+    }
+
+    private static HttpURLConnection createConnection(String urlString, int connectTimeout, int readTimeout) throws IOException {
+        URL url = new URL(urlString);
+        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+        connection.setConnectTimeout(connectTimeout*1000);
+        connection.setReadTimeout(readTimeout*1000);
+        connection.setRequestMethod("GET");
+        connection.setRequestProperty("Accept", "application/json, application/xml");
+        connection.setRequestProperty("User-Agent", "Mozilla/5.0");
+        return connection;
+    }
+
+    private static String getContentType(HttpURLConnection connection) {
+        String contentType = connection.getContentType();
+        return contentType != null ? contentType.split(";")[0].trim() : "";
+    }
+
+    private static String readResponse(HttpURLConnection connection) throws IOException {
+        try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
+            return br.lines().collect(Collectors.joining());
+        }
+    }
+
+    private static <T> T parseJson(String json, TypeReference<T> responseType) throws JsonProcessingException {
+        return objectMapper.readValue(json, responseType);
+    }
+
+    private static <T> T parseXml(String xml, Class<T> responseType) throws Exception {
+//        String cleanedXml = xml.replaceFirst("^\\uFEFF", ""); // UTF-8 BOM 제거
+        try {
+            JAXBContext jaxbContext = JAXBContext.newInstance(responseType);
+            Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+            return responseType.cast(unmarshaller.unmarshal(new StringReader(xml)));
+//            return (T) unmarshaller.unmarshal(new StringReader(xml));
+        } catch (JAXBException e) {
+            return null; // XML 파싱 실패 시 null 반환
+        }
+    }
+
+}

+ 27 - 0
ggits-etlp-server/src/main/java/com/sig/ggits/etlp/server/url/RequestUrlDataError.java

@@ -0,0 +1,27 @@
+package com.sig.ggits.etlp.server.url;
+
+public enum RequestUrlDataError {
+    SUCCESS(0, "요청 성공"),
+    NETWORK_ERROR(1, "네트워크 오류"),
+    HTTP_ERROR(2, "HTTP 요청 실패"),
+    RETRY_LIMIT_EXCEEDED(3, "최대 재시도 횟수 초과"),
+    UNSUPPORTED_CONTENT_TYPE(4, "지원되지 않는 Content-Type");
+
+    private final int code;
+    private final String message;
+
+    RequestUrlDataError(int code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+
+}

+ 23 - 0
ggits-etlp-server/src/main/java/com/sig/ggits/etlp/server/url/RequestUrlDataResult.java

@@ -0,0 +1,23 @@
+package com.sig.ggits.etlp.server.url;
+
+public class RequestUrlDataResult<T> {
+    private final RequestUrlDataError errorCode;
+    private final String errorMessage;
+    private final T data;
+
+    public RequestUrlDataResult(RequestUrlDataError errorCode, String errorMessage, T data) {
+        this.errorCode = errorCode;
+        this.errorMessage = errorMessage;
+        this.data = data;
+    }
+
+    public RequestUrlDataError getErrorCode() {
+        return errorCode;
+    }
+
+    public T getData() {
+        return data;
+    }
+
+
+}

+ 2 - 0
ggits-etlp-server/src/main/resources/application.yml

@@ -52,6 +52,8 @@ application:
     pool-size: 0
     #process-ggits-etlp: 0 9 * * * *
     process-ggits-etlp: 10 3 3 * * *
+    ggits-tsinfo-process-id: 81050
+    ggits-tsinfo-url: http://192.168.24.22:9871/info/ps
 
 ---
 spring:

+ 20 - 0
ggits-etlp-server/src/main/resources/mybatis/mapper/sig/ProcessMapper.xml

@@ -32,4 +32,24 @@
         ]]>
     </update>
 
+    <update id="updateGgitsProcessStateStop" parameterType="java.lang.String">
+    <![CDATA[
+        UPDATE TB_PROCESS_STATE
+        SET RUNSTATE  = '1',
+            REGDATE   =  SYSDATE
+        WHERE PROCESSID = #{processId}
+        ]]>
+    </update>
+
+    <update id="updateGgitsProcessState" parameterType="java.lang.String">
+    <![CDATA[
+        UPDATE TB_PROCESS_STATE
+        SET RUNSTATE  = '0',
+            STRDATE   = TO_DATE(#{strDate}, 'YYYY-MM-DD HH24:MI:SS'),
+            ERRDESC   = #{errDesc},
+            REGDATE   =  SYSDATE
+        WHERE PROCESSID = #{processId}
+        ]]>
+    </update>
+
 </mapper>

+ 27 - 0
ggits-tsinfo-server/src/main/java/com/sig/ggits/tsinfo/server/controller/GgitsTsinfoServerController.java

@@ -3,8 +3,10 @@ package com.sig.ggits.tsinfo.server.controller;
 import com.its.common.utils.TimeUtils;
 import com.sig.ggits.tsinfo.server.config.ApplicationConfig;
 import com.sig.ggits.tsinfo.server.dto.GgitsRegion;
+import com.sig.ggits.tsinfo.server.dto.ProcessStateRestDto;
 import com.sig.ggits.tsinfo.server.repository.ApplicationRepository;
 import lombok.RequiredArgsConstructor;
+import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
@@ -60,5 +62,30 @@ public class GgitsTsinfoServerController {
         return sb.toString();
     }
 
+    @GetMapping(value = "/ps")
+    public ResponseEntity<?> processStateInfo() {
+        ProcessStateRestDto result = ProcessStateRestDto.builder()
+                .processId(this.config.getProcessId())
+                .strDate(this.config.getBootingTime())
+                .onlineCount(0)
+                .offlineCount(0)
+                .build();
 
+        int totalCount = 0;
+        int onlineCount = 0;
+        List<Integer> keySet = new ArrayList<>(this.repo.getCenterMap().keySet());
+        for (Integer key : keySet) {
+            GgitsRegion center = this.repo.getCenterMap().get(key);
+            if (center == null) {
+                continue;
+            }
+            totalCount++;
+            if (center.isCommOnline(this.config.getCommFailSeconds())) {
+                onlineCount++;
+            }
+        }
+        result.setOnlineCount(onlineCount);
+        result.setOfflineCount(totalCount - onlineCount);
+        return ResponseEntity.ok(result);
+    }
 }

+ 18 - 0
ggits-tsinfo-server/src/main/java/com/sig/ggits/tsinfo/server/dto/ProcessStateRestDto.java

@@ -0,0 +1,18 @@
+package com.sig.ggits.tsinfo.server.dto;
+
+import lombok.Builder;
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+@Builder
+public class ProcessStateRestDto implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    public String processId;
+    public String strDate;
+    public int onlineCount;
+    public int offlineCount;
+
+}

+ 26 - 26
sig-consumer/src/main/java/com/sig/comm/consumer/kafka/KafkaConsumerWorker.java

@@ -107,16 +107,16 @@ public class KafkaConsumerWorker implements MessageListener<String, byte[]> {
             int blink;              //1   점멸 상태,                      1 : 점멸, 0 : 정상
             int ppc;                //0   PPC Control,                    0: PPC Disable  1: PPC Enabled
 
-        operStts  = buffer[idx++] & 0xFF;
-        aRingCode = buffer[idx++] & 0xFF;
-        bRingCode = buffer[idx++] & 0xFF;
-        lcStts    = buffer[idx++] & 0xFF;
+        operStts  = (int)(buffer[idx++] & 0xFF);
+        aRingCode = (int)(buffer[idx++] & 0xFF);
+        bRingCode = (int)(buffer[idx++] & 0xFF);
+        lcStts    = (int)(buffer[idx++] & 0xFF);
 
         aRingPhase = (aRingCode >> 5) & 0x07;   // 0x7 = 0000 0111
-        aRingStep =  (aRingCode     ) & 0x1F;   // 0x1F == 0001 1111
+        aRingStep  = (aRingCode     ) & 0x1F;   // 0x1F == 0001 1111
 
         bRingPhase = (bRingCode >> 5) & 0x07;
-        bRingStep   =(bRingCode     ) & 0x1F;
+        bRingStep  = (bRingCode     ) & 0x1F;
 
         centerComm = (operStts >> 7) & 0x01;
         operMapNo  = (operStts >> 4) & 0x07;
@@ -130,7 +130,7 @@ public class KafkaConsumerWorker implements MessageListener<String, byte[]> {
         contration    = (lcStts >> 3) & 0x01;
         turnOff       = (lcStts >> 2) & 0x01;
         blink         = (lcStts >> 1) & 0x01;
-        ppc       = (lcStts     ) & 0x01;
+        ppc           = (lcStts     ) & 0x01;
 
         log.info("-------------------------------------------------------------------------------------------");
         log.info("             NodeId({}), Key({}), Version({})", nodeId, topicKey, version);
@@ -154,27 +154,27 @@ public class KafkaConsumerWorker implements MessageListener<String, byte[]> {
 //        PPC 제어 상태
 
         if (version == 1) {
-            int cycleCount   = buffer[idx++] & 0xFF;
-            int currentCycle = buffer[idx++] & 0xFF;
+            int cycleCount   = (int)(buffer[idx++] & 0xFF);
+            int currentCycle = (int)(buffer[idx++] & 0xFF);
             log.info("  주기 Count/Length({}/{})", cycleCount, currentCycle);
             log.info("  B Ring PHASE/STEP({}/{})", cycleCount, currentCycle);
-            int a1 = buffer[idx++] & 0xFF;
-            int a2 = buffer[idx++] & 0xFF;
-            int a3 = buffer[idx++] & 0xFF;
-            int a4 = buffer[idx++] & 0xFF;
-            int a5 = buffer[idx++] & 0xFF;
-            int a6 = buffer[idx++] & 0xFF;
-            int a7 = buffer[idx++] & 0xFF;
-            int a8 = buffer[idx++] & 0xFF;
-
-            int b1 = buffer[idx++] & 0xFF;
-            int b2 = buffer[idx++] & 0xFF;
-            int b3 = buffer[idx++] & 0xFF;
-            int b4 = buffer[idx++] & 0xFF;
-            int b5 = buffer[idx++] & 0xFF;
-            int b6 = buffer[idx++] & 0xFF;
-            int b7 = buffer[idx++] & 0xFF;
-            int b8 = buffer[idx++] & 0xFF;
+            int a1 = (int)(buffer[idx++] & 0xFF);
+            int a2 = (int)(buffer[idx++] & 0xFF);
+            int a3 = (int)(buffer[idx++] & 0xFF);
+            int a4 = (int)(buffer[idx++] & 0xFF);
+            int a5 = (int)(buffer[idx++] & 0xFF);
+            int a6 = (int)(buffer[idx++] & 0xFF);
+            int a7 = (int)(buffer[idx++] & 0xFF);
+            int a8 = (int)(buffer[idx++] & 0xFF);
+
+            int b1 = (int)(buffer[idx++] & 0xFF);
+            int b2 = (int)(buffer[idx++] & 0xFF);
+            int b3 = (int)(buffer[idx++] & 0xFF);
+            int b4 = (int)(buffer[idx++] & 0xFF);
+            int b5 = (int)(buffer[idx++] & 0xFF);
+            int b6 = (int)(buffer[idx++] & 0xFF);
+            int b7 = (int)(buffer[idx++] & 0xFF);
+            int b8 = (int)(buffer[idx++] & 0xFF);
             log.info(" A Ring Phase Value({}/{}/{}/{}/{}/{}/{}/{})", a1, a2, a3, a4, a5, a6, a7, a8);
             log.info(" B Ring Phase Value({}/{}/{}/{}/{}/{}/{}/{})", b1, b2, b3, b4, b5, b6, b7, b8);
         }