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