시나리오
정보시스템은 다양한 데이터소스를 의미있게 전달하는 것으로 정의할 수 있다. 기온, 미세먼지 등 실시간으로 수치화되어 나타나는 정보는 기본적으로 데이터소스가 DB시스템에 저장된 정보가 나타나는 것이 아니라 센서에서 취득되는 정보라고 할 수 있다. 이를 사용자에게 전달하기 위한 과정은 복잡하지만 임의로 몇 개의 센서를 설치하여 센서의 정상 동작 여부를 모니터링하는 시나리오를 정의했다.
> 서비스바로가기
목적 및 작업 계획
- 센서작동현황 버튼을 이용하여 사용자가 지정한 일정한 시간 간격으로 해당 데이터의 정보를 Web Socket을 이용하여 전달
- Web Socket을 통해 전달 받은 데이터의 상태 변화를 지도 위에 시각화
- 앞 과정을 통해 그룹 내 모든 사용자는 동일한 화면 공유 가능
구성 요약
1. Soket 서버 : 웹 브라우저와 메세지 교환
- Web Socket의 기본형태는 아래소스와 같이 Open, Close, Error, Message 구분
- 46행 : @onMessage를 통해 check Sensor Receiver에서 데이터 정보를 받아 데이터의 상태 정보를 전달
- 48행 : 새로고침에 따른 중복 메세지 방지를 위해 runCheck 조건문
- 59행 : SensorInfo.getSensorInfo()클래스를 통해 데이터의 상태 정보 가져와 check Sensor Receiver에 다시 전달
- 49행/70행~71행 : 타이머 기능을 통해 지정한 시간 간격으로 정보를 갱신하여 check Sensor Receiver에 전달
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | package egovframework.map.service; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Timer; import java.util.TimerTask; import javax.websocket.OnClose; import javax.websocket.OnError; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.ServerEndpoint; import org.springframework.stereotype.Controller; import egovframework.map.web.SensorInfo; @Controller @ServerEndpoint("/websocket") public class WSocketServer {     static List<Session> sessionUsers = Collections.synchronizedList(new ArrayList<Session>());     static Boolean runCheck = false;     @OnOpen     public void onOpen(Session userSession) {         System.out.println("Open Connection!...");         sessionUsers.add(userSession);     }     @OnClose     public void onClose(Session userSession) {         System.out.println("Close Connection!...");         sessionUsers.remove(userSession);     }     @OnError     public void onError(Throwable e) {         e.printStackTrace();     }     @OnMessage     public void onMessage(String message) throws IOException {         if(runCheck == false){ TimerTask task = new TimerTask() {               @Override               public void run() {               String sensorInfo = SensorInfo.getSensorInfo();                Iterator<Session> itr = sessionUsers.iterator();                   while (itr.hasNext()) {                      try {                          Session session = itr.next();                          session.getBasicRemote().sendText(sensorInfo);                      } catch (IOException e) {                                                  e.printStackTrace();                     }                   }               }          }; runCheck = true;          Timer timer = new Timer(true);          timer.scheduleAtFixedRate(task, 0, 1*1000); };     } } | 
2. check Sensor Receiver
check Sensor Receiver는 센서의 위치 및 상태 정보를 공유할 수 있는 페이지로 지도 위에 위치한 센서의 현재 상태 및 일정 시간 간격으로 변화 상태를 체크하여 공유할 수 있는 페이지다. check Sensor Receiver 페이지의 소스는 아래와 같다.
2.1 <script></script>부분(openlayers3 및 geojson 데이터 부분)
- 19행 : QGIS를 통해 제작한 Json파일 경로
- 36행 : openlayer3 map 불러오기
- 49행 : 19행에서 지정한 경로의 파일을 geoJson 포맷으로 openlayers map에 올리기
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | <script type="text/javascript"> var map,     ftData,     vectorSource,     vectorSocket,     vectorLayer,     d3Data,     d3Style; var changeFillColor,     changeStrokeColor; var raster = new ol.layer.Tile({     source: new ol.source.XYZ({         url: 'http://xdworld.vworld.kr:8080/2d/Base/201802/{z}/{x}/{y}.png'     }) }); //geojson 파일 경로 var geoUrl = "/js/data/geojson/sensor_point_3857.json"; var ftStyle =  new ol.style.Style({     image: new ol.style.Circle({         radius: 10,         fill: new ol.style.Fill({             color: "rgba(0, 255, 0, 1)"         }),         stroke: new ol.style.Stroke({             color: "rgba(0, 0, 0, 1)",             width: 2         }),     }) }); $(document).ready(function(){     //openlayers3 map     map = new ol.Map({         layers: [raster],         target: 'map',         view: new ol.View({             center: [14128579.82, 4512570.74],             zoom: 13.5,             maxZoom: 19         })     }); }); //geojson data 지도 표출 $.getJSON(geoUrl, function( data ) {     var format = new ol.format.GeoJSON();     vectorSource = new ol.source.Vector({         features: format.readFeatures(data)     });     vectorSocket = vectorSource.getFeatures();     vectorLayer = new ol.layer.Vector({         source: vectorSource,         style : vectorSource.forEachFeature(function(features){             ftData = features;             var originStyle = ftStyle;             ftData.setStyle(originStyle);         })     });     map.addLayer(vectorLayer); });     </script> | cs | 
2.2 <script></script>부분(socket 통신 부분)
- 3행 : Web Socket통신 연결
- 8행~11행 : Web Socket통신 function 함수 실행
- 33행 : Web Socket통신을 통해 데이터의 정보를 전달 받아 지도 위에 표출 및 상태 메세지 전송
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | <script type="text/javascript">     var webSocket = new WebSocket("ws://***.***.*.**:8080/websocket2");     var echoText = document.getElementById("echoText");     echoText.value = "";     webSocket.onopen = function(message){ wsOpen(message);};     webSocket.onmessage = function(message){ wsGetMessage(message);};     webSocket.onclose = function(message){ wsClose(message);};     webSocket.onerror = function(message){ wsError(message);};     function wsOpen(message){         echoText.value += "Connected ... \n"; webSendMessage();     };     function wsCloseConnection(){         webSocket.close();     };     function wsSendMessage(){         webSocket.send(vectorSocket);     };     function wsGetMessage(message){         pointStyle(message.data);     };     function wsClose(message){        echoText.value += "Disconnect ... \n";     };     function wserror(message){         echoText.value += "Error ... \n";     };     function pointStyle(ft){         var resultStyle;         var jsonft = JSON.parse(ft);         var vectorFts = vectorSource.getFeatures();         for(var i = 0; i < vectorFts.length; i++){             if(i ==  jsonft.index){                 if(jsonft.code == 1){                     //노랑                     changeFillColor = "rgba(255, 255, 0, 1)";                     echoText.value += i +"번 "+"센서(위치정보 :"+ vectorFts[i].getGeometry().getCoordinates()                                 +")에 이상이 감지되었습니다.(코드번호 :"+jsonft.code+"번 ) \n";                 }else if(jsonft.code == 2){                     //빨강                     changeFillColor = "rgba(255, 0, 0, 1)";                     echoText.value += i +"번"+"센서(위치정보 :"+ vectorFts[i].getGeometry().getCoordinates()                                 +")센서를 점검해주십시오.(코드번호 :"+jsonft.code+"번 ) \n";                 }                 resultStyle =  new ol.style.Style({                     image: new ol.style.Circle({                         radius: 10,                         fill: new ol.style.Fill({                             color: changeFillColor                         }),                         stroke: new ol.style.Stroke({                             color: "rgba(0, 0, 0, 1)",                             width: 2                         }),                     })                 });             }else{                 resultStyle = ftStyle;             }                 vectorSource.getFeatures()[i].setStyle(resultStyle);         };     };         </script> | cs | 
2.3 <body></body>부분
- 5행 : openlayers map을 화면에 표출하기 위한 div태그 id 선언
- 12행 : 데이터 작동 현황 시작 버튼 생성(Web Socket실행)
- 49행 : Web Socket통신 종료
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <div class="container-fluid">     <div class="row content">         <div class="col-sm-6" style= "border-right: 1px solid;">             <h1>Sensor Location</h1>             <div id="map"></div>         </div>         <div class="col-sm-6" style= "border-left: 1px solid;">             <h1>Emergency Message</h1>             <textarea id="echoText" rows="500" cols="700"></textarea>                     </div>     </div> </div> | cs | 
3. 실행 화면 및 사용법
테스트는 IE, 크롬, Microsoft Edge에서 진행하였으며, check Sensor Receiver 페이지 접속 시 센서의 상태정보가 실시간으로 반영되어 센세의 상태정보가 변경된다.
- 노란색 : 센서 상태 이상감지(코드번호 1번)
- 빨간색 : 센서 점검 필요(코드번호 2번)
1. check Sensor Receiver 페이지를 IE, 크롬, Microsoft Edge에서 접속한다.
2. 우측 메세지창<textarea id="echoText" rows="500" cols="700"></textarea> 에 센서의 위치정보 및 이상 감지 메세지가 표출되는지 확인한다.
3.1 테스트 결과 화면

> 서비스바로가기
'꿀팁 - OpenLayers, Leaflet' 카테고리의 다른 글
| leaflet SHP 파일 올리기 (0) | 2019.05.14 | 
|---|---|
| leaflet에서 D3를 이용한 TSP(traveling salesman problem) 활용 (1) | 2019.04.05 | 
| Openlayers3와 Leaflet에서 Feature Click Event (2) | 2019.02.22 | 
| Openlayers3와 Leaflet에서 D3 TopoJson 이용하기 (1) | 2019.01.30 | 
| OpenLayers와 Leaflet에서 User Control 등록하기(거리재기) (0) | 2019.01.11 | 
