package com.its.vms.service; import com.its.app.utils.Elapsed; import com.its.app.utils.FloodFill; import com.its.app.utils.ItsUtils; import com.its.vms.config.ApplicationConfig; import com.its.vms.config.DebugConfig; import com.its.vms.dao.mapper.VmsManageMapper; import com.its.vms.domain.VmsConstants; import com.its.vms.domain.VmsForm; import com.its.vms.domain.VmsFormObject; import com.its.vms.domain.VmsSchedule; import com.its.vms.domain.enums.eTrafficGrade; import com.its.vms.domain.enums.eVmsColor; import com.its.vms.domain.enums.eVmsFormType; import com.its.vms.domain.enums.eVmsScheduleType; import com.its.vms.dto.*; import com.its.vms.entity.TbVmsIncd; import com.its.vms.entity.TbVmsOperMode; import com.its.vms.entity.TbVmsSchedule; import com.its.vms.process.DbmsData; import com.its.vms.process.DbmsDataProcess; import com.its.vms.process.DbmsDataType; import com.its.vms.xnettcp.vms.process.TcpServerSendData; import com.its.vms.xnettcp.vms.protocol.enums.eVmsFormObjectKind; import com.its.vms.xnettcp.vms.protocol.enums.eVmsOpCode; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.List; import java.util.*; @Slf4j @Service @RequiredArgsConstructor public class VmsManageService { private final DebugConfig debug; private final ApplicationConfig config; private final VmsManageMapper mapper; private final AppRepositoryService repoService; private final VmsFontService fontService; private final VmsSymbService symbService; private final VmsFormService formService; private final VmsIfscService ifscService; private final VmsAtmpService atmpService; private final VmsParkService parkService; private final DbmsDataProcess dbmsDataProcess; private int toggleFormSeq = 1; public void initVmsDsplPrst() { HashMap param = new HashMap<>(); param.put("maxPhase", this.config.getMaxDownloadForms()+1); this.mapper.initVmsDsplPrst(param); } /** * VMS 기초 정보 로딩 */ public void loadDb() { Elapsed elapsed = new Elapsed(); log.info("VmsManageService.loadBaseDatabase: START."); this.fontService.loadDb(); this.symbService.loadDb(); this.formService.loadDb(); log.info("VmsManageService.loadBaseDatabase: ..END. {} ms.", elapsed.milliSeconds()); } /** * 돌발 및 공사/행사 정보 조회 */ public void loadEventOccrInfo() { Elapsed elapsed = new Elapsed(); List result = this.mapper.selectVmsIncd(); result.forEach(data -> { TbVmsCtlrDto vmsObj = this.repoService.getCtlrMap(data.getVmsCtlrNmbr()); if (vmsObj == null) { log.error("VmsManageService.loadEventOccrInfo: Not Found VMS {}, Incident {}.", data.getVmsCtlrNmbr(), data.getIncdOcrrId()); return; } // if (!vmsObj.isProvide()) { // log.error("VmsManageService.loadEventOccrInfo: VMS {}, Provide {}.", data.getVmsCtlrNmbr(), vmsObj.isProvide()); // return; // } if ("VIT1".equals(data.getVmsIncdTypeCd())) { // 사고 vmsObj.getIncident().add(data.toDto()); } else { // 공사/행사 vmsObj.getEvent().add(data.toDto()); } }); log.info("VmsManageService.loadEventOccrInfo: {} ms.", elapsed.milliSeconds()); } /** * VMS 정보제공구간 정체 판정 */ public void congestJudgment() { this.repoService.getCtlrMap().forEach((key, obj) -> { obj.getRltnIfscMap().forEach((ifscId, ifsc) -> { if (!ifsc.isUsed()) { return; // 사용안함 } if (!ifsc.isCngstCnfmYn()) { return; // 정체판정이 아닌경우 } TbVmsIfscTrafDto ifscTraf = this.ifscService.find(ifsc.getVmsIfscId()); if (ifscTraf == null) { log.error("VmsManageService.congestJudgment: VMS {}, Not Found VMS IFSC TRAF {}.", ifsc.getVmsCtlrNmbr(), ifsc.getVmsIfscId()); ifsc.setCngstCnt(0); return; } if (ifsc.getCngstSped() > ifscTraf.getSped()) { // 현재속도값이 정체판정속도 이하이면 정체판정 횟수를 증가 if (ifsc.getCngstCnt() == 0) { ifsc.setCngstDt(ItsUtils.getSysTime()); } // 가공주기에 대해서 정체가 지속되는 경우 주기를 증가 // 연속으로 정체로 판정되는 경우에 한해서 정체폼을 생성하기 위함. ifsc.setCngstCnt(ifsc.getCngstCnt()+1); } else { // 정체판정속도보다 크면 정체횟수를 초기화 ifsc.setCngstCnt(0); } }); }); } /** * VMS 교통정보 표출 스케쥴 조회 */ public void loadVmsDsplTrafSchedule(TbVmsCtlrDto vmsObj, TbVmsFormDto vmsForm, TbVmsScheduleDto schedule) { eVmsFormType vmsFormType = eVmsFormType.getValue(vmsForm.getVmsFormTypeCd()); if (vmsFormType != eVmsFormType.eFormTp_figure) { // 도형식 소통정보 스케쥴이 아닌 일반 소통정보 스케쥴 인 경우 TbVmsScheduleDto trafSchedule = schedule.clone(); vmsObj.getSchedule().add(trafSchedule); return; } // 도형식 소통정보 스케쥴 boolean isIfscTraf = false; Long trafIfscId = 0L; int trafIfscCnt = 0; //전체 표출할 하단 소통정보 갯수 boolean isAxisTraf = false; Long axisIfscId = 0L; int trafAxisCnt = 0; //전체 표출할 하단 소통정보 갯수 boolean isTraffic = false; int missingCnt = 0; int figureDisplayTm = schedule.getDsplHh(); TbVmsSymbLibDto backTrafSymb = this.symbService.find(vmsForm.getTrfBackImgId()); // 심벌번호+"0" if (backTrafSymb == null) { log.error("VmsManageService.loadVmsDsplTrafSchedule: VMS {} Back Traffic Form {}, Not Found Back Traffic Image {}.", vmsObj.getVmsCtlrNmbr(), vmsForm.getVmsFormId(), vmsForm.getTrfBackImgId()); return; } // 배경 이미지에 설정된 구간에 대해서 소통정보 확인 for (Map.Entry e : backTrafSymb.getCellMap().entrySet()) { TbVmsSymbIfscDto cell = e.getValue(); if (cell.isDup()) { continue; } TbVmsIfscTrafDto ifscTraf = this.ifscService.find(cell.getVmsIfscId()); if (ifscTraf == null) { log.error("VmsManageService.loadVmsDsplTrafSchedule: VMS {} Back Traffic Form {}, IFSC Not Found {}, cellId {}.", vmsObj.getVmsCtlrNmbr(), vmsForm.getVmsFormId(), cell.getVmsIfscId(), cell.getCellId()); missingCnt++; continue; } if (0 == ifscTraf.getCmtrGradCd()) { missingCnt++; } else { isTraffic = true; if ("Y".equals(ifscTraf.getAxisYn())) { // 축 구간 if (axisIfscId == 0L) { axisIfscId = ifscTraf.getVmsIfscId(); } if (vmsForm.isBottomTrfAxis()) { isAxisTraf = true; // 첫번째 소통정보가 표출되도록 함 trafAxisCnt++; } } else { // 정보제공구간 if (trafIfscId == 0L) { trafIfscId = cell.getVmsIfscId(); // 지/정체 정보가 없을 경우 하단 소통정보에 표출할 정보제공구간 } if (vmsForm.isBottomTrfIfsc()) { if (3 == ifscTraf.getCmtrGradCd() || 2 == ifscTraf.getCmtrGradCd()) { // 지/정체구간 isIfscTraf = true; // 도형식배경소통정보의 셀내의 구간정보 소통정보가 하나라도 있으면 도형식 소통정보를 표출함 trafIfscCnt++; } } } } } // 민간정보 연계에서 정보가 수집되지 않는 경우 가 종종 있어서 도형식 소통정보를 채우지 못한다. // 결측구간이 3구간 이상이면 도형식 소통정보 표출하지 말자 // 도형식 구간의 모든 소통정보가 생성되지 않았음===> 가공서버가 죽었거나 수집되지 않았음. if (!isTraffic || missingCnt >= 3) { log.error("VmsManageService.loadVmsDsplTrafSchedule: VMS {} Back Traffic Form {}, {}, IFSC Missing Traffic {} EA.", vmsObj.getVmsCtlrNmbr(), vmsForm.getVmsFormId(), isTraffic, missingCnt); return; } // 하단에 정보제공구간 소통정보를 표출해야 하는 경우 if (vmsForm.isBottomTrfIfsc()) { // 도형식 하단에 정보제공구간 소통정보 표출하는 경우 다중폼이 생성됨 // 제공구간소통정보가 정체, 지체인 경우만 하단 소통정보를 표출함 // 도형식 배경셀에 등록된 구간에 대해서 표출하도록함 if (trafIfscId != 0L && !isIfscTraf) { // 소통정보는 존재하지만 지체, 정체가 없는 경우 하단 소통정보를 표출못하게 된다. // 만일 하단 고정문자가 존재하는 경우 하단 고정문자를 표출하면 되지만 // 고정문자가 존재하기 않으면 하단에 표출할 정보가 없으므로 첫번째 구간의 정보를 표출하도록 한다. if (!vmsForm.isBottomFixedText()) { isIfscTraf = true; // 첫번째 소통정보가 표출되도록 함 trafIfscCnt = 1; } } } // 하단에 VMS 축 소통정보를 표출해야 하는 경우 if (vmsForm.isBottomTrfAxis()) { // 도형식 소통정보 폼일때 하단에 VMS 축 소통정보를 표출해야 하는 경우 다중폼이 생성됨 // 축 소통정보인 경우 모든 축에 대해 소통정보를 표출, 최대 표출설정값이 설정된 경우 설정값만큼만 표출되게 수정(20200515) if (axisIfscId != 0L && !isAxisTraf) { // 하단 축 소통정보가 없는 경우 하단 소통정보를 표출못하게 된다. // 만일 하단 고정문자가 존재하는 경우 하단 고정문자를 표출하면 되지만 // 고정문자가 존재하기 않으면 하단에 표출할 정보가 없으므로 첫번째 구간의 정보를 표출하도록 한다. if (!vmsForm.isBottomFixedText()) { isAxisTraf = true; // 첫번째 소통정보가 표출되도록 함 trafAxisCnt = 1; } } } if (!isIfscTraf && !isAxisTraf) { // 하단에 표출할 소통정보가 존재하지 않는 경우 TbVmsScheduleDto trafSchedule = schedule.clone(); trafSchedule.initTrafId(); vmsObj.getSchedule().add(trafSchedule); return; } int fromMaxCnt = 0; List ifscIds = new ArrayList<>(); if (isIfscTraf) { fromMaxCnt = trafIfscCnt; if (this.config.getBottomTrafficMax() > 0 && trafIfscCnt > this.config.getBottomTrafficMax()) { fromMaxCnt = this.config.getBottomTrafficMax(); } if (this.config.getBottomTrafficCycle() > 0) { int dsplTm = figureDisplayTm / trafIfscCnt; if (dsplTm < this.config.getBottomTrafficCycle()) { figureDisplayTm = this.config.getBottomTrafficCycle(); } else { figureDisplayTm = dsplTm; } } // 정보제공구간 정체정보 표출 for (Map.Entry e : backTrafSymb.getCellMap().entrySet()) { TbVmsSymbIfscDto cell = e.getValue(); if (cell.isDup()) { continue; } TbVmsIfscTrafDto ifscTraf = this.ifscService.find(cell.getVmsIfscId()); if (ifscTraf == null || "Y".equals(ifscTraf.getAxisYn())) { continue; } if (3 == ifscTraf.getCmtrGradCd()) { ifscIds.add(cell.getVmsIfscId()); } } // 정보제공구간 지체정보 표출 for (Map.Entry e : backTrafSymb.getCellMap().entrySet()) { TbVmsSymbIfscDto cell = e.getValue(); if (cell.isDup()) { continue; } TbVmsIfscTrafDto ifscTraf = this.ifscService.find(cell.getVmsIfscId()); if (ifscTraf == null || "Y".equals(ifscTraf.getAxisYn())) { continue; } if (2 == ifscTraf.getCmtrGradCd()) { ifscIds.add(cell.getVmsIfscId()); } } if (ifscIds.isEmpty() && trafIfscId != 0L && !vmsForm.isBottomFixedText()) { // 지정체구간이 없고 하단 고정문자가 없으면서 첫번째 정보제공구간 데이터가 존재하는 경우 ifscIds.add(trafIfscId); } } if (isAxisTraf) { fromMaxCnt = trafAxisCnt; if (this.config.getBottomTrafficCycle() > 0) { int dsplTm = figureDisplayTm / trafAxisCnt; if (dsplTm < this.config.getBottomTrafficCycle()) { figureDisplayTm = this.config.getBottomTrafficCycle(); } else { figureDisplayTm = dsplTm; } } // 축 소통정보 표출 for (Map.Entry e : backTrafSymb.getCellMap().entrySet()) { TbVmsSymbIfscDto cell = e.getValue(); if (cell.isDup()) { continue; } TbVmsIfscTrafDto ifscTraf = this.ifscService.find(cell.getVmsIfscId()); if (ifscTraf == null || !"Y".equals(ifscTraf.getAxisYn())) { continue; } if (0 != ifscTraf.getCmtrGradCd()) { ifscIds.add(cell.getVmsIfscId()); } } if (ifscIds.isEmpty() && axisIfscId != 0L && !vmsForm.isBottomFixedText()) { // 지정체구간이 없고 하단 고정문자가 없으면서 첫번째 정보제공구간 데이터가 존재하는 경우 ifscIds.add(axisIfscId); } } if (ifscIds.isEmpty()) { // 하단에 표출할 정보가 없는 경우 TbVmsScheduleDto trafSchedule = schedule.clone(); trafSchedule.initTrafId(); vmsObj.getSchedule().add(trafSchedule); } else { for (int ii = 0; ii < ifscIds.size() && ii < fromMaxCnt; ii++) { TbVmsScheduleDto trafSchedule = schedule.clone(); trafSchedule.setDnldFormId(schedule.getDnldFormId()+ii); trafSchedule.initTrafId(); trafSchedule.setVmsIfscId(ifscIds.get(ii)); trafSchedule.setFrstVmsIfscId(ifscIds.get(ii)); trafSchedule.setDsplHh(figureDisplayTm); vmsObj.getSchedule().add(trafSchedule); } } } /** * VMS 표출 스케쥴 정보를 조회 */ public void loadVmsDsplSchedule() { Elapsed elapsed = new Elapsed(); List result = this.mapper.selectVmsDsplSchedule(); result.forEach(data -> { TbVmsCtlrDto vmsObj = this.repoService.getCtlrMap(data.getVmsCtlrNmbr()); if (vmsObj == null) { log.error("VmsManageService.loadVmsDsplSchedule: Not Found VMS {}, Schedule Phase {}.", data.getVmsCtlrNmbr(), data.getPhase()); return; } TbVmsFormDto vmsForm = this.formService.find(data.getVmsFormId()); if (vmsForm == null) { log.error("VmsManageService.loadVmsDsplSchedule: VMS {}, Not Found Form {}.", data.getVmsCtlrNmbr(), data.getVmsFormId()); return; } eVmsScheduleType vmsSchFormType = eVmsScheduleType.getValue(data.getVmsSchFormType()); if (vmsSchFormType == null) { log.error("VmsManageService.loadVmsDsplSchedule: Unknown Form Schedule Type: VMS({}), FormId({}), FormScheduleType({})", data.getVmsCtlrNmbr(), data.getVmsFormId(), data.getVmsSchFormType()); return; } eVmsFormType vmsFormType = eVmsFormType.getValue(vmsForm.getVmsFormTypeCd()); if (vmsFormType == null) { log.error("VmsManageService.loadVmsDsplSchedule: Unknown Form Type: VMS({}), FormId({}), FormScheduleType({})", data.getVmsCtlrNmbr(), data.getVmsFormId(), vmsForm.getVmsFormTypeCd()); return; } // 조회정렬은 기본,고정,자동(돌발,공사,행사,우회,교통,정체폼) 순으로 조회된다. // 따라서 각 폼에 대한처리를 수행하면 된다. // ==> 신규작업에서 폼 표출 우선순위적용함 ==> 조회정렬이 영향이 있는지 확인해야함. // eFormTp_traf_1 = 11, // 소통상황(1단) // eFormTp_traf_2 = 12, // 소통상황(2단) // eFormTp_traf_3 = 13, // 소통상황(3단) // eFormTp_traf_4 = 14, // 소통상황(4단) boolean isIncidentForm = false; if (vmsSchFormType == eVmsScheduleType.eSchTp_traffic && vmsFormType == eVmsFormType.eFormTp_traf_1) { // 교통정보스케쥴이고 폼의 유형이 소통정보(1단) 인경우 // 해당 폼이 돌발이나 이벤트가 등록되어 있다면 폼을 생성하지 않는다. Long frstVmsIfscId = data.getFrstVmsIfscId(); if (frstVmsIfscId != null && frstVmsIfscId != 0L) { for (int ii = 0; ii < vmsObj.getSchedule().getUnits().size(); ii++) { TbVmsScheduleDto schedule = vmsObj.getSchedule().getUnits().get(ii); eVmsScheduleType scheduleFormType = eVmsScheduleType.getValue(schedule.getVmsSchFormType()); if (scheduleFormType == eVmsScheduleType.eSchTp_incident || //돌발 scheduleFormType == eVmsScheduleType.eSchTp_gongsa || //공사/행사 scheduleFormType == eVmsScheduleType.eSchTp_deture //우회도로 ) { if (schedule.getEvent() != null && Objects.equals(schedule.getEvent().getVmsIfscId(), frstVmsIfscId)) { isIncidentForm = true; break; } } } } } if (isIncidentForm) { log.error("VmsManageService.loadVmsDsplSchedule: VMS {}, Form {}, IFSC ID {} Incident Occurred.", vmsObj.getVmsCtlrNmbr(), vmsForm.getVmsFormId(), data.getFrstVmsIfscId()); return; } final int[] formIdx = new int[1]; TbVmsScheduleDto schedule = data.toDto(); switch(vmsSchFormType) { case eSchTp_traffic: // 교통정보 loadVmsDsplTrafSchedule(vmsObj, vmsForm, schedule); break; case eSchTp_incident: // 돌발 // 돌발 스케줄인 경우 해당 VMS 에 발생한 모든 돌발 정보를 표출하도록 스케줄 추가 formIdx[0] = 0; vmsObj.getIncident().getUnits().forEach(incd -> { TbVmsScheduleDto incdSchedule = schedule.clone(); incdSchedule.setDnldFormId(schedule.getDnldFormId() + formIdx[0]++); incdSchedule.setVmsIfscId(incd.getVmsIfscId()); incdSchedule.setEvent(incd); vmsObj.getSchedule().add(incdSchedule); }); break; case eSchTp_gongsa: // 공사/행사문안 // 공사/행사 스케줄인 경우 해당 VMS 에 발생한 모든 돌발 정보를 표출하도록 스케줄 추가 formIdx[0] = 0; vmsObj.getEvent().getUnits().forEach(event -> { TbVmsScheduleDto eventSchedule = schedule.clone(); eventSchedule.setDnldFormId(schedule.getDnldFormId() + formIdx[0]++); eventSchedule.setVmsIfscId(event.getVmsIfscId()); eventSchedule.setEvent(event); vmsObj.getSchedule().add(eventSchedule); }); break; case eSchTp_hongbo: // 홍보 TbVmsScheduleDto hongboSchedule = schedule.clone(); vmsObj.getSchedule().add(hongboSchedule); break; case eSchTp_deture: // 우회도로 // 돌발발생한 구간중 우회도로 구간이 있는경우 formIdx[0] = 0; vmsObj.getIncident().getUnits().forEach(incd -> { if (incd.getDetrId() == 0L || incd.getVmsIfscId() == 0) { return; } TbVmsScheduleDto detureSchedule1 = schedule.clone(); detureSchedule1.setDnldFormId(schedule.getDnldFormId() + formIdx[0]++); detureSchedule1.setVmsIfscId(incd.getVmsIfscId()); detureSchedule1.setEvent(incd); vmsObj.getSchedule().add(detureSchedule1); }); // 공사/행사 발생한 구간중 우회도로 구간이 있는경우 vmsObj.getEvent().getUnits().forEach(event -> { if (event.getDetrId() == 0L || event.getVmsIfscId() == 0) { return; } TbVmsScheduleDto detureSchedule2 = schedule.clone(); detureSchedule2.setDnldFormId(schedule.getDnldFormId() + formIdx[0]++); detureSchedule2.setVmsIfscId(event.getVmsIfscId()); detureSchedule2.setEvent(event); vmsObj.getSchedule().add(detureSchedule2); }); break; case eSchTp_congest: // 정체상황 formIdx[0] = 0; vmsObj.getRltnIfscMap().forEach((key, cngs) -> { if (!cngs.isUsed() || !cngs.isCngstCnfmYn()) { // 정체판정이 아닌경우 return; } if (cngs.getCngstCnt() < this.config.getCngstContCount()) { // 설정되어 있는 정체판정 횟수보다 작으면 정체아님. 정체가 연속에서 반복되는 최소 갯수임... return; } if (vmsObj.getCngstForms() < vmsObj.getMaxCngstForm()) { vmsObj.setCngstForms(cngs.getCngstCnt()+1); vmsObj.setExistCngsForm(true); TbVmsScheduleDto congestSchedule = schedule.clone(); congestSchedule.setDnldFormId(schedule.getDnldFormId() + formIdx[0]++); congestSchedule.setFrstVmsIfscId(cngs.getVmsIfscId()); congestSchedule.setVmsIfscId(cngs.getVmsIfscId()); vmsObj.getSchedule().add(congestSchedule); } }); break; case eSchTp_video: //동영상 // 동영상명칭이 설정되지 않은 것은 표출하지 않는다. //if (data.getSymbLibNmbr() != 0 && data.getSymbLibNmbr() != 200 && !"".equals(data.getStrmAddr())) { TbVmsScheduleDto videoSchedule = schedule.clone(); vmsObj.getSchedule().add(videoSchedule); } break; case eSchTp_stream: //스트리밍영상 //스트리밍주소가 설정되지 않은 것은 표출하지 않는다. //if (data.getSymbLibNmbr() == 300 && !"".equals(data.getStrmAddr())) { TbVmsScheduleDto streamSchedule = schedule.clone(); vmsObj.getSchedule().add(streamSchedule); } break; case eSchTp_atmp: //9:대기환경 Long atmpSttnNmbr = 0L; boolean isAtmp = false; for (int ii = 0; ii < vmsForm.getObjects().size(); ii++) { TbVmsFormObjectDto tmpFormObj = vmsForm.getObjects().get(ii); /** 90 401 @관측장소 Y 90 402 @PM10 Y 90 403 @PM2.5 Y 90 404 @PM10등급 Y 90 405 @PM2.5등급 Y 90 406 @통합대기등급 이미지 Y 90 407 @미세먼지등급 이미지 Y 90 408 @초미세먼지등급 이미지 Y 90 409 @통합대기등급 Y 90 410 @통합대기 Y 90 411 @오존 Y 90 412 @오존등급 Y 90 413 @오존등급이미지 Y */ if (tmpFormObj.getVmsFormObjectTypeCd() >= 401 && tmpFormObj.getVmsFormObjectTypeCd() <= 413) { atmpSttnNmbr = tmpFormObj.getVmsIfscId(); TbVmsAtmpDto atmpObj = this.atmpService.find(atmpSttnNmbr); if (atmpObj == null) { log.error("VmsManageService.loadVmsDsplSchedule: VMS {}, ATMP Form {}, Not Found AtmpSttnNmb {}.", vmsObj.getVmsCtlrNmbr(), vmsForm.getVmsFormId(), atmpSttnNmbr); continue; } if (atmpObj.isSuccess()) { isAtmp = true; break; } } } if (isAtmp) { TbVmsScheduleDto atmpSchedule = schedule.clone(); atmpSchedule.setFrstVmsIfscId(atmpSttnNmbr); vmsObj.getSchedule().add(atmpSchedule); } else { log.error("VmsManageService.loadVmsDsplSchedule: VMS {}, ATMP Form {}, Atmp Traffic Failed.", vmsObj.getVmsCtlrNmbr(), vmsForm.getVmsFormId()); } break; case eSchTp_park: //10:주차정보 boolean isParkingForm = false; for (int ii = 0; ii < vmsForm.getObjects().size(); ii++) { TbVmsFormObjectDto tmpFormObj = vmsForm.getObjects().get(ii); /** 100 101 @주차장명 N 100 102 @주차면수 Y 100 103 @주차가능면수 Y 100 104 @주차혼잡도 Y */ if (tmpFormObj.getVmsFormObjectTypeCd() >= 101 && tmpFormObj.getVmsFormObjectTypeCd() <= 104) { TbVmsParkDto parkObj = this.parkService.find(tmpFormObj.getVmsIfscId()); if (parkObj == null) { log.error("VmsManageService.loadVmsDsplSchedule: VMS {}, Parking Form {}, Not Found Parking {}.", vmsObj.getVmsCtlrNmbr(), vmsForm.getVmsFormId(), tmpFormObj.getVmsIfscId()); continue; } if (parkObj.isSuccess()) { isParkingForm = true; break; } } } if (isParkingForm) { TbVmsScheduleDto parkSchedule = schedule.clone(); vmsObj.getSchedule().add(parkSchedule); } else { log.error("VmsManageService.loadVmsDsplSchedule: VMS {}, Parking Form {}, Parking Congest Failed.", vmsObj.getVmsCtlrNmbr(), vmsForm.getVmsFormId()); } break; case eSchTp_evehicle: //11:긴급차량우선신호 if (vmsForm.getVmsFormDsplDrctCd() == 0) { vmsObj.setEvehIngForm(true); } else { vmsObj.setEvehEndForm(true); schedule.setDsplHh(60); } TbVmsScheduleDto evehSchedule = schedule.clone(); vmsObj.getSchedule().add(evehSchedule); break; default: break; } }); log.info("VmsManageService.loadVmsDsplSchedule: {} ms.", elapsed.milliSeconds()); } /** * VMS 운영모드 정보 조회 */ public void loadVmsOperationMode() { Elapsed elapsed = new Elapsed(); List result = this.mapper.selectVmsOperMode(); result.forEach(data-> { TbVmsCtlrDto vmsObj = this.repoService.getCtlrMap(data.getVmsCtlrNmbr()); if (vmsObj == null) { log.error("VmsManageService.loadVmsOperationMode: Not Found VMS {}.", data.getVmsCtlrNmbr()); return; } if (!"A".equals(data.getOperMode()) && !"F".equals(data.getOperMode()) && !"B".equals(data.getOperMode())) { data.setOperMode("A"); } String oldOperMode = vmsObj.getOperMode(); vmsObj.setOperMode(data.getOperMode()); vmsObj.setMaxPhaseNum(Math.min(this.config.getMaxDownloadForms(), data.getVmsMaxPhaseNum())); // VMS 별 정체폼갯수를 제한하는 경우 여기에서 처리하도록 하자 vmsObj.setMaxCngstForm(Math.min(this.config.getMaxCngstForms(), VmsConstants.VMS_MAX_CNGS_FORM)); if (data.getOperMode().equals(oldOperMode)) { // TODO: 화면 업데이트 } }); log.info("VmsManageService.loadVmsOperationMode: {} ms.", elapsed.milliSeconds()); } public void initProvide(TbVmsCtlrDto AObj) { this.repoService.getCtlrMap().forEach((key, obj) -> { if (AObj == null || obj.getVmsCtlrNmbr() == AObj.getVmsCtlrNmbr()) { obj.setProvide(true); } }); } public void clearVmsProvideMode() { String dsplDt = ItsUtils.getSysTime(); this.repoService.getCtlrMap().forEach((key, obj) -> { obj.getEvechile().getUnits().clear(); obj.setEvehIngForm(false); obj.setEvehEndForm(false); obj.getSchedule().getUnits().clear(); obj.getIncident().getUnits().clear(); obj.getEvent().getUnits().clear(); obj.getFormManager().clear(); obj.setCngstForms(0); obj.setMaxCngstForm(this.config.getMaxCngstForms()); obj.setExistCngsForm(false); // if (!obj.isProvide()) { // return; // } obj.getControlMode().setMaxDisplayForm(0); obj.getControlMode().setEnable(false); obj.getControlMode().setSvcDate(dsplDt); obj.getControlMode().setSaveFlag(true); obj.getControlMode().setTimer(System.currentTimeMillis()); obj.getControlMode().setResult(false); }); } /** * VMS 다운로드 폼 정보 생성 */ public void jobMakeDownloadVmsForm() { log.info("VmsManageService.jobMakeDownloadVmsForm: START."); Elapsed elapsed = new Elapsed(); if (this.repoService.isStaticCycle()) { loadVmsOperationMode(); // 운영모드 조회 initProvide(null); } clearVmsProvideMode(); makeVmsScenarioForm(); // 시나리오정보 로딩 makeVmsProvideForm(); // 시나리오에 따른 폼 정보 생성 makeVmsDatabaseForm(); // 폼 이미지 생성 /** * 데이터베이스 처리 프로세스로 VMS 폼 다운로드 정보를 보낸다. * 데이터베이스 처리 프로레스에서 제어기의 네트워크 상태에 따라서 통신 정상인 제어기로 데이터를 전송한다. */ this.repoService.setDsplDt(ItsUtils.getSysTime()); this.dbmsDataProcess.add(new DbmsData(DbmsDataType.DBMS_DATA_VMS_FORM_DOWNLOAD, this.repoService.isStaticCycle(), this.repoService.getDsplDt())); log.info("VmsManageService.jobMakeDownloadVmsForm: {} ms.", elapsed.milliSeconds()); } /** * VMS FORM 데이터를 생성한다. */ public void makeVmsScenarioForm() { log.info("VmsManageService.makeVmsScenarioForm: START."); Elapsed elapsed = new Elapsed(); if (this.config.isLoadDb()) { loadDb(); } this.atmpService.loadDb(); // 기상정보 if (this.config.isUseParking()) { this.parkService.loadDb(); // 주차정보 } loadEventOccrInfo(); // 돌발정보조회 this.ifscService.loadDb(); // VMS 정보제공구간 교통정보 if (this.repoService.isStaticCycle()) { // 정주기 가공일때 처리해야 함 congestJudgment(); // 정체판정 this.repoService.setStaticCycle(false); } loadVmsDsplSchedule(); log.info("VmsManageService.makeVmsScenarioForm: {} ms.", elapsed.milliSeconds()); } public void makeVmsProvideForm() { log.info("VmsManageService.makeVmsProvideForm: START."); Elapsed elapsed = new Elapsed(); this.repoService.getCtlrMap().forEach((ctlrNmbr, vmsObj) -> { if ("Y".equals(vmsObj.getDelYn())) { return; } VmsSchedule scheObj = vmsObj.getSchedule(); int downLoadForms = Math.min(vmsObj.getMaxPhaseNum(), scheObj.size()); vmsObj.getControlMode().setMaxDisplayForm(downLoadForms); this.config.makeDirectory(vmsObj.getLocalFormDir(), "VMS " + vmsObj.getVmsCtlrNmbr() + " Directory."); boolean isEVehIngForm = vmsObj.isEvehIngForm() && vmsObj.getEvechile().isOcrr(); // 폼이 존재하고 데이터 발생 boolean isEVehEndForm = vmsObj.isEvehEndForm() && vmsObj.getEvechile().isEnd(); // 폼이 존재하고 데이터 발생 for (int scheduleIdx = 0; scheduleIdx < scheObj.size(); scheduleIdx++) { TbVmsScheduleDto schedule = scheObj.getUnits().get(scheduleIdx); if (vmsObj.isExistCngsForm() && !schedule.isDsplCngsYn()) { // 해당 제어기에 정체폼이 존재하는 경우 스케쥴 폼이 정체일때 표출하지 않는 경우 폼을 생성하지 않는다. log.info("VmsManageService.makeVmsProvideForm: VMS {}, Congest continuous {}/{}.", ctlrNmbr, vmsObj.isExistCngsForm(), schedule.isDsplCngsYn()); continue; } TbVmsFormDto vmsForm = this.formService.find(schedule.getVmsFormId()); if (vmsForm == null) { log.error("VmsManageService.makeVmsProvideForm: VMS {}, Not Found Form {}.", ctlrNmbr, schedule.getVmsFormId()); continue; } eVmsScheduleType vmsSchFormType = eVmsScheduleType.getValue(schedule.getVmsSchFormType()); if (vmsSchFormType == null) { log.error("VmsManageService.makeVmsProvideForm: Unknown Form Schedule Type: VMS({}), FormId({}), FormScheduleType({})", ctlrNmbr, schedule.getVmsFormId(), schedule.getVmsSchFormType()); continue; } eVmsFormType vmsFormType = eVmsFormType.getValue(vmsForm.getVmsFormTypeCd()); if (vmsFormType == null) { log.error("VmsManageService.makeVmsProvideForm: Unknown Form Type: VMS({}), FormId({}), FormScheduleType({})", ctlrNmbr, schedule.getVmsFormId(), vmsForm.getVmsFormTypeCd()); continue; } if (isEVehIngForm) { // 긴급차량 진행중 메시지 표출 if (vmsSchFormType != eVmsScheduleType.eSchTp_evehicle || vmsForm.getVmsFormDsplDrctCd() != 0) { // 긴급차량우선신호 진행중 일때 스케쥴 유형 및 폼유형이 맞지 않으면 리턴 // 단일 메시지로 표출하는 경우 // log.info("VmsManageService.makeVmsProvideForm: VMS {}, FORM {}, EVehicle Ing {}. {} DsplDrctCd {}.", // ctlrNmbr, vmsForm.getVmsFormId(), isEVehIngForm, vmsSchFormType, vmsForm.getVmsFormDsplDrctCd()); continue; } } else { if (vmsSchFormType == eVmsScheduleType.eSchTp_evehicle && vmsForm.getVmsFormDsplDrctCd() == 0) { // log.info("VmsManageService.makeVmsProvideForm: VMS {}, FORM {}, EVehicle Ing {}. {} DsplDrctCd {}.", // ctlrNmbr, vmsForm.getVmsFormId(), isEVehIngForm, vmsSchFormType, vmsForm.getVmsFormDsplDrctCd()); continue; } } if (isEVehEndForm) { // 긴급차량 운영종료 메시지 표출 // 운영종료 메시지는 기타 메시지와 같이 내려보낸다. 단, 표출시간을 60초로 해서 내려보내자. // if (vmsSchFormType != eVmsScheduleType.eSchTp_evehicle || vmsForm.getVmsFormDsplDrctCd() != 1) { // // 긴급차량우선신호 운영종료 일때 스케쥴 유형 및 폼유형이 맞지 않으면 리턴 // // 단일메시지로 표출하는 경우 // continue; // } } else { if (vmsSchFormType == eVmsScheduleType.eSchTp_evehicle && vmsForm.getVmsFormDsplDrctCd() == 1) { // log.info("VmsManageService.makeVmsProvideForm: VMS {}, FORM {}, EVehicle End {}. {} DsplDrctCd {}.", // ctlrNmbr, vmsForm.getVmsFormId(), isEVehEndForm, vmsSchFormType, vmsForm.getVmsFormDsplDrctCd()); continue; } } // 소통정보 표출폼 인 경우 표출할 구간의 소통정보가 존재하지 않는 경우 폼을 생성하지 않도록 한다. int reqTraffic = 0; int setTraffic = 0; switch (vmsFormType) { case eFormTp_traf_1: reqTraffic = 1; break; // = 11, // 소통상황(1단) case eFormTp_traf_2: reqTraffic = 2; break; // = 12, // 소통상황(2단) case eFormTp_traf_3: reqTraffic = 3; break; // = 13, // 소통상황(3단) case eFormTp_traf_4: reqTraffic = 4; break; // = 14, // 소통상황(4단) default: break; } if (reqTraffic > 0) { int ss; Long[] vmsIfscId = { schedule.getFrstVmsIfscId(), schedule.getSecdVmsIfscId(), schedule.getThirVmsIfscId(), schedule.getFourVmsIfscId() }; Long[] imgIfscId = { schedule.getFrstImgIfscId(), schedule.getSecdImgIfscId(), schedule.getThirImgIfscId(), schedule.getFourImgIfscId() }; for (ss = 0; ss < 4; ss++) { if (vmsIfscId[ss] == 0L) { vmsIfscId[ss] = imgIfscId[ss]; } if (vmsIfscId[ss] != 0L) { setTraffic++; } } if (setTraffic != 0 && (reqTraffic > setTraffic)) { //실제 소통정보 폼 갯수보다 할당된 구간이 적은 경우에 해당함 reqTraffic = setTraffic; } setTraffic = 0; for (ss = 0; ss < 4; ss++) { if (vmsIfscId[ss] == 0L) continue; TbVmsIfscTrafDto ifscTraf = this.ifscService.find(vmsIfscId[ss]); if (ifscTraf != null && 0 != ifscTraf.getCmtrGradCd()) { setTraffic++; } } if (reqTraffic != setTraffic) { log.error("VmsManageService.makeVmsProvideForm: No Traffic: VMS({}), FormId({}), Req {}, Set {}.", ctlrNmbr, schedule.getVmsFormId(), reqTraffic, setTraffic); continue; } } // 1,2,3,4 단 소통정보 표출 폼인 경우 // 스케줄에 따른 VMS FORM 을 생성한다. VmsForm form = vmsObj.getFormManager().addForm(schedule.getVmsFormId(), schedule.getDnldFormId()); form.initDownload(vmsObj, vmsForm, schedule); for (int objectIdx = 0; objectIdx < vmsForm.getObjects().size(); objectIdx++) { if (objectIdx >= VmsConstants.VMS_MAX_FORM_OBJECTS) { log.error("VmsManageService.makeVmsProvideForm: VMS({}), FormId({}), Form Object count overflow {} EA.", ctlrNmbr, schedule.getVmsFormId(), vmsForm.getObjects().size()); break; } TbVmsFormObjectDto obj = vmsForm.getObjects().get(objectIdx); if (vmsFormType == eVmsFormType.eFormTp_figure) { // 도형식 배경소통정보 폼인 경우 하단에 표출할 정보가 없는 경우 하단 소통정보 객체는 생성하지 않도록 하자. switch(obj.getVmsFormObjectTypeCd()) { case 0: //문자열 case 1: //심볼 case 2: //이미지 //N:일반(모두표출하는것) //T:소통정보(소통정보가 있는 경우에만 표출하는것) //F:하단고정(소통정보가 없는 경우에만 표출하는것) if (schedule.getVmsIfscId() == 0L) { // 표출할 소통정보가 없는 경우 교통정보 표출인 경우 하단정보 생성하지 않음 if ("T".equals(obj.getTrfcFillCd())) { continue; } } else { // 표출할 소통정보가 있는 경우 고정문자 표출인 경우 하단정보 생성하지 않음 if ("F".equals(obj.getTrfcFillCd())) { continue; } } break; case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: if (schedule.getVmsIfscId() == 0L) { continue; //하단에 표출할 정보제공구간이 없는 경우임 } if (obj.getVmsFormObjectTypeCd() == 17) { // 하단 소통정보이미지 schedule.setFrstImgIfscId(schedule.getVmsIfscId()); } break; default: break; } } // (vmsFormType == eVmsFormType.eFormTp_figure) VmsFormObject formObj = form.addFormObject(obj.getVmsFormObjectId()); formObj.setFormObjectInfo(this.fontService.getFontName(obj.getVmsFontNameCd()), obj); if (formObj.getBlinking() == 1) { // 객체 Blinking 정보가 다운로드 될때 폼정보로 다운로드 되지 않기 때문에 // Blinking 하기 위해서는 객체로 다운로드 하여야 한다. form.setObjectDownload(true); form.setVmsFormDsplDrctCd(1); } if (obj.getVmsFormObjectTypeCd() == 200 || obj.getVmsFormObjectTypeCd() == 300) { // 200:동영상이미지, 300:스트리밍영상이미지 if (obj.getVmsFormObjectTypeCd() == 200) { formObj.setVideoFileName(obj.getVideoFileName()); formObj.setTextData(obj.getVideoFileName()); } else if (obj.getVmsFormObjectTypeCd() == 300) { formObj.setStrmAddr(obj.getStrmAddr()); formObj.setTextData(obj.getStrmAddr()); } form.setObjectDownload(true); formObj.setMemSymbLibNmbr(obj.getSymbLibNmbr()+"0"); //if (obj.getVmsFormObjectTypeCd() == 200) { if (formObj.getDsplWidth() == 0 || formObj.getDsplHeight() == 0) { formObj.setPosX(0); // NUMBER(5) Y VMS 표출 X좌표 formObj.setPosY(0); // NUMBER(5) Y VMS 표출 Y좌표 formObj.setDsplWidth(form.getWidth()); // NUMBER(5) Y 0 VMS 표출 넓이 formObj.setDsplHeight(form.getHeight());// NUMBER(5) Y 0 VMS 표출 높이 } TbVmsSymbLibDto symb = this.symbService.find(formObj.getMemSymbLibNmbr()); if (symb == null) { log.error("VmsManageService.makeVmsProvideForm: VMS({}), FormId({}), Form Object Video Symbol Not Found {}.", ctlrNmbr, schedule.getVmsFormId(), formObj.getMemSymbLibNmbr()); } else { if (form.getDsplHh() == 0 || form.getDsplHh() > symb.getPlayTm()) { if (symb.getPlayTm() > 0) { form.setDsplHh(Math.toIntExact(symb.getPlayTm())); } } } } } if (formObj.getObjectKind() != eVmsFormObjectKind.OBJECT_TEXT) { if (obj.getVmsFormObjectTypeCd() == 200 || obj.getVmsFormObjectTypeCd() == 300) { // 200:동영상이미지, 300:스트리밍영상이미지 TbVmsSymbLibDto symb = this.symbService.find(formObj.getMemSymbLibNmbr()); if (symb != null) { formObj.setImageData(symb.getImageData()); } else { formObj.setImageData(formObj.getImageData()); log.error("VmsManageService.makeVmsProvideForm: VMS({}), FormId({}), Symbol Not Found {} set form object image data.", ctlrNmbr, schedule.getVmsFormId(), formObj.getMemSymbLibNmbr()); } } else if (obj.getVmsFormObjectTypeCd() == 406 || //@통합대기등급 이미지 obj.getVmsFormObjectTypeCd() == 407 || //@미세먼지등급 이미지 obj.getVmsFormObjectTypeCd() == 408 || //@초미세먼지등급 이미지 obj.getVmsFormObjectTypeCd() == 413 ) //@오존등급이미지 { TbVmsAtmpDto atmp = this.atmpService.find(obj.getVmsIfscId()); if (atmp != null && atmp.isSuccess()) { // 관측장소 정보가 존재하는 경우에만 대기환경이미지를 폼에 적용한다. int atmpGrad = 0; switch(obj.getVmsFormObjectTypeCd()) { case 406: atmpGrad = ItsUtils.parseIntDef(atmp.getIntgAtmpGrad(), 1); break; case 407: atmpGrad = ItsUtils.parseIntDef(atmp.getPm101hhGrad(), 1); break; case 408: atmpGrad = ItsUtils.parseIntDef(atmp.getPm251hhGrad(), 1); break; case 413: atmpGrad = ItsUtils.parseIntDef(atmp.getO3Grad(), 1); break; } if (atmpGrad > 0) { atmpGrad--; } TbVmsSymbLibDto symb = this.symbService.find(formObj.getMemSymbLibNmbr()); if (symb != null && symb.getGradSymbLibNmbrList().size() >= atmpGrad) { TbVmsSymbLibDto atmpSymb = this.symbService.find(symb.getGradSymbLibNmbrList().get(atmpGrad)); if (atmpSymb != null) { formObj.setImageData(atmpSymb.getImageData()); formObj.setMemSymbLibNmbr(symb.getGradSymbLibNmbrList().get(atmpGrad)); formObj.setBitmapId(atmpSymb.getDnldSymbLibNmbr()); } else { formObj.setImageData(symb.getImageData()); formObj.setMemSymbLibNmbr(formObj.getMemSymbLibNmbr()); } } else { formObj.setImageData(formObj.getImageData()); log.error("VmsManageService.makeVmsProvideForm: VMS({}), FormId({}), Atmp Symbol Not Found {} set form object image data.", ctlrNmbr, schedule.getVmsFormId(), formObj.getMemSymbLibNmbr()); } } } else if (obj.getVmsFormObjectTypeCd() == 1 || obj.getVmsFormObjectTypeCd() == 2) { // 심볼, 이미지 TbVmsSymbLibDto symb = this.symbService.find(formObj.getMemSymbLibNmbr()); if (symb != null) { formObj.setImageData(symb.getImageData()); } else { formObj.setImageData(obj.getImagData()); log.error("VmsManageService.makeVmsProvideForm: VMS({}), FormId({}), Atmp Symbol Not Found {} set form symbol object image data.", ctlrNmbr, schedule.getVmsFormId(), formObj.getMemSymbLibNmbr()); } } else { formObj.setImageData(obj.getImagData()); } } // (formObj.getObjectKind() != eVmsFormObjectData.text_object_data.getValue()) // 폼객체 유형별 Fill In switch(formObj.getObjectType()) { case 0: // 고정문자열 case 201: // 동영상파일명 case 301: // 스트리밍영상주소 formObj.changeTextPosition(this.config.getFontSizeRatio()); break; case 1: // 심볼 case 2: // 파일이미지 TbVmsSymbLibDto tSymb = this.symbService.find(formObj.getMemSymbLibNmbr()); if (tSymb == null) { log.error("VmsManageService.makeVmsProvideForm: VMS({}), FormId({}), Not Found Symbol, File Image Symbol {}.", ctlrNmbr, schedule.getVmsFormId(), formObj.getMemSymbLibNmbr()); } else { formObj.setImageData(tSymb.getImageData()); } //formObj.setMemSymbLibNmbr(formObj.getMemSymbLibNmbr()); break; case 17: // 1단,소통정보이미지1 case 27: // 2단,소통정보이미지2 case 37: // 3단,소통정보이미지3 case 47: // 4단,소통정보이미지4 case 167: // @우회소통정보이미지 TbVmsSymbLibDto symb = this.symbService.find(formObj.getMemSymbLibNmbr()); if (symb == null) { log.error("VmsManageService.makeVmsProvideForm: VMS({}), FormId({}), Not Found Traffic 1,2,3,4,detour Symbol {}.", ctlrNmbr, schedule.getVmsFormId(), formObj.getMemSymbLibNmbr()); continue; } formObj.setMemSymbLibNmbr(formObj.getMemSymbLibNmbr()); switch(formObj.getObjectType()) { case 167: // @우회소통정보이미지 case 17: formObj.setIfscId(schedule.getFrstImgIfscId()); break; // 1단,소통정보이미지1 case 27: formObj.setIfscId(schedule.getSecdImgIfscId()); break; // 2단,소통정보이미지2 case 37: formObj.setIfscId(schedule.getThirImgIfscId()); break; // 3단,소통정보이미지3 case 47: formObj.setIfscId(schedule.getFourImgIfscId()); break; // 4단,소통정보이미지4 } TbVmsIfscTrafDto ifscTraf = this.ifscService.find(formObj.getIfscId()); if (ifscTraf != null) { formObj.setIfscTrafGradCd(ifscTraf.getCmtrGradCd()); String trafImagId = symb.getSymbLibNmbr() + String.valueOf(ifscTraf.getCmtrGradCd()); TbVmsSymbLibDto trafSymb = this.symbService.find(trafImagId); if (trafSymb != null) { formObj.setMemSymbLibNmbr(trafImagId); formObj.setImageData(trafSymb.getImageData()); formObj.setBitmapId(trafSymb.getDnldSymbLibNmbr()); } else { formObj.setImageData(symb.getImageData()); } } else { log.error("VmsManageService.makeVmsProvideForm: VMS({}), FormId({}), Not Found IFSC Traffic 1,2,3,4,detour IFSC {}.", ctlrNmbr, schedule.getVmsFormId(), formObj.getIfscId()); formObj.setIfscTrafGradCd(0); formObj.setImageData(symb.getImageData()); } break; case 3: // 소통정보 배경이미지 TbVmsSymbLibDto bkSymb = this.symbService.find(formObj.getMemSymbLibNmbr()); if (bkSymb == null) { log.error("VmsManageService.makeVmsProvideForm: VMS({}), FormId({}), Not Found Bk Traffic Symbol {}.", ctlrNmbr, schedule.getVmsFormId(), formObj.getMemSymbLibNmbr()); continue; } formObj.setMemSymbLibNmbr(formObj.getMemSymbLibNmbr()); //formObj.setPosX(bkSymb.getPosX()); //formObj.setPosY(bkSymb.getPosY()); Image imgBmp = bkSymb.getImage(); // 원천이미지를 가지고 온다. if (imgBmp == null) { log.error("VmsManageService.makeVmsProvideForm: VMS({}), FormId({}), Image Data Error {}.", ctlrNmbr, schedule.getVmsFormId(), formObj.getMemSymbLibNmbr()); continue; } BufferedImage formImage = new BufferedImage(imgBmp.getWidth(null), imgBmp.getHeight(null), BufferedImage.TYPE_INT_RGB); Graphics2D g2d = formImage.createGraphics(); FloodFill floodFill = new FloodFill(imgBmp); floodFill.setAntialiased(false); bkSymb.getCellMap().forEach((cellId, cell) -> { if (!cell.isValid()) { return; } TbVmsIfscTrafDto cellTraf = this.ifscService.find(cell.getVmsIfscId()); if (cellTraf == null) { return; } int cmtrGradCd = cellTraf.getCmtrGradCd(); int orgColor = floodFill.getImage().getRGB(cell.getPosX(), cell.getPosY()); int trfColor = VmsSymbService.getGradColor(cmtrGradCd); if (orgColor != trfColor) { floodFill.fill(cell.getPosX(), cell.getPosY(), VmsSymbService.getTrafColor(cmtrGradCd)); } }); g2d.drawImage(floodFill.getImage(), 0, 0, imgBmp.getWidth(null), imgBmp.getHeight(null), null); ByteArrayOutputStream out = new ByteArrayOutputStream(); try { ImageIO.write(formImage, "bmp", out); } catch (IOException e) { log.error("VmsManageService.makeVmsProvideForm: Image Convert error: {}.", formObj.getMemSymbLibNmbr()); } g2d.dispose(); formObj.setImageData(out.toByteArray()); break; case 61: // 구간명 case 62: // 시점명 case 63: // 종점명 case 64: // 돌발유형 case 65: // 대응문구 case 66: // 통제유형 ==> 여기까지 돌발 case 71: // 발생장소 case 72: // INCD_TITL case 73: // 통제시점명 case 74: // 통제종점명 case 75: // 00차로 차단 case 76: // 00월00일 ~ 00월00일 case 77: // 대응문구 case 78: // @통제유형 ==> 여기까지 공사/행사 case 81: // 돌발종류 case 82: // 해당도로 case 83: // 우회도로 case 84: // 발생장소 ==> 여기까지 돌발 // 돌발문안, 공사/행사문안 임 // TB_VMS_FORM_OBJECT_TYPE 테이블에 유형추가하고 돌발화면에서 필요한 항목 추가, TB_INCD_OCRR_VMS 테이블에 컬럼추가해야함 formObj.setTextData(""); TbVmsIncdDto event = schedule.getEvent(); if (event != null) { switch(formObj.getObjectType()) { case 82: //해당도로 case 83: //우회도로 case 61: formObj.setTextData(event.getVmsIfscNm()); break; //@구간명(사용안함) case 62: //@시점명 case 73: formObj.setTextData(event.getStrtLctnNm()); break; //통제시점명 case 74: //통제종점명 case 63: formObj.setTextData(event.getEndLctnNm()); break; //@종점명 case 81: //돌발종류 case 64: formObj.setTextData(event.getVmsIncdDetlNm()); break; //@돌발유형 case 66: //@통제유형 case 78: formObj.setTextData(event.getVmsIncdRstrTypeNm()); break; //@통제유형 case 65: //@대응문구(사용안함-발생장소로 일단넣음) case 77: //대응문구(사용안함-발생장소로 일단넣음) case 84: //발생장소 case 71: formObj.setTextData(event.getOcrrLctnNm()); break; //발생장소 case 72: formObj.setTextData(event.getIncdTitl()); break; //@공사행사명 case 75: // 00차로 차단 int nLane = ItsUtils.parseIntDef(event.getIncdClsrLane(), 0); if (nLane == 111111) formObj.setTextData("차로 차단"); else if (nLane > 0) formObj.setTextData("일부 차단"); else formObj.setTextData(" "); break; case 76: //00월00일 ~ 00월00일 try { String strtDt = event.getIncdStrtDt(); String endDt = event.getIncdEndPrarDt(); String sFrom = strtDt.substring(4,6) + "월" + strtDt.substring(6,8) + "일 " + strtDt.substring(8,10) + "시"; String sTo = endDt.substring(4,6) + "월" + endDt.substring(6,8) + "일 " + endDt.substring(8,10) + "시"; formObj.setTextData(sFrom + " ~ " + sTo); } catch(Exception e) {} break; } } if ("".equals(formObj.getTextData())) { formObj.setTextData(" "); } formObj.changeTextPosition(this.config.getFontSizeRatio()); break; case 401: // @관측장소 case 402: // @PM10 case 403: // @PM2.5 case 404: // @PM10등급 case 405: // @PM2.5등급 case 409: // @통합대기등급 case 410: // @통합대기 case 411: // @오존 case 412: // @오존등급 TbVmsAtmpDto atmp = this.atmpService.find(obj.getVmsIfscId()); if (atmp == null) { log.error("VmsManageService.makeVmsProvideForm: VMS({}), FormId({}), Not Found Atmp {}.", ctlrNmbr, schedule.getVmsFormId(), obj.getVmsIfscId()); } else { String unitGap = ""; boolean isUnit = false; if (formObj.getTextData().contains(" -")) { isUnit = true; unitGap = " "; } else if (formObj.getTextData().contains("-")) { isUnit = true; } boolean isSetFontColor = true; int fontGradeColorCd = 0; if (formObj.getObjectType() == 401) { isSetFontColor = false; formObj.setTextData(atmp.getVmsDispNm()); } else if (formObj.getObjectType() == 402) { formObj.setTextData(atmp.getPm10ValDesc(unitGap, isUnit)); fontGradeColorCd = atmp.getPm10Color(); } else if (formObj.getObjectType() == 403) { formObj.setTextData(atmp.getPm25ValDesc(unitGap, isUnit)); fontGradeColorCd = atmp.getPm25Color(); } else if (formObj.getObjectType() == 404) { formObj.setTextData(atmp.getPm10GradDesc()); fontGradeColorCd = atmp.getPm10Color(); } else if (formObj.getObjectType() == 405) { formObj.setTextData(atmp.getPm25GradDesc()); fontGradeColorCd = atmp.getPm25Color(); } else if (formObj.getObjectType() == 409) { formObj.setTextData(atmp.getAtmpGradDesc()); fontGradeColorCd = atmp.getAtmpColor(); } else if (formObj.getObjectType() == 410) { formObj.setTextData(atmp.getAtmpValDesc()); fontGradeColorCd = atmp.getAtmpColor(); } else if (formObj.getObjectType() == 411) { formObj.setTextData(atmp.getO3ValDesc(unitGap, isUnit)); fontGradeColorCd = atmp.getO3Color(); } else if (formObj.getObjectType() == 412) { formObj.setTextData(atmp.getO3GradDesc()); fontGradeColorCd = atmp.getO3Color(); } if (isSetFontColor && formObj.getFontColor() != 10) { // 엘이디 고장난게 있어서 흰색으로 표출해야 해서 폰트색상이 흰색인 경우 그냥 흰색으로 표출하는 것으로..... formObj.setFontColor(fontGradeColorCd); } } if ("".equals(formObj.getTextData())) { formObj.setTextData(" "); } formObj.changeTextPosition(this.config.getFontSizeRatio()); break; case 101: // @주차장명 case 102: // @주차면수 case 103: // @주차가능면수 case 104: // @주차혼잡도 TbVmsParkDto park = this.parkService.find(obj.getVmsIfscId()); if (park == null) { formObj.setTextData("-"); formObj.setFontColor(eVmsColor.color_red.getValue()); log.error("VmsManageService.makeVmsProvideForm: VMS({}), FormId({}), Not Found Parking {}.", ctlrNmbr, schedule.getVmsFormId(), obj.getVmsIfscId()); } else { String textFmt = obj.getVmsDsplTxt().replaceAll("@", ""); switch(formObj.getObjectType()) { case 101:// || //@주차장명 formObj.setTextData(park.getParkName()); break; case 102:// || //@주차면수 formObj.setTextData(park.getTotalCo(textFmt)); break; case 103:// || //@주차가능면수 formObj.setTextData(park.getRemainCo(textFmt)); formObj.setFontColor(park.getGradeColorCd()); break; case 104:// //@주차혼잡도 formObj.setTextData(park.getParkingCngstSttsDesc()); formObj.setFontColor(park.getGradeColorCd()); break; } } if ("".equals(formObj.getTextData())) { formObj.setTextData(" "); } formObj.changeTextPosition(this.config.getFontSizeRatio()); break; default: //객체가 가변(소통정보 표출) 인 경우 가변문자를 설정하자.... Long vmsIfscId = 0L; switch(formObj.getObjectType()) { case 11: case 12: case 13: case 14: case 15: case 16: case 18: case 19: vmsIfscId = schedule.getFrstVmsIfscId(); if (form.getVmsFormTypeCd() == eVmsFormType.eFormTp_figure.getValue() || form.getVmsFormTypeCd() == eVmsFormType.eFormTp_congest.getValue()) { vmsIfscId = schedule.getVmsIfscId(); } break; case 161: case 162: case 163: case 164: case 165: case 166: case 168: case 21: case 22: case 23: case 24: case 25: case 26: case 28: vmsIfscId = schedule.getSecdVmsIfscId(); break; case 31: case 32: case 33: case 34: case 35: case 36: case 38: vmsIfscId = schedule.getThirVmsIfscId(); break; case 41: case 42: case 43: case 44: case 45: case 46: case 48: vmsIfscId = schedule.getFourVmsIfscId(); break; case 91: case 92: //@축통행시간(고정), @축소통상황(고정) case 93: case 94: case 95: case 96: // @축시점명(순환), @축종점명(순환), @축소통상황(순환), @축통행시간(순환) vmsIfscId = schedule.getVmsIfscId(); break; default: continue; } formObj.setTextData(""); ifscTraf = this.ifscService.find(vmsIfscId); if (ifscTraf == null) { log.error("VmsManageService.makeVmsProvideForm: VMS({}), FormId({}), Traffic IFSC Not Found {}.", ctlrNmbr, schedule.getVmsFormId(), vmsIfscId); continue; } switch(formObj.getObjectType()) { case 11: case 21: case 31: case 41: case 161: //구간명 formObj.setTextData(ifscTraf.getRoadNm()); break; case 12: case 22: case 32: case 42: case 93: case 162: //시점명 formObj.setTextData(ifscTraf.getDsplStrtNodeNm()); break; case 13: case 23: case 33: case 43: case 94: case 163: //종점명 formObj.setTextData(ifscTraf.getDsplEndNodeNm()); break; case 14: case 24: case 34: case 44: case 92: case 95: case 164: //소통상황 formObj.setTextData(trafGradeDesc(form.getVmsFormTypeCd(), ifscTraf.getCmtrGradCd())); // 도형식 하단쪽에 엘이디 고장난게 있어서 흰색으로 표출해야 해서 // 폰트색상이 흰색인 경우 그냥 흰색으로 표출하는 것으로..... if (formObj.getFontColor() != 10) { formObj.setFontColor(gradeToColorCode(ifscTraf.getCmtrGradCd())); } break; case 19: //소통상황(가변) String gradText = trafGradeDesc(form.getVmsFormTypeCd(), ifscTraf.getCmtrGradCd()); if (ifscTraf.getCmtrGradCd() == eTrafficGrade.grade_smoothness.getValue()) { gradText = String.format("소통원활 약 %d 분", ifscTraf.getTrvlHh()); } formObj.setTextData(gradText); formObj.setFontColor(gradeToColorCode(ifscTraf.getCmtrGradCd())); break; case 15: case 25: case 35: case 45: case 91: case 96: case 165: //통행시간 if (ifscTraf.getTrvlHh() > 0) { String textFmt = obj.getVmsDsplTxt().replace("@", ""); if (textFmt.contains("0")) { textFmt = textFmt.replace("0000", "%4d"); textFmt = textFmt.replace("000", "%3d"); textFmt = textFmt.replace("00", "%2d"); textFmt = textFmt.replace("0", "%d"); String textData = String.format(textFmt, ifscTraf.getTrvlHh()); formObj.setTextData(textData); } else { formObj.setTextData(String.valueOf(ifscTraf.getTrvlHh())); } formObj.setFontColor(gradeToColorCode(ifscTraf.getCmtrGradCd())); } else { formObj.setTextData(" "); formObj.setFontColor(eVmsColor.color_black.getValue()); } break; case 16: case 26: case 36: case 46: case 166: //통행속도 formObj.setTextData(String.valueOf(ifscTraf.getSped())); formObj.setFontColor(gradeToColorCode(ifscTraf.getCmtrGradCd())); break; case 17: case 27: case 37: case 47: //방향이미지...??? break; case 18: case 28: case 38: case 48: case 168: //지점명 formObj.setTextData(ifscTraf.getSpotNm()); break; default: break; } formObj.changeTextPosition(this.config.getFontSizeRatio()); break; } } // (ii = 0; ii < vmsForm.getObjects().size() } // (int ii = 0; ii < scheObj.size(); ii++) }); log.info("VmsManageService.makeVmsProvideForm: {} ms.", elapsed.milliSeconds()); } /** * 데이터베이스에 저장할 폼 이미지를 생성한다. */ public void makeVmsDatabaseForm() { log.info("VmsManageService.makeVmsDatabaseForm: START."); Elapsed elapsed = new Elapsed(); this.repoService.getCtlrMap().forEach((ctlrNmbr, vmsObj) -> { if ("Y".equals(vmsObj.getDelYn())) { return; } if (this.config.isFigureTrafficCenter()) { //도형식폼의 하단소통정보위치를 가운데로 정렬하는 경우 makeVmsFigureFormPos(vmsObj); } if (this.config.isTextTrafficCenter() && "VMP2".equals(vmsObj.getTypeCd())) //2단 12열 일 경우 정렬 { //1단교통정보의 이정을 가운데로 정렬하는 경우 makeVmsTextFormPos(vmsObj); } makeVmsDatabaseFormImage(vmsObj); }); this.toggleFormSeq++; if (this.toggleFormSeq >= 6) { this.toggleFormSeq = 1; } log.info("VmsManageService.makeVmsDatabaseForm: {} ms.", elapsed.milliSeconds()); } /** * 데이터베이스에 저장할 폼 이미지를 생성한다. * @param vmsObj */ public void makeVmsDatabaseFormImage(TbVmsCtlrDto vmsObj) { if (vmsObj == null) { log.error("VmsManagerService.makeVmsDatabaseFormData: VMS Controller null data."); return; } int formCnt = vmsObj.getFormManager().count(); if (formCnt == 0) { log.error("VmsManagerService.makeVmsDatabaseFormData: VMS {}, Form Data Not Found.", vmsObj.getVmsCtlrNmbr()); return; } if (formCnt > vmsObj.getMaxPhaseNum()) { log.error("VmsManagerService.makeVmsDatabaseFormData: VMS {}, Form Count Over: {}/{} EA.", vmsObj.getVmsCtlrNmbr(), formCnt, vmsObj.getMaxPhaseNum()); formCnt = vmsObj.getMaxPhaseNum(); } for (int ii = 0; ii < formCnt; ii++) { VmsForm pForm = vmsObj.getFormManager().getItem(ii); pForm.drawForm(this.formService, this.fontService, this.config); pForm.calVmsSchFormType(); pForm.makeVmsDsplMsgData(this.formService, this.symbService, this.ifscService); // FTP 다운로드 하는 경우 폼을 FTP 디렉토리에 저장해야함 //if (pForm.getFileType() != VmsProtocolConst.P_FILE_TYPE_VIDEO && // 비디오 // pForm.getFileType() != VmsProtocolConst.P_FILE_TYPE_STREAM // 스트리밍영상 등은 로컬파일로 저장할 필요가 없음 //) { // 파일이름을 여기서 변경하면 ftp 파일명이 변경된다. if (vmsObj.isFtpDownload()) { String formFileName; if (this.config.isImageSeqSave()) { //시퀀스_운영모드-순서_폼유형-폼번호.bmp formFileName = String.format("%d_%s%02d_%X%s.bmp", this.toggleFormSeq, vmsObj.getOperMode(), ii+1, pForm.getVmsSchFormType(), pForm.getVmsFormId()); } else { //운영모드-순서_폼유형-폼번호.bmp formFileName = String.format("%s%02d_%X%s.bmp", vmsObj.getOperMode(), ii+1, pForm.getVmsSchFormType(), pForm.getVmsFormId()); } pForm.setLocalFileName(vmsObj.getLocalFormDir() + formFileName); pForm.setFtpFileName(vmsObj.getFtpFormDir() + formFileName); pForm.saveToFile(); } } pForm.setSuccess(true); if (this.debug.isDebug()) { log.info("VmsManagerService.makeVmsDatabaseFormData: VMS {}, FORM {}, DnldFormNo {}, Objects {}. ScheduleType {}, FileType {}, File/FtpName {}/{}.", vmsObj.getVmsCtlrNmbr(), pForm.getVmsFormId(), pForm.getDnldFormNo(), pForm.count(), eVmsScheduleType.getValue(pForm.getVmsSchFormType()), pForm.getFileType(), pForm.getLocalFileName(), pForm.getFtpFileName()); } } } /** * 도형식 VMS 하단 소통정보 좌표 위치 조정 * @param vmsObj */ public void makeVmsFigureFormPos(TbVmsCtlrDto vmsObj) { if (vmsObj == null) { log.error("VmsManagerService.makeVmsFigureFormPos: VMS Controller null data."); return; } int formCnt = vmsObj.getFormManager().count(); if (formCnt == 0) { log.error("VmsManagerService.makeVmsFigureFormPos: VMS {}, Form Data Not Found.", vmsObj.getVmsCtlrNmbr()); return; } if (formCnt > vmsObj.getMaxPhaseNum()) { log.error("VmsManagerService.makeVmsFigureFormPos: VMS {}, Form Count Over: {}/{} EA.", vmsObj.getVmsCtlrNmbr(), formCnt, vmsObj.getMaxPhaseNum()); formCnt = vmsObj.getMaxPhaseNum(); } int arrowGap = 7; int trafGap = 17; int objCnt; int formT; VmsFormObject pArw; VmsFormObject pStr; VmsFormObject pEnd; VmsFormObject pTrf; int totW; int left; for (int ii = 0; ii < formCnt; ii++) { VmsForm pForm = vmsObj.getFormManager().getItem(ii); if (pForm.getVmsFormTypeCd() != eVmsFormType.eFormTp_figure.getValue()) { //도형식배경소통정보 폼이 아닌경우 계산하지 않음 continue; } formT = pForm.getHeight() - 40; //하단소통정보 객체의 최대높이를 설정, 이것보다 작으면 위치조정 하지 않음 pArw = null; pStr = null; pEnd = null; pTrf = null; //소통상황 시점 -> 종점 //시점 -> 종점 소통상황 //위의 2가지 유형에 대하여 가운데 정렬 objCnt = pForm.count(); for (int jj = 0; jj < objCnt; jj++) { VmsFormObject pFormObj = pForm.getItem(jj); if (pFormObj.getPosY() < formT) continue; switch(pFormObj.getObjectType()) { case 1: // 심볼 Y case 2: // 이미지 Y if ("T".equals(pFormObj.getTrfcFillCd())) pArw = pFormObj; break; case 17: // @소통정보이미지 N pArw = pFormObj; break; case 12: // @시점명 Y case 93: // @축시점명(순환) Y case 13: // @종점명 Y case 94: // @축종점명(순환) Y if (pFormObj.getObjectType() == 12 || pFormObj.getObjectType() == 93) pStr = pFormObj; else pEnd = pFormObj; break; case 14: // @소통상황 Y case 15: // @통행시간 Y case 16: // @통행속도 N case 95: // @축소통상황(순환) Y case 96: // @축통행시간(순환) Y pTrf = pFormObj; break; default: break; } } if (pArw == null || pStr == null || pEnd == null || pTrf == null) { continue; } int totalWidth = pStr.getTextWidth() + pArw.getTextWidth() + pEnd.getTextWidth() + pTrf.getTextWidth(); if (totalWidth > (pForm.getWidth() - arrowGap - arrowGap - trafGap - 10) ) { arrowGap = 3; trafGap = 10; } totW = pStr.getTextWidth() + arrowGap + pArw.getTextWidth() + arrowGap + pEnd.getTextWidth() + trafGap + pTrf.getTextWidth(); left = (pForm.getWidth() - totW) / 2; if (pStr.getPosX() < pTrf.getPosX()) { //시점 -> 종점 소통상황 pStr.setPosX(left); pArw.setPosX(pStr.getPosX() + pStr.getTextWidth() + arrowGap); pEnd.setPosX(pArw.getPosX() + pArw.getTextWidth() + arrowGap); pTrf.setPosX(pEnd.getPosX() + pEnd.getTextWidth() + trafGap); } else { //소통상황 시점 -> 종점 pTrf.setPosX(left); pStr.setPosX(pTrf.getPosX() + pTrf.getTextWidth() + trafGap); pArw.setPosX(pStr.getPosX() + pStr.getTextWidth() + arrowGap); pEnd.setPosX(pArw.getPosX() + pArw.getTextWidth() + arrowGap); } } } /** * 1단 텍스트 소통정보 좌표 위치 조정 * @param vmsObj */ public void makeVmsTextFormPos(TbVmsCtlrDto vmsObj) { // 시점 화살표 종점 의 좌표는 폼생성할때 정의된데로 하고 // 시점 화살표 종점의 전체 길이를 폼의 넓이로 환산하여 가운데 정렬 // 시점(오른쪽정렬) 화살표(의미없고) 종점(왼쪽정렬) 로 폼설정에서 설정하도록 한다. // 시점/화살표/종점의 Y축 좌표도 설정한 데로 표출한다. // 시점/화살표/종점을 폼의 가운데에 정렬하는 것이다. if (vmsObj == null) { log.error("VmsManagerService.makeVmsTextFormPos: VMS Controller null data."); return; } int formCnt = vmsObj.getFormManager().count(); if (formCnt == 0) { log.error("VmsManagerService.makeVmsTextFormPos: VMS {}, Form Data Not Found.", vmsObj.getVmsCtlrNmbr()); return; } if (formCnt > vmsObj.getMaxPhaseNum()) { log.error("VmsManagerService.makeVmsTextFormPos: VMS {}, Form Count Over: {}/{} EA.", vmsObj.getVmsCtlrNmbr(), formCnt, vmsObj.getMaxPhaseNum()); formCnt = vmsObj.getMaxPhaseNum(); } int objCnt; int gapL; VmsFormObject pArw; VmsFormObject pStr; VmsFormObject pEnd; int totW; int left; for (int ii = 0; ii < formCnt; ii++) { VmsForm pForm = vmsObj.getFormManager().getItem(ii); if (pForm.getVmsFormTypeCd() != eVmsFormType.eFormTp_traf_1.getValue()) { //소통상황(1단) 폼이 아닌경우 계산하지 않음 continue; } pArw = null; pStr = null; pEnd = null; // 시점(12) -> 종점(13) objCnt = pForm.count(); for (int jj = 0; jj < objCnt; jj++) { VmsFormObject pFormObj = pForm.getItem(jj); switch(pFormObj.getObjectType()) { case 12: // @시점명 Y pStr = pFormObj; break; case 13: // @종점명 Y pEnd = pFormObj; break; default: break; } } if (pStr == null || pEnd == null) { continue; } for (int jj = 0; jj < objCnt; jj++) { VmsFormObject pFormObj = pForm.getItem(jj); switch(pFormObj.getObjectType()) { case 1: // @심볼 Y case 2: // @이미지 Y case 17: // @소통정보이미지 Y // if (pFormObj->TRFC_FILL_CD == "T") if (pFormObj.getPosY() <= (pStr.getPosY()+pStr.getDsplHeight())) { pArw = pFormObj; } break; default: break; } } if (pArw != null && pStr != null && pEnd!= null ) { //시점 화살표 종점 순으로 되어 있어야 한다. int nRange = pStr.getPosY() + pStr.getDsplHeight(); if (pArw.getPosY() <= nRange && pEnd.getPosY() <= nRange) { gapL = pArw.getPosX()- (pStr.getPosX()+ pStr.getTextWidth()); // 시점 화살표 사이의 간격 totW = (pEnd.getPosX()+ pEnd.getTextWidth()) - pStr.getPosX(); // 전체길이 left = (pForm.getWidth() - totW) / 2; pStr.setPosX(left); pArw.setPosX(pStr.getPosX()+ pStr.getTextWidth() + gapL); pEnd.setPosX((left + totW) - pEnd.getTextWidth()); } } } } /** * 폼유형에 따라 소통정보 등급에 해당하는 문자열 리턴 * @param formType * @param cmtrGradCd * @return */ public String trafGradeDesc(int formType, int cmtrGradCd) { if (formType == eVmsFormType.eFormTp_figure.getValue()) { switch(cmtrGradCd) { case 1: return this.config.getFigureTrafGrad1(); case 2: return this.config.getFigureTrafGrad2(); case 3: return this.config.getFigureTrafGrad3(); default: break; } } else { switch(cmtrGradCd) { case 1: return this.config.getTextTrafGrad1(); case 2: return this.config.getTextTrafGrad2(); case 3: return this.config.getTextTrafGrad3(); default: break; } } return " "; } /** * 소통정보 등급에 따른 표출 색상코드를 리턴 * @param cmtrGradCd * @return */ public int gradeToColorCode(int cmtrGradCd) { switch(cmtrGradCd) { case 1: return eVmsColor.color_green.getValue(); case 2: return eVmsColor.color_amber.getValue(); case 3: return eVmsColor.color_red.getValue(); default: break; } return eVmsColor.color_green.getValue(); } /** * 제어기 상태정보 요청 */ public void requestStatus() { this.repoService.getCtlrMap().forEach((ctlrNmbr, vmsObj) -> { if ("Y".equals(vmsObj.getDelYn())) { return; } vmsObj.addRequestData(new TcpServerSendData(eVmsOpCode.OP_VMS_STATUS_REQ, null)); }); } }