시나리오

정보시스템은 다양한 데이터소스를 의미있게 전달하는 것으로 정의할 수 있다. 기온, 미세먼지 등 실시간으로 수치화되어 나타나는 정보는 기본적으로 데이터소스가 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, 01*1000);
    
};
    }
 
}
 

cs

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.824512570.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 테스트 결과 화면

 

서비스바로가기

+ Recent posts