main-func.js 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257
  1. import { currDt } from "/js/utils/common.js";
  2. import { requestGet, apiGet } from "/js/utils/restApi.js";
  3. import { TMapMngr } from "/js/vworld/map-mngr.js";
  4. import { LayerType, LayerIndex } from "/js/vworld/map-const.js";
  5. import { TWebSocket } from "/js/websocket/websocket.js";
  6. import * as MAIN from "./main.js";
  7. export let _mapManager = null;
  8. let _webSocket = null;
  9. export let _cctvMap = new Map();
  10. export let _vmsMap = new Map();
  11. let _trafficMap = new Map();
  12. const _crdnMap = new Map();
  13. window.$trafficMap = _trafficMap;
  14. let _timerFetchFcltStts = null; // 시설물 상태정보 요청 타이머
  15. let _timerFetchTraffic = null; // 교통정보 요청 타이머
  16. let _timerFetchIncdData = null; // 돌발정보 요청 타이머
  17. let _timerWebsocket = null;
  18. export let _iceServerMap = new Map();
  19. export const drctMap = new Map();
  20. drctMap.set(1, 0);
  21. drctMap.set(2, 90);
  22. drctMap.set(3, 180);
  23. drctMap.set(4, 270);
  24. drctMap.set(5, 45);
  25. drctMap.set(6, 135);
  26. drctMap.set(7, 225);
  27. drctMap.set(8, 315);
  28. const requestFetchFcltStts = () => {
  29. //console.log(`${nowTime()} requestFetchFcltStts`);
  30. if (_timerFetchFcltStts) window.clearTimeout(_timerFetchFcltStts);
  31. _timerFetchFcltStts = window.setTimeout(() => fetchFcltStts(), 2 * 60 * 1000);
  32. };
  33. const requestFetchTraffic = () => {
  34. //console.log(`${nowTime()} requestFetchTraffic`);
  35. if (_timerFetchTraffic) window.clearTimeout(_timerFetchTraffic);
  36. _timerFetchTraffic = window.setTimeout(() => fetchTraffic(), 5 * 60 * 1000);
  37. };
  38. const requestFetchIncdData = () => {
  39. //console.log(`${nowTime()} requestFetchIncdData`);
  40. if (_timerFetchIncdData) window.clearTimeout(_timerFetchIncdData);
  41. _timerFetchIncdData = window.setTimeout(() => fetchIncdData(), 2 * 60 * 1000);
  42. };
  43. let _timerFetchUnitStts = null; // 프로세스 상태정보 요청 타이머
  44. const requestFetchUnitStts = () => {
  45. //console.log(`${nowTime()} requestFetchUnitStts`);
  46. if (_timerFetchUnitStts) window.clearTimeout(_timerFetchUnitStts);
  47. _timerFetchUnitStts = window.setTimeout(() => fetchUnitStts(), 2 * 60 * 1000);
  48. };
  49. // 웹소켓 초기화
  50. function websocketConnect(clientType) {
  51. _webSocket = new TWebSocket(clientType, onSocketReceived, onSocketDisconnected, onSocketError, onSocketConnected);
  52. _webSocket.connect();
  53. }
  54. function onSocketConnected(AClientType, AMessage) {
  55. if (_timerWebsocket != null) {
  56. clearTimeout(_timerWebsocket);
  57. _timerWebsocket = null;
  58. }
  59. console.log(`${nowTime()} onSocketConnected, ${AClientType}, `, AMessage);
  60. }
  61. function onSocketReceived(AClientType, AMessage) {
  62. // console.log(`${nowTime()} onSocketReceived, ${AClientType}, `, AMessage);
  63. const command = AMessage.command;
  64. const jsonData = AMessage.data;
  65. if (command === "itsFcltStts" || command === "bisFcltStts") {
  66. updateFcltStts(jsonData);
  67. //if (command === "bisFcltStts") {
  68. //const sttsArray = Array.from( _sttsMap.values() );
  69. MAIN.updateFcltStts(_sttsMap);
  70. //}
  71. requestFetchFcltStts();
  72. } else if (command === "itsUnitStts" || command === "bisUnitStts") {
  73. if (command === "itsUnitStts") {
  74. MAIN.updateUnitStts(jsonData); //ITS 프로세스
  75. }
  76. //if (command === "bisUnitStts") {
  77. requestFetchUnitStts();
  78. //}
  79. } else if (command === "traffic") {
  80. // 소통정보 가공완료
  81. fetchTraffic();
  82. } else if (command === "form-save") {
  83. // VMS 메시지 생성 저장
  84. } else if ( command === "fcltUserMsg" ) {
  85. getDataAsync('/api/facility/tb_user_msg/list/notify/' + encodeURIComponent(window.$userId), (jsonData)=>{
  86. if (jsonData && jsonData.length > 0){
  87. MAIN.drawMsgView(jsonData);
  88. }
  89. }, null, null, true);
  90. }
  91. }
  92. function connectToWebSocket() {
  93. if (_timerWebsocket != null) {
  94. clearTimeout(_timerWebsocket);
  95. _timerWebsocket = null;
  96. }
  97. websocketConnect('op')
  98. }
  99. //소켓이 끊어 졌을때 다시 실행
  100. function onSocketDisconnected(AClientType, AMessage) {
  101. console.log(`${nowTime()} onSocketDisconnected, ${AClientType}, `, AMessage);
  102. if (_timerWebsocket != null) {
  103. clearTimeout(_timerWebsocket);
  104. _timerWebsocket = null;
  105. }
  106. _timerWebsocket = setTimeout(connectToWebSocket, 5000);
  107. }
  108. function onSocketError(AClientType, AMessage) {
  109. console.log(`${nowTime()} onSocketError, ${AClientType}, `, AMessage);
  110. }
  111. function FcltStts(type) {
  112. this.type = type;
  113. this.total = 0;
  114. this.normal = 0;
  115. this.error = 0;
  116. this.collect = 0;
  117. this.objLists = new Array();
  118. }
  119. export const _sttsMap = new Map();
  120. _sttsMap.set("CCTV", new FcltStts("CCTV"));
  121. _sttsMap.set("VMS", new FcltStts("VMS"));
  122. _sttsMap.set("VDS", new FcltStts("VDS"));
  123. _sttsMap.set("DSRC", new FcltStts("DSRC"));
  124. _sttsMap.set("SIG", new FcltStts("신호제어기"));
  125. _sttsMap.set("CCAM", new FcltStts("교차로카메라"));
  126. _sttsMap.set("WCAM", new FcltStts("웹카메라"));
  127. //_sttsMap.set("BIT", new FcltStts("BIT"));
  128. export function doMap() {
  129. // 지도객체 먼저 생성 하여야 함
  130. _mapManager = new TMapMngr("map", "tooltip");
  131. connectToWebSocket();
  132. _mapManager.onMapMoveEndFunc = onMapMoveEndFunc; // 지도 이동/줌 변경 이벤트 반환
  133. _mapManager.onMouseClickFunc = onMouseClickFunc; // 객체 마우스 클릭 이벤트 반환
  134. _mapManager.onContextMenuFunc = onContextMenuFunc; // 객체 컨텍스트 이벤트 반환
  135. //_mapManager.onSelectObjFunc = onSelectObjFunc; // 객체 선택 이벤트 반환
  136. //_mapManager.onFcltDragEndFunc = onFcltDragEndFunc; // 객체(시설물) 편집시 객체 이동후 좌표 반환
  137. // 지도 초기화설정
  138. _mapManager.showTrafficTooltip(false);
  139. _mapManager.setSelectMode(true);
  140. _mapManager.toggleBaseMap(true);
  141. requestGet('/api/database/code/cmmn-cd/LTC', (jsonData) => {_mapManager.setTrafficGradDesc(jsonData);});
  142. }
  143. function onMapMoveEndFunc(AZoom, ACenterX, ACenterY, ALeft, ABottom, ARight, ATop) {
  144. //console.log(`${nowTime()} onMapMoveEndFunc, ${AZoom}, ${ACenterX}, ${ACenterY}, ${ALeft}, ${ABottom}, ${ARight}, ${ATop}`);
  145. $('.cctv-right-btn-click').remove();
  146. $('.vms-right-btn-click').remove();
  147. }
  148. function onMouseClickFunc(ALyrIdx, ALyrName, ANmbr, ACoordX, ACoordY, X, Y) {
  149. //console.log(`${nowTime()} onMouseClickFunc, ${ALyrIdx}, ${ALyrName}, ${ANmbr}, ${ACoordX}, ${ACoordY}, ${X}, ${Y}`);
  150. if (ALyrIdx === -1) {
  151. $('.cctv-right-btn-click').remove();
  152. $('.vms-right-btn-click').remove();
  153. }
  154. // const obj = _mapManager.findLayerObject(ALyrIdx, ANmbr);
  155. // if (!obj) {
  156. // return;
  157. // }
  158. if (ALyrName === "VMS") {
  159. } else if (ALyrName === "CCTV") {
  160. }
  161. // else if (ALyrName === "BIT") {
  162. // }
  163. let option = 'width = 580, height = 550, top = 200, left = 674, resizable=no, scrollbars=no';
  164. if (ALyrIdx >= LayerIndex.Link1 && ALyrIdx <= LayerIndex.Link5) {
  165. window.open('./detail-traffic-pop-up.html?id=' + encodeURIComponent(ANmbr) + '&type=link', '구간선택', option);
  166. }
  167. else if (ALyrIdx >= LayerIndex.Ifsc1 && ALyrIdx <= LayerIndex.Ifsc5) {
  168. window.open('./detail-traffic-pop-up.html?id=' + encodeURIComponent(ANmbr) + '&type=ifsc', '구간선택', option);
  169. }
  170. else if (ALyrIdx >= LayerIndex.Road1 && ALyrIdx <= LayerIndex.Road5) {
  171. window.open('./detail-traffic-pop-up.html?id=' + encodeURIComponent(ANmbr) + '&type=road', '구간선택', option);
  172. }
  173. }
  174. function onContextMenuFunc(ALyrIdx, ALyrName, ANmbr, ACoordX, ACoordY, X, Y) {
  175. //console.log(`${nowTime()} onContextMenuFunc, ${ALyrIdx}, ${ALyrName}, ${ANmbr}, ${ACoordX}, ${ACoordY}, ${X}, ${Y}`);
  176. $('.cctv-right-btn-click').remove();
  177. $('.vms-right-btn-click').remove();
  178. //cctv 우클릭 이벤트
  179. if (ALyrIdx === LayerIndex.Cctv || ALyrIdx === LayerIndex.WCam || ALyrIdx === LayerIndex.CCam) {
  180. const cctvObj = _mapManager.findLayerObject(ALyrIdx, ANmbr);
  181. let type;
  182. switch (ALyrIdx) {
  183. case LayerIndex.Cctv:
  184. type = 'CCTV';
  185. break;
  186. case LayerIndex.WCam:
  187. type = '웹카메라';
  188. break;
  189. case LayerIndex.CCam:
  190. type = '교차로카메라';
  191. break;
  192. }
  193. if (cctvObj) {
  194. let div = $(`<div class='cctv-right-btn-click'>
  195. <div>
  196. <div>[${type}] ${cctvObj.ID} - ${cctvObj.NAME}</div>
  197. <div>카메라 영상</div>
  198. </div>
  199. </div>`);
  200. $('body').append(div);
  201. if ($('#drawer')[0].offsetWidth - X < div[0].offsetWidth){
  202. div.css('left', $('#drawer')[0].offsetWidth - div[0].offsetWidth + 12);
  203. }
  204. else {
  205. div.css('left', X);
  206. }
  207. if ($('#drawer')[0].offsetHeight - Y < div[0].offsetHeight){
  208. div.css('top', $('#drawer')[0].offsetHeight - div[0].offsetHeight + 59);
  209. }
  210. else {
  211. div.css('top', Y);
  212. }
  213. $(div).children().eq(0).children().eq(1).on('click',function(e){
  214. $('.cctv-right-btn-click').remove();
  215. const cctvBox = $('#' + cctvObj.ID);
  216. if (cctvBox.length > 0) {
  217. return cctvBox.mousedown();
  218. }
  219. newCamCtrl(createVideoIframe, cctvObj, X, Y);
  220. })
  221. }
  222. }
  223. //vms 우클릭 이벤트
  224. else if (ALyrIdx === LayerIndex.Vms) {
  225. const vmsObj = _mapManager.findLayerObject(ALyrIdx, ANmbr);
  226. if (vmsObj) {
  227. let div = $(`<div class='vms-right-btn-click'>
  228. <div>
  229. <div>[VMS] ${vmsObj.ID} - ${vmsObj.NAME}</div>
  230. <div>카메라 영상</div>
  231. <div>표출메시지</div>
  232. </div>
  233. </div>`);
  234. $('body').append(div);
  235. if ($('#drawer')[0].offsetWidth - X < div[0].offsetWidth){
  236. div.css('left', $('#drawer')[0].offsetWidth - div[0].offsetWidth + 12);
  237. }
  238. else {
  239. div.css('left', X);
  240. }
  241. if ($('#drawer')[0].offsetHeight - Y < div[0].offsetHeight){
  242. div.css('top', $('#drawer')[0].offsetHeight - div[0].offsetHeight + 59);
  243. }
  244. else {
  245. div.css('top', Y);
  246. }
  247. if (!_cctvMap.get(vmsObj.ID)){
  248. _cctvMap.set(vmsObj.ID, new Map());
  249. }
  250. if (!_vmsMap.get(vmsObj.ID)){
  251. _vmsMap.set(vmsObj.ID, new Map());
  252. }
  253. // 카메라 영상 클릭 이벤트
  254. $(div).children().eq(0).children().eq(1).on('click',function(){
  255. $('.vms-right-btn-click').remove();
  256. let src = vmsObj.strmHttpAddr;
  257. camCtrl(_cctvMap, createVideoDiv, vmsObj, src, X, Y, true);
  258. });
  259. //표출메시지 클릭 이벤트
  260. $(div).children().eq(0).children().eq(2).on('click',function(){
  261. $('.vms-right-btn-click').remove();
  262. if(!_vmsMap.get(vmsObj.ID).get('div')){
  263. vmsMessageCtrl(vmsObj,X, Y);
  264. }
  265. })
  266. }
  267. }
  268. }
  269. /**
  270. * 표출메시지 이벤트
  271. * @param {*} obj vms 객체
  272. * @param {*} X 마우스 X 좌표
  273. * @param {*} Y 마우스 Y 좌표
  274. */
  275. export function vmsMessageCtrl(obj, X, Y){
  276. let vmsData = [];
  277. //vms 데이터 수신
  278. getData('/api/vms/common/vms-form/dspl-prst', vmsData, {id:obj.NMBR});
  279. if (vmsData[0] && vmsData[0].length > 0) {
  280. vmsData = vmsData[0];
  281. //vms 이미지 데이터
  282. let msgs = vmsData[0].msgs;
  283. //현재 시각
  284. let now = "제공시각 - " + nowTime();
  285. //이미지 높이에 따른 박스 높이
  286. let height = vmsData[0].vms_hght + 80;
  287. //이미지 높이
  288. let imgBoxHeight = vmsData[0].vms_hght;
  289. //이미지 넓이에 따른 박스 넓이
  290. let width = vmsData[0].vms_wdth + 20;
  291. //vms div 생성
  292. let vmsDiv = createMessageDiv(obj, now, vmsData[0].cmnc_stts_desc);
  293. let vmsLeft = X;
  294. let vmsTop = Y;
  295. $('body').append(vmsDiv);
  296. vmsDiv.children().eq(1).css('height', imgBoxHeight);
  297. vmsDiv.children().eq(1).children().eq(0).css({height: imgBoxHeight, width: width - 20});
  298. if ($('#drawer')[0].offsetWidth - X < width){
  299. vmsLeft = $('#drawer')[0].offsetWidth - width + 12;
  300. }
  301. if ($('#drawer')[0].offsetHeight - Y < height){
  302. vmsTop = $('#drawer')[0].offsetHeight - height + 59;
  303. }
  304. vmsDiv.css({left:vmsLeft, top:vmsTop, height: height});
  305. let imgPosition = vmsDiv.children().eq(1).children().eq(0);
  306. let phaseNumPosition = vmsDiv.children().eq(2).children().eq(0);
  307. let intervalNumPosition = vmsDiv.children().eq(2).children().eq(1);
  308. let closePosition = vmsDiv.children().eq(0).children().eq(0);
  309. let vmsInfo = _vmsMap.get(obj.ID);
  310. vmsInfo.set('div', vmsDiv);
  311. setVmsInterval(msgs, imgPosition, phaseNumPosition, intervalNumPosition, 0, obj.ID);
  312. //vmsInfo.set('intervalArr', intervalArr);
  313. $('.vms-box').draggable({ containment: "body" });
  314. //dragEvent(vmsDiv, 'vms-box');
  315. closePosition.on('click', function(){
  316. clearTimeout(vmsInfo.get('interval'));
  317. vmsInfo.get('div').remove();
  318. vmsInfo.delete('div');
  319. });
  320. }
  321. else {
  322. //현재 시각
  323. let now = '표출메시지가 없습니다.';
  324. //이미지 높이에 따른 박스 높이
  325. let height = 144;
  326. //이미지 높이
  327. let imgBoxHeight = 64;
  328. //이미지 넓이에 따른 박스 넓이
  329. let width = 404;
  330. //vms div 생성
  331. let vmsDiv = createMessageDiv(obj, now);
  332. let vmsLeft = X;
  333. let vmsTop = Y;
  334. $('body').append(vmsDiv);
  335. vmsDiv.children().eq(1).css('height', imgBoxHeight);
  336. vmsDiv.children().eq(1).children().eq(0).css({height: imgBoxHeight, width: width - 20});
  337. if ($('#drawer')[0].offsetWidth - X < width){
  338. vmsLeft = $('#drawer')[0].offsetWidth - width + 12;
  339. }
  340. if ($('#drawer')[0].offsetHeight - Y < height){
  341. vmsTop = $('#drawer')[0].offsetHeight - height + 59;
  342. }
  343. vmsDiv.css({left:vmsLeft, top:vmsTop, width:width, height: height});
  344. let imgPosition = vmsDiv.children().eq(1).children().eq(0);
  345. let closePosition = vmsDiv.children().eq(0).children().eq(0);
  346. imgPosition.css('background-color', 'black');
  347. let vmsInfo = _vmsMap.get(obj.ID);
  348. vmsInfo.set('div', vmsDiv);
  349. //dragEvent(vmsDiv, 'vms-box');
  350. $('.vms-box').draggable({ containment: "body" });
  351. closePosition.on('click', function(){
  352. vmsInfo.get('div').remove();
  353. vmsInfo.delete('div');
  354. });
  355. }
  356. }
  357. /**
  358. * vms 이미지 인터벌
  359. * @param {*} value vms 데이터
  360. * @param {*} position vms 이미지 위치
  361. * @param {*} phase phase 번호 텍스트 위치
  362. * @param {*} num 카운트 텍스트 위치
  363. */
  364. export function setVmsInterval(data, position, phase, num, idx, id){
  365. if (data[idx]) {
  366. $(position).prop('src', 'data:image/png;base64,'+ data[idx].vms_dspl_msg_imag);
  367. let time = data[idx].dspl_hh;
  368. let intervalNum = data[idx].dspl_hh;
  369. idx++;
  370. $(num).text(intervalNum--);
  371. $(phase).text(idx + '/' + data.length);
  372. let timeInterval = setInterval(()=>{
  373. $(num).text(intervalNum--);
  374. if(intervalNum === 0){
  375. clearInterval(timeInterval);
  376. }
  377. }, 1000);
  378. if(idx === data.length){
  379. idx = 0;
  380. }
  381. let interval = setTimeout(() => {
  382. window.clearTimeout(interval);
  383. setVmsInterval(data, position, phase, num, idx, id);
  384. }, time * 1000);
  385. _vmsMap.get(id).set('interval', interval);
  386. }
  387. }
  388. /**
  389. * 시설물 클릭 시 카메라 영상 생성 및 이동 이벤트
  390. * @param {*} map 해당 맵 객체
  391. * @param {*} obj 해당 시설물 객체
  392. * @param {*} src 영상 소스
  393. * @param {*} X X좌표
  394. * @param {*} Y Y좌표
  395. */
  396. export async function newCamCtrl(method, obj, X, Y){
  397. let cctvBox = method(obj);
  398. $("body").append(cctvBox);
  399. let cctvLeft = X;
  400. let cctvTop = Y;
  401. const drawer = $('#drawer');
  402. const dragBox = $('#' + obj.ID);
  403. if (drawer[0].offsetWidth - X < cctvBox[0].offsetWidth){
  404. cctvLeft = drawer[0].offsetWidth - cctvBox[0].offsetWidth + 12;
  405. }
  406. if (drawer[0].offsetHeight - Y < cctvBox[0].offsetHeight){
  407. cctvTop = drawer[0].offsetHeight - cctvBox[0].offsetHeight + 59;
  408. }
  409. dragBox.css({left:cctvLeft, top:cctvTop});
  410. dragBox.draggable({ containment: "body", handle: '.cctv-box-title' });
  411. dragBox.children().eq(0).children().eq(0).on('click',function(){
  412. cctvBox.remove();
  413. });
  414. dragBox.on('mousedown', ()=>{
  415. const cctvBoxArr = $('.cctv-box');
  416. if (cctvBoxArr.length > 1) {
  417. let maxZ = Math.max(...cctvBoxArr.map((_, el) => +$(el).css('z-index') || 0).get());
  418. if (maxZ === 100 || maxZ > Number(dragBox.css('z-index'))) {
  419. maxZ++;
  420. }
  421. dragBox.css('z-index', maxZ);
  422. }
  423. })
  424. }
  425. /**
  426. * 시설물 클릭 시 카메라 영상 생성 및 이동 이벤트
  427. * @param {*} map 해당 맵 객체
  428. * @param {*} obj 해당 시설물 객체
  429. * @param {*} src 영상 소스
  430. * @param {*} X X좌표
  431. * @param {*} Y Y좌표
  432. */
  433. export function camCtrl(map, method, obj, src, X, Y, vmsTrue){
  434. let cctvBox = method(obj);
  435. $("body").append(cctvBox);
  436. let cctvLeft = X;
  437. let cctvTop = Y;
  438. if ($('#drawer')[0].offsetWidth - X < cctvBox[0].offsetWidth){
  439. cctvLeft = $('#drawer')[0].offsetWidth - cctvBox[0].offsetWidth + 12;
  440. }
  441. if ($('#drawer')[0].offsetHeight - Y < cctvBox[0].offsetHeight){
  442. cctvTop = $('#drawer')[0].offsetHeight - cctvBox[0].offsetHeight + 59;
  443. }
  444. cctvBox.css({left:cctvLeft, top:cctvTop});
  445. let cctvInfo = map.get(obj.ID);
  446. cctvInfo.set('div', cctvBox);
  447. let player = webRtcConnector(obj, $('#' + obj.ID).children().eq(1).children().eq(0), 'video' + obj.ID, vmsTrue);
  448. if (player) {
  449. cctvInfo.set('video', player);
  450. $('#video' + obj.ID).on('dblclick', function (){
  451. if (cctvBox.css('width') === '350px') {
  452. cctvBox.css('width', 700);
  453. cctvBox.css('height', 600);
  454. }
  455. else {
  456. cctvBox.css('width', 350);
  457. cctvBox.css('height', 300);
  458. }
  459. })
  460. }
  461. cctvBox.children().eq(0).children().eq(0).on('click',function(){
  462. cctvBox.remove();
  463. if (cctvInfo.get('video')) {
  464. cctvInfo.get('video').Stop();
  465. }
  466. });
  467. cctvBox.draggable({ containment: "body", handle : ".cctv-box-title" });
  468. //dragEvent(cctvBox, 'cctv-box');
  469. }
  470. /**
  471. * 카메라 영상 div 생성
  472. * @param {*} obj 데이터 객체
  473. * @returns 생성 div
  474. */
  475. export function createVideoIframe(obj){
  476. const iceInfo = _iceServerMap.get(obj.rtc_svr_ip);
  477. if (iceInfo) {
  478. const {svr_ip, svr_prot, svr_port, svr_id, svr_pswd} = iceInfo
  479. obj.local_ice_svr = svr_prot + ":" + svr_ip + ":" + svr_port;
  480. obj.local_ice_id = svr_id;
  481. obj.local_ice_pswd = svr_pswd;
  482. }
  483. const {ID, NAME, local_ice_id, local_ice_svr, local_ice_pswd, rtc_id, rtc_svr_ip, rtc_svr_port} = obj;
  484. const objInfo = {ID, NAME, local_ice_id, local_ice_svr, local_ice_pswd, rtc_id, rtc_svr_ip, rtc_svr_port};
  485. const objStr = encodeURIComponent(JSON.stringify(objInfo));
  486. let title = ID + ' - ' + NAME;
  487. if (obj.lyrInfo.lyrName === '교차로카메라') {
  488. title = obj.NMBR + ' - ' + NAME;
  489. }
  490. let div = $(`<div class="cctv-box dx-nav-item" id=${obj.ID}>
  491. <div class="b2 dx-theme-border-color cctv-box-title">${title} <span class="b0 dx-theme-border-color" title="닫기">X</span></div>
  492. <div>
  493. <iframe src="/application/op/99.common/video.html?info=${objStr}" width="100%" height="100%"></iframe>
  494. </div>
  495. </div>`);
  496. return div;
  497. }
  498. /**
  499. * 카메라 영상 div 생성
  500. * @param {*} obj 데이터 객체
  501. * @returns 생성 div
  502. */
  503. export function createVideoDiv(obj){
  504. let div = $(`<div class="cctv-box dx-nav-item" id=${obj.ID}>
  505. <div class="b2 dx-theme-border-color cctv-box-title">${obj.ID} - ${obj.NAME} <span class="b0 dx-theme-border-color" title="닫기">X</span></div>
  506. <div>
  507. <div class="bg-black" id="cctv-box${obj.ID}"></div>
  508. </div>
  509. </div>`);
  510. return div;
  511. }
  512. function webRtcConnector(obj, videoBox, id, vmsTrue){
  513. //let { web_rtc_svr_ip, web_rtc_svr_port, web_rtc_id } = obj;
  514. let { rtc_svr_ip, rtc_svr_port, rtc_id } = obj;
  515. if (vmsTrue) {
  516. rtc_svr_ip = obj.web_rtc_svr_ip;
  517. rtc_svr_port = obj.web_rtc_svr_port;
  518. rtc_id = obj.web_rtc_id;
  519. }
  520. let isNull = nullArrChecker([rtc_svr_ip, rtc_svr_port, rtc_id]);
  521. if (!isNull) {
  522. videoBox.css('cursor', 'pointer');
  523. videoBox.append($(`<video id="${id}" title="확대/축소" class="cctv-body" style="width:100%; height:100%;" autoplay playsinline muted></video>`))
  524. let video;
  525. if (rtc_id.includes('vms-')) {
  526. video = new WebRtcPlayer(id, rtc_svr_ip, rtc_svr_port, rtc_id);
  527. }
  528. else {
  529. video = new HiVeWebRtcPlayer(id, rtc_svr_ip, rtc_svr_port, rtc_id);
  530. }
  531. video.Play();
  532. return video;
  533. } else {
  534. videoBox.css('background-color', '');
  535. videoBox.append($(`<div class="empty-body" id="${id}">
  536. <h5>영상 스트리밍 정보를 확인해주세요.</h5>
  537. <br>
  538. <div class="error-content">
  539. <div class="fr">
  540. <div class='error-label'>
  541. WEB RTC IP
  542. </div>
  543. <div class='ml-5'> : </div>
  544. <div class='ml-5'>
  545. ${rtc_svr_ip}
  546. </div>
  547. </div>
  548. <div class="fr">
  549. <div class='error-label'>
  550. WEB RTC PORT
  551. </div>
  552. <div class='ml-5'> : </div>
  553. <div class='ml-5'>
  554. ${rtc_svr_port}
  555. </div>
  556. </div>
  557. <div class="fr">
  558. <div class='error-label'>
  559. WEB RTC ID
  560. </div>
  561. <div class='ml-5'> : </div>
  562. <div class='ml-5'>
  563. ${rtc_id}
  564. </div>
  565. </div>
  566. </div>
  567. </div>`))
  568. }
  569. }
  570. /**
  571. * 메시지 표출 div 생성
  572. * @param {*} obj 데이터 객체
  573. * @param {*} now 현재 시각
  574. * @returns 생성 div
  575. */
  576. export function createMessageDiv(obj, now, cmncSttsDesc){
  577. const procClass = cmncSttsDesc === "통신두절" || !cmncSttsDesc ? 't-red' : '';
  578. let div = $(`<div draggable="true" class="vms-box dx-nav-item">
  579. <div class="b2 dx-theme-border-color">${obj.ID} - ${obj.NAME} &nbsp;&nbsp;<span class="b0 dx-theme-border-color" title="닫기">X</span></div>
  580. <div>
  581. <img class='vms-img'>
  582. </div>
  583. <div class="${procClass}">${now} <span class="phase-num"></span>&nbsp;&nbsp;<span class="interval-num"></span></div>
  584. </div>`);
  585. return div;
  586. }
  587. /**
  588. * 드래그 이벤트
  589. * @param {*} position 드래그 상자 위치
  590. */
  591. export function dragEvent(position, classNm){
  592. $(position).on('mousedown', function(){
  593. for (let ii = 0; ii < $('.' + classNm).length; ii++ ){
  594. $($('.' + classNm)[ii]).css('z-index', '100');
  595. };
  596. $(position).css('z-index', '101');
  597. })
  598. position.on("dragstart", function(ev){
  599. let offsetX = ev.offsetX;
  600. let offsetY = ev.offsetY;
  601. $('#drawer').off('drop');
  602. $('#drawer').off('dragover');
  603. $('#drawer').on('dragover', function(ev){
  604. ev.preventDefault();
  605. })
  606. $('#drawer').on('drop',function(ev){
  607. ev.preventDefault();
  608. $(position).css({left : ev.clientX - offsetX, top : ev.clientY - offsetY});
  609. })
  610. });
  611. }
  612. function setTranslate(xPos, yPos, el) {
  613. el.style.transform = "translate3d(" + xPos + "px, " + yPos + "px, 0)";
  614. }
  615. function onSelectObjFunc(ALyrIdx, ALyrName, ANmbr, ACoordX, ACoordY, X, Y) {
  616. //console.log(`${nowTime()} onSelectObjFunc, ${ALyrIdx}, ${ALyrName}, ${ANmbr}, ${ACoordX}, ${ACoordY}, ${X}, ${Y}`);
  617. }
  618. function onFcltDragEndFunc(ALyrIdx, ALyrName, ANmbr, ACoordX, ACoordY) {
  619. //console.log(`${nowTime()} onFcltDragEndFunc, ${ALyrIdx}, ${ALyrName}, ${ANmbr}, ${ACoordX}, ${ACoordY}`);
  620. }
  621. export function loadingData() {
  622. fetchBaseData();
  623. fetchFcltData();
  624. fetchUnitStts();
  625. fetchIncdData(); // 돌발정보 요청
  626. //fetchFcltStts();
  627. }
  628. /**
  629. * Promise.all 사용해서 하나라도 오류가 발생하면 다음 함수가 실행되지 않도록 한다.
  630. * 개별 오류 catch 하면 다음 작업에서 계속 오류가 발생(객체를 찾지 못함)하기 때문에
  631. * 아예 다음작업이 수행되지 않도록 catch 를 한번 만 잡는다.
  632. * 즉, 오류가 발생하면 그냥 오류 발생 후 다음 작업이 진행되지 않도록 한다.
  633. */
  634. async function fetchBaseData() {
  635. //console.time("***** fetchBaseData: ");
  636. const node = apiGet("/api/database/node/list"); // 노드정보 요청
  637. const link = apiGet("/api/database/link/list"); // 링크정보 요청
  638. const ifsc = apiGet("/api/database/ifsc/list"); // 링크정보 요청
  639. const road = apiGet("/api/database/road/list"); // 도로정보 요청
  640. Promise.all([node, link, ifsc, road])
  641. .then((results) => Promise.all(results.map((r) => r.json())))
  642. .then((values) => {
  643. //console.log(`${nowTime()} BaseData, NODE(${values[0].length}), LINK(${values[1].length}), IFSC(${values[2].length}), ROAD(${values[3].length})`);
  644. _mapManager.makeLayer(LayerIndex.Node, values[0]);
  645. _mapManager.makeTrafficObject(LayerType.LINK, values[1]);
  646. _mapManager.makeTrafficObject(LayerType.IFSC, values[2]);
  647. _mapManager.makeTrafficObject(LayerType.ROAD, values[3]);
  648. _trafficMap.set('node', values[0]);
  649. _trafficMap.set('link', values[1]);
  650. _trafficMap.set('ifsc', values[2]);
  651. _trafficMap.set('road', values[3]);
  652. fetchTraffic();
  653. fetchBaseVrtx();
  654. })
  655. .catch((err) => {
  656. console.error(`${nowTime()} Error in fetchBaseData ${err}`);
  657. setTimeout(()=>fetchBaseData(), 30000);
  658. })
  659. //.finally(() => console.timeEnd("***** fetchBaseData: "));
  660. }
  661. async function fetchTraffic() {
  662. //console.time("***** fetchTraffic: ");
  663. const link = apiGet("/api/manage/main/traffic/link"); // 링크소통정보 요청
  664. const ifsc = apiGet("/api/manage/main/traffic/ifsc"); // 정보제공구간정보 요청
  665. const road = apiGet("/api/manage/main/traffic/road"); // 도로소통정보 요청
  666. // 결측구간, 반복정체구간은 async 로 조회한다.
  667. requestGet("/api/manage/main/syst-opr/miss-link-traf", recvMissLinkTraf);
  668. requestGet("/api/manage/main/syst-opr/repeat-congest", recvRepeatCongest);
  669. Promise.all([link, ifsc, road])
  670. .then((results) => Promise.all(results.map((r) => r.json())))
  671. .then((values) => {
  672. //console.log(`${nowTime()} Traffic, LINK(${values[0].length}), IFSC(${values[1].length}), ROAD(${values[2].length})`);
  673. _mapManager.updateTrafficObject(LayerType.LINK, values[0]);
  674. _mapManager.updateTrafficObject(LayerType.IFSC, values[1]);
  675. _mapManager.updateTrafficObject(LayerType.ROAD, values[2]);
  676. })
  677. .catch((err) => {
  678. console.error(`Error in fetchTraffic ${err}`);
  679. setTimeout(()=>fetchTraffic(), 30000);
  680. })
  681. //.finally(() => );
  682. // 요청시간을 기준으로 교통정보 요청 타이머 리셋
  683. requestFetchTraffic();
  684. }
  685. function recvMissLinkTraf(jsonData) {
  686. MAIN.updateMissLinkTraf(jsonData);
  687. }
  688. function recvRepeatCongest(jsonData) {
  689. MAIN.updateRepeatCongest(jsonData);
  690. }
  691. async function fetchBaseVrtx() {
  692. //console.time("***** fetchBaseVrtx: ");
  693. // 버텍스를 표출할 레벨을 설정한다.
  694. _mapManager.setLayerVisible(LayerIndex.Link1, 16);
  695. _mapManager.setLayerVisible(LayerIndex.Link2, 17, 18, 19);
  696. _mapManager.setLayerVisible(LayerIndex.Ifsc1, 14);
  697. _mapManager.setLayerVisible(LayerIndex.Ifsc2, 15);
  698. _mapManager.setLayerVisible(LayerIndex.Road1, 10);
  699. _mapManager.setLayerVisible(LayerIndex.Road2, 11, 12, 13);
  700. //console.error("***** fetchBaseVrtx_1: ");
  701. //const link1 = apiGet("/api/manage/main/map/vrtx/link/1"); // 버텍스정보 요청(1 => 16)
  702. const link2 = apiGet("/api/manage/main/map/vrtx/link/2"); // 버텍스정보 요청(2 => 17,18,19)
  703. //const ifsc3 = apiGet("/api/manage/main/map/vrtx/ifsc/3"); // 버텍스정보 요청(3 => 15)
  704. const ifsc4 = apiGet("/api/manage/main/map/vrtx/ifsc/4"); // 버텍스정보 요청(4 => 14)
  705. //const road5 = apiGet("/api/manage/main/map/vrtx/road/5"); // 버텍스정보 요청(5 => 13)
  706. const road6 = apiGet("/api/manage/main/map/vrtx/road/6"); // 버텍스정보 요청(6 => 10, 11, 12)
  707. //Promise.all([link1, link2, ifsc3, ifsc4, road5, road6])
  708. //Promise.all([link2, ifsc4, road6])
  709. Promise.all([link2, ifsc4, road6])
  710. .then((results) => Promise.all(results.map((r) => r.json())))
  711. .then((values) => {
  712. _mapManager.makeLayer(LayerIndex.Link1, values[0]);
  713. _mapManager.makeLayer(LayerIndex.Link2, values[0]);
  714. _mapManager.makeLayer(LayerIndex.Ifsc1, values[1]);
  715. _mapManager.makeLayer(LayerIndex.Ifsc2, values[1]);
  716. _mapManager.makeLayer(LayerIndex.Road1, values[2]);
  717. _mapManager.makeLayer(LayerIndex.Road2, values[2]);
  718. _trafficMap.set('link1', values[0]);
  719. _trafficMap.set('link2', values[0]);
  720. _trafficMap.set('ifsc1', values[1]);
  721. _trafficMap.set('ifsc2', values[1]);
  722. _trafficMap.set('road1', values[2]);
  723. _trafficMap.set('road2', values[2]);
  724. })
  725. .catch((err) => {
  726. console.error(`Error in fetchBaseVrtx ${err}`);
  727. setTimeout(()=>fetchBaseVrtx(), 30000);
  728. })
  729. .finally(() => {
  730. });
  731. }
  732. async function fetchFcltData() {
  733. //console.time("***** fetchFcltData: ");
  734. const cctv = apiGet("/api/cctv/common/cctv-list"); // CCTV
  735. const vms = apiGet("/api/vms/common/vms-list"); // VMS
  736. const vds = apiGet("/api/vds/common/vds-list"); // VDS
  737. const dsrc = apiGet("/api/rse/tb_rse_ctlr"); // RSE
  738. const sig = apiGet("/api/scrs/tb_sc_sgnl_ctlr"); // 신호제어기(SIG)
  739. const ccam = apiGet("/api/scrs/tb_sc_ixr_cmra_mngm/list"); // 교차로 카메라
  740. const wcam = apiGet("/api/wcam/manager/info"); // 교차로 카메라
  741. const iceServer = apiGet("/api/database/strm_ice_svr"); // 교차로 카메라
  742. Promise.all([cctv, vms, vds, dsrc, sig, ccam, wcam, iceServer])
  743. .then((results) => Promise.all(results.map((r) => r.json())))
  744. .then((values) => {
  745. // console.log(
  746. // //`${nowTime()} FcltData, CCTV(${values[0].length}), VMS(${values[1].length}), VDS(${values[2].length}), PARK(${values[3].length}), BIT(${values[4].length})`
  747. // `${nowTime()} FcltData, CCTV(${values[0].length}), VMS(${values[1].length}), VDS(${values[2].length})`
  748. // );
  749. _mapManager.makeLayer(LayerIndex.Cctv, values[0]);
  750. _mapManager.makeLayer(LayerIndex.Vms, values[1]);
  751. _mapManager.makeLayer(LayerIndex.Vds, values[2]);
  752. _mapManager.makeLayer(LayerIndex.Dsrc, values[3]);
  753. _mapManager.makeLayer(LayerIndex.Sig, values[4]);
  754. _mapManager.makeLayer(LayerIndex.WCam, values[6]);
  755. values[7].map((obj)=>{
  756. _iceServerMap.set(obj.svr_ip, obj);
  757. })
  758. // values[5].map((obj)=>{
  759. // let deg = drctMap.get(obj.drct_dvsn_cd);
  760. // const crdn = getDestinationPoint(obj.cmra_y_crdn, obj.cmra_x_crdn, deg, 25);
  761. // obj.cmra_y_crdn = crdn[1];
  762. // obj.cmra_x_crdn = crdn[0];
  763. // _crdnMap.set(obj.cmra_id, [obj.cmra_x_crdn, obj.cmra_y_crdn]);
  764. // });
  765. _mapManager.makeLayer(LayerIndex.CCam, values[5]);
  766. fetchFcltStts();
  767. })
  768. .catch((err) => {
  769. console.error(`Error in fetchFcltData ${err}`);
  770. setTimeout(()=>fetchFcltData(), 30000);
  771. $('.loading-box').css('display','none');
  772. })
  773. //.finally(() => console.timeEnd("***** fetchFcltData: "));
  774. }
  775. // 시설물 상태정보 요청(타이머 또는 웹소켓에 의해 실행됨)
  776. async function fetchFcltStts() {
  777. // console.log("***** fetchFcltStts: ");
  778. const its = apiGet("/api/common/stts/total"); // ITS 상태정보 요청
  779. //const bit = apiGet("/api/bis/stts/bit/total"); // BIT 상태정보 요청
  780. //Promise.all([its, bit])
  781. Promise.all([its])
  782. .then((results) => Promise.all(results.map((r) => r.json())))
  783. .then((values) => {
  784. //console.log(`${nowTime()} FcltStts, ITS(${values[0].fclt_list.length}))`);
  785. //console.log(`${nowTime()} FcltStts, ITS(${values[0].fclt_list.length}), BIT(${values[1].fclt_list.length})`);
  786. updateFcltStts(values[0]);
  787. MAIN.updateFcltStts(_sttsMap);
  788. })
  789. .catch((err) => {
  790. console.error(`Error in fetchFcltStts ${err}`);
  791. setTimeout(()=>fetchFcltStts(), 30000);
  792. })
  793. .finally(() => $('.loading-box').css('display','none'));
  794. //.finally(() => console.timeEnd("***** fetchFcltStts: "));
  795. // 요청시간을 기준으로 상태정보 요청 타이머 리셋
  796. requestFetchFcltStts();
  797. }
  798. function updateFcltStts(jsonData) {
  799. jsonData.fclt_list.forEach((el) => {
  800. let lyrInfo = null;
  801. const stts = _sttsMap.get(el.fclt_type);
  802. // console.log("stts : ",stts);
  803. if (!stts) {
  804. return;
  805. }
  806. let toNumber = true;
  807. if (el.fclt_type === "CCTV") {
  808. lyrInfo = _mapManager.getLayer(LayerIndex.Cctv);
  809. // toNumber = true;
  810. } else if (el.fclt_type === "VMS") {
  811. lyrInfo = _mapManager.getLayer(LayerIndex.Vms);
  812. // toNumber = true;
  813. } else if (el.fclt_type === "VDS") {
  814. lyrInfo = _mapManager.getLayer(LayerIndex.Vds);
  815. // toNumber = true;
  816. } else if (el.fclt_type === "DSRC") {
  817. lyrInfo = _mapManager.getLayer(LayerIndex.Dsrc);
  818. // toNumber = true;
  819. }
  820. else if (el.fclt_type === "SIG") {
  821. lyrInfo = _mapManager.getLayer(LayerIndex.Sig);
  822. // toNumber = true;
  823. }
  824. else if (el.fclt_type === "CCAM") {
  825. lyrInfo = _mapManager.getLayer(LayerIndex.CCam);
  826. toNumber = false;
  827. }
  828. else if (el.fclt_type === "WCAM") {
  829. lyrInfo = _mapManager.getLayer(LayerIndex.WCam);
  830. // toNumber = true;
  831. }
  832. if (lyrInfo) {
  833. stts.total = el.total_cnt;
  834. stts.normal = el.normal_cnt;
  835. stts.error = el.error_cnt;
  836. stts.collect = el.col_err_cnt;
  837. stts.objLists = el.fclt_objs;
  838. // console.log(`${nowTime()} updateFcltStts: stts: `, stts);
  839. el.fclt_objs.forEach((obj) => {
  840. const fclt = lyrInfo.findObject(toNumber ? Number(obj.fclt_nmbr) : obj.fclt_nmbr);
  841. if (fclt) {
  842. fclt.updateStts(obj.stts_cd, obj.updt_dt, obj.fclt_info1, obj.fclt_info2);
  843. // if (el.fclt_type === "CCTV" && obj.stts_cd !== "CMS0") {
  844. // console.log(`${nowTime()} updateFcltStts: CCTV: `, obj.fclt_nmbr);
  845. // }
  846. } else {
  847. console.warn(`fetchFcltStts: Not Found Object, ${obj.fclt_type}, ${obj.fclt_nmbr}, ${obj.fclt_id}`);
  848. }
  849. });
  850. } else {
  851. console.error(nowTime(), " Unknown Fclt Type: ", el.fclt_type);
  852. setTimeout(()=>updateFcltStts(), 30000);
  853. }
  854. });
  855. }
  856. // 센터프로세스 상태정보 요청(타이머 또는 웹소켓에 의해 실행됨)
  857. export async function fetchUnitStts() {
  858. if (_timerFetchUnitStts) window.clearTimeout(_timerFetchUnitStts);
  859. //console.time("***** fetchUnitStts: ");
  860. const its = apiGet("/api/common/stts/process/its"); // 센터프로세스 ITS
  861. //const bis = apiGet("/api/bis/stts/process"); // 센터프로세스 BIT
  862. Promise.all([its])
  863. .then((results) => Promise.all(results.map((r) => r.json())))
  864. .then((values) => {
  865. //console.log(`${nowTime()} UnitStts, ITS(${values[0].length}), BIS(${values[1].length})`);
  866. //console.log(`${nowTime()} UnitStts, ITS(${values[0].length})`);
  867. MAIN.updateUnitStts(values[0]); //ITS 프로세스
  868. //updateUnitStts(values[1]); //BIS 프로세스
  869. })
  870. .catch((err) => {
  871. console.error(`Error in fetchUnitStts ${err}`);
  872. })
  873. //.finally(() => console.timeEnd("***** fetchUnitStts: "));
  874. // 요청시간을 기준으로 상태정보 요청 타이머 리셋
  875. requestFetchUnitStts();
  876. }
  877. // function updateUnitStts(jsonData) {
  878. // //console.log("updateUnitStts: ", jsonData);
  879. // jsonData.forEach((obj) => {
  880. // const runStts = obj.run_sts.slice(-1);
  881. // let comStts = obj.com_sts.slice(-1);
  882. // let dbStts = obj.db_sts.slice(-1);
  883. // if (runStts == "1") {
  884. // comStts = "1";
  885. // dbStts = "1";
  886. // }
  887. // // const comImg = "<img src='/images/application_wall/stts" + comStts + ".png'>";
  888. // // //const dbImg = "<img src='/images/application_wall/stts" + dbStts + ".png'>";
  889. // // setHtml(".A" + obj.syst_id + "_server", comImg);
  890. // // if (comStts == null || comStts == "0" || comStts == "2") {
  891. // // windowPop(obj.syst_id);
  892. // // }
  893. // });
  894. // //MAIN._dataUnitSttsList = jsonData;
  895. // MAIN._gridFcltSttsBoard.option("dataSource", jsonData);
  896. // }
  897. // 돌발정보 수신
  898. function recvIncdData(jsonData) {
  899. //console.log(`${nowTime()} recvIncdData: ${jsonData.length} EA.`);
  900. _mapManager.makeLayer(LayerIndex.Incd, jsonData); // 레이어 생성
  901. MAIN.updateIncdData(jsonData);
  902. //console.timeEnd("***** fetchIncdData: ");
  903. }
  904. // 돌발정보 수신
  905. function recvAutoIncd(jsonData) {
  906. //console.log( `${ nowTime() } recvAutoIncd: ${ jsonData.length } EA.` );
  907. //MAIN.updateAutoIncd(jsonData);
  908. }
  909. // 돌발정보요청
  910. function fetchIncdData() {
  911. //console.time("***** fetchIncdData: ");
  912. requestGet("/api/manage/main/syst-opr/incd-ocrr", recvIncdData); // 돌발정보
  913. //requestGet("/api/manage/main/syst-opr/auto-incd", recvAutoIncd); // 시스템 자동 돌발 정보
  914. // 요청시간을 기준으로 돌발정보 요청 타이머 리셋
  915. requestFetchIncdData();
  916. }
  917. // 시설물 개별적으로 상태정보 요청
  918. async function fetchFcltSttsIndividual() {
  919. const cctv = apiGet("/api/cctv/monitoring/stts"); // CCTV 상태정보 요청
  920. const vms = apiGet("/api/vms/monitoring/stts"); // VMS 상태정보 요청
  921. const vds = apiGet("/api/vds/monitoring/ctlr-stts"); // VDS 상태정보 요청
  922. //const bit = apiGet("/api/bis/stts/bit"); // BIT 상태정보 요청
  923. const rse = apiGet("/api/utis/stts/rse"); // RSE 상태정보 요청
  924. //Promise.all([cctv, vms, vds, rse, bit])
  925. Promise.all([cctv, vms, vds, rse])
  926. .then((results) => Promise.all(results.map((r) => r.json())))
  927. .then((values) => {
  928. //console.log(`${nowTime()} CCTV(${values[0].length}), VMS(${values[1].length}), VDS(${values[2].length}), BIT(${values[3].length})`);
  929. //console.log(`${nowTime()} CCTV(${values[0].length}), VMS(${values[1].length}), VDS(${values[2].length})`);
  930. const cctvStts = recvCctvSttsInfo(values[0]);
  931. const vmsStts = recvVmsSttsInfo(values[1]);
  932. const vdsStts = recvVdsSttsInfo(values[2]);
  933. //const bitStts = recvBitSttsInfo(values[3]);
  934. const rseStts = recvRseSttsInfo(values[3]);
  935. //console.log(nowTime(), "CCTV: ", cctvStts);
  936. //console.log(nowTime(), " VMS: ", vmsStts);
  937. //console.log(nowTime(), " VDS: ", vdsStts);
  938. //console.log(nowTime(), " BIT: ", bitStts);
  939. //console.log(nowTime(), " RSE: ", rseStts);
  940. })
  941. .catch((err) => {
  942. console.error(`Error in fetchFcltStts ${err}`);
  943. });
  944. // 요청시간을 기준으로 시설물 상태정보 요청 타이머 리셋
  945. requestFetchFcltStts();
  946. }
  947. function recvNodeInfo(AJsonData) {
  948. //console.log("recvNodeInfo: " + AJsonData.length + " EA.");
  949. _mapManager.makeLayer(LayerIndex.Node, AJsonData);
  950. }
  951. function recvLinkInfo(AJsonData) {
  952. //console.log("recvLinkInfo: " + AJsonData.length + " EA.");
  953. _mapManager.makeTrafficObject(LayerType.LINK, AJsonData);
  954. requestGet("/api/manage/main/traffic/link", recvLinkTrafInfo); // 소통정보 요청
  955. requestGet("/api/manage/main/map/vrtx/link/1", recvLinkVrtxInfo, LayerIndex.Link1); // 버텍스정보 요청(1 => 16)
  956. requestGet("/api/manage/main/map/vrtx/link/2", recvLinkVrtxInfo, LayerIndex.Link2); // 버텍스정보 요청(2 => 17,18,19)
  957. }
  958. function recvLinkTrafInfo(AJsonData) {
  959. //console.log("recvLinkTrafInfo: " + AJsonData.length + " EA.");
  960. _mapManager.updateTrafficObject(LayerType.LINK, AJsonData);
  961. }
  962. function recvIfscInfo(AJsonData) {
  963. //console.log("recvIfscInfo: " + AJsonData.length + " EA.");
  964. _mapManager.makeTrafficObject(LayerType.IFSC, AJsonData);
  965. requestGet("/api/manage/main/traffic/ifsc", recvIfscTrafInfo); // 소통정보 요청
  966. requestGet("/api/manage/main/map/vrtx/ifsc/3", recvIfscVrtxInfo, LayerIndex.Ifsc1); // 버텍스정보 요청(3 => 14)
  967. requestGet("/api/manage/main/map/vrtx/ifsc/4", recvIfscVrtxInfo, LayerIndex.Ifsc2); // 버텍스정보 요청(4 => 15)
  968. }
  969. function recvIfscTrafInfo(AJsonData) {
  970. //console.log("recvIfscTrafInfo: " + AJsonData.length + " EA.");
  971. _mapManager.updateTrafficObject(LayerType.IFSC, AJsonData);
  972. }
  973. function recvRoadInfo(AJsonData) {
  974. //console.log("recvRoadInfo: " + AJsonData.length + " EA.");
  975. _mapManager.makeTrafficObject(LayerType.ROAD, AJsonData);
  976. requestGet("/api/manage/main/traffic/road", recvRoadTrafInfo); // 소통정보 요청
  977. requestGet("/api/manage/main/map/vrtx/road/5", recvRoadVrtxInfo, LayerIndex.Road1); // 버텍스정보 요청(5 => 10, 11, 12)
  978. requestGet("/api/manage/main/map/vrtx/road/6", recvRoadVrtxInfo, LayerIndex.Road2); // 버텍스정보 요청(6 => 13)
  979. }
  980. function recvRoadTrafInfo(AJsonData) {
  981. //console.log("recvRoadTrafInfo: " + AJsonData.length + " EA.");
  982. _mapManager.updateTrafficObject(LayerType.ROAD, AJsonData);
  983. }
  984. function recvLinkVrtxInfo(AJsonData, ALyrIdx) {
  985. //console.log(`${nowTime()} recvLinkVrtxInfo: ${ALyrIdx}, ${AJsonData.length} EA.`);
  986. _mapManager.makeLayer(ALyrIdx, AJsonData);
  987. }
  988. function recvIfscVrtxInfo(AJsonData, ALyrIdx) {
  989. //console.log(`${nowTime()} recvIfscVrtxInfo: ${ALyrIdx}, ${AJsonData.length} EA.`);
  990. _mapManager.makeLayer(ALyrIdx, AJsonData);
  991. }
  992. function recvRoadVrtxInfo(AJsonData, ALyrIdx) {
  993. //console.log(`${nowTime()} recvRoadVrtxInfo: ${ALyrIdx}, ${AJsonData.length} EA.`);
  994. _mapManager.makeLayer(ALyrIdx, AJsonData);
  995. }
  996. // CCTV
  997. function recvCctvInfo(AJsonData) {
  998. //console.log("recvCctvInfo: " + AJsonData.length + " EA.");
  999. _mapManager.makeLayer(LayerIndex.Cctv, AJsonData);
  1000. requestGet("/api/cctv/monitoring/stts", recvCctvSttsInfo); // 상태정보 요청
  1001. }
  1002. // CCTV 상태
  1003. function recvCctvSttsInfo(AJsonData) {
  1004. let stts = new FcltStts();
  1005. const lyrInfo = _mapManager.getLayer(LayerIndex.Cctv);
  1006. if (lyrInfo == null) {
  1007. return stts;
  1008. }
  1009. AJsonData.forEach((el, idx) => {
  1010. const obj = lyrInfo.findObject(el.nmbr);
  1011. if (obj) {
  1012. stts.total++;
  1013. const sttsCd = el.cmnc_stts_cd.slice(-1);
  1014. if (Number(sttsCd) == 0) {
  1015. stts.normal++;
  1016. }
  1017. obj.updateStts(el.cmnc_stts_cd, el.updt_dt);
  1018. }
  1019. });
  1020. stts.error = stts.total - stts.normal;
  1021. //console.log(`${nowTime()} recvCctvSttsInfo: ${AJsonData.length} EA.`);
  1022. return stts;
  1023. }
  1024. // VMS
  1025. function recvVmsInfo(AJsonData) {
  1026. //console.log("recvVmsInfo: " + AJsonData.length + " EA.");
  1027. _mapManager.makeLayer(LayerIndex.Vms, AJsonData);
  1028. requestGet("/api/vms/monitoring/stts", recvVmsSttsInfo); // 상태정보 요청
  1029. }
  1030. // VMS 상태
  1031. function recvVmsSttsInfo(AJsonData) {
  1032. let stts = new FcltStts();
  1033. const lyrInfo = _mapManager.getLayer(LayerIndex.Vms);
  1034. if (lyrInfo == null) {
  1035. return stts;
  1036. }
  1037. AJsonData.forEach((el, idx) => {
  1038. const obj = lyrInfo.findObject(el.nmbr);
  1039. if (obj) {
  1040. stts.total++;
  1041. const sttsCd = el.cmnc_stts_cd.slice(-1);
  1042. if (Number(sttsCd) == 0) {
  1043. stts.normal++;
  1044. }
  1045. obj.updateStts(el.cmnc_stts_cd, el.updt_dt);
  1046. }
  1047. });
  1048. stts.error = stts.total - stts.normal;
  1049. //console.log(`${nowTime()} recvVmsSttsInfo: ${AJsonData.length} EA.`);
  1050. return stts;
  1051. }
  1052. // VDS
  1053. function recvVdsInfo(AJsonData) {
  1054. //console.log("recvVdsInfo: " + AJsonData.length + " EA.");
  1055. _mapManager.makeLayer(LayerIndex.Vds, AJsonData);
  1056. requestGet("/api/vds/monitoring/ctlr-stts", recvVdsSttsInfo); // 상태정보 요청
  1057. }
  1058. // VDS 상태
  1059. function recvVdsSttsInfo(AJsonData) {
  1060. let stts = new FcltStts();
  1061. const lyrInfo = _mapManager.getLayer(LayerIndex.Vds);
  1062. if (lyrInfo == null) {
  1063. return stts;
  1064. }
  1065. AJsonData.forEach((el, idx) => {
  1066. const obj = lyrInfo.findObject(el.nmbr);
  1067. if (obj) {
  1068. stts.total++;
  1069. const sttsCd = el.cmnc_stts_cd.slice(-1);
  1070. if (Number(sttsCd) == 0) {
  1071. stts.normal++;
  1072. if (el.coll_cnt == 0) {
  1073. stts.collect++;
  1074. }
  1075. }
  1076. obj.updateStts(el.cmnc_stts_cd, el.updt_dt);
  1077. }
  1078. });
  1079. stts.error = stts.total - stts.normal;
  1080. //console.log(`${nowTime()} recvVdsSttsInfo: ${AJsonData.length} EA.`);
  1081. return stts;
  1082. }
  1083. // RSE
  1084. function recvRseInfo(AJsonData) {
  1085. //console.log("recvRseInfo: " + AJsonData.length + " EA.");
  1086. _mapManager.makeLayer(LayerIndex.Rse, AJsonData);
  1087. //requestGet("/api/utis/stts/rse", recvRseSttsInfo); // 상태정보 요청
  1088. }
  1089. // RSE 상태
  1090. function recvRseSttsInfo(AJsonData) {
  1091. let stts = new FcltStts();
  1092. const lyrInfo = _mapManager.getLayer(LayerIndex.Rse);
  1093. if (lyrInfo == null) {
  1094. return stts;
  1095. }
  1096. AJsonData.forEach((el, idx) => {
  1097. const obj = lyrInfo.findObject(el.fclt_id);
  1098. if (obj) {
  1099. stts.total++;
  1100. const sttsCd = el.stts_cd.slice(-1);
  1101. if (Number(sttsCd) == 0) {
  1102. stts.normal++;
  1103. }
  1104. obj.updateStts(el.stts_cd, el.updt_dt);
  1105. }
  1106. });
  1107. stts.error = stts.total - stts.normal;
  1108. //console.log(`${nowTime()} recvRseSttsInfo: ${AJsonData.length} EA.`);
  1109. // 시설물 상태정보 요청 타이머 설정
  1110. //_timerLoadingFcltStts = window.setTimeout(function() {
  1111. // loadingFcltStts();
  1112. //}, (60 * 1000));
  1113. return stts;
  1114. }
  1115. // Park
  1116. function recvParkInfo(AJsonData) {
  1117. //console.log("recvParkInfo: " + AJsonData.length + " EA.");
  1118. _mapManager.makeLayer(LayerIndex.Park, AJsonData);
  1119. }
  1120. // BIT
  1121. // function recvBitInfo(AJsonData) {
  1122. // console.log("recvBitInfo: " + AJsonData.length + " EA.");
  1123. // _mapManager.makeLayer(LayerIndex.Bit, AJsonData);
  1124. // }
  1125. // function recvBitSttsInfo(AJsonData) {
  1126. // let stts = new FcltStts();
  1127. // const lyrInfo = _mapManager.getLayer(LayerIndex.Bit);
  1128. // if (lyrInfo == null) {
  1129. // return stts;
  1130. // }
  1131. // AJsonData.forEach((el, idx) => {
  1132. // const obj = lyrInfo.findObject(el.fclt_id);
  1133. // if (obj) {
  1134. // stts.total++;
  1135. // const sttsCd = el.stts_cd.slice(-1);
  1136. // if (Number(sttsCd) == 0) {
  1137. // stts.normal++;
  1138. // }
  1139. // obj.updateStts(el.stts_cd, el.updt_dt);
  1140. // }
  1141. // });
  1142. // stts.error = stts.total - stts.normal;
  1143. // console.log(`${nowTime()} recvBitSttsInfo: ${AJsonData.length} EA.`);
  1144. // 시설물 상태정보 요청 타이머 설정
  1145. //_timerLoadingFcltStts = window.setTimeout(function() {
  1146. // loadingFcltStts();
  1147. //}, (60 * 1000));
  1148. // return stts;
  1149. // }
  1150. window.selectLink = function selectLink(linkId) {
  1151. const map = _mapManager.getInfo();
  1152. let lyrIdx = LayerIndex.Link2;
  1153. let zoom = map.zoom;
  1154. if (map.zoom == 16) {
  1155. lyrIdx = LayerIndex.Link1;
  1156. }
  1157. else if (map.zoom >= 17) {
  1158. lyrIdx = LayerIndex.Link2;
  1159. }
  1160. else {
  1161. zoom = 17;
  1162. lyrIdx = LayerIndex.Link2;
  1163. }
  1164. _mapManager.selectLayerObject(lyrIdx, linkId, zoom);
  1165. }