시나리오
정보시스템은 다양한 데이터소스를 의미있게 전달하는 것으로 정의할 수 있다. 기온, 미세먼지 등 실시간으로 수치화되어 나타나는 정보는 기본적으로 데이터소스가 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) 활용 (0) | 2019.04.05 |
Openlayers3와 Leaflet에서 Feature Click Event (0) | 2019.02.22 |
Openlayers3와 Leaflet에서 D3 TopoJson 이용하기 (0) | 2019.01.30 |
OpenLayers와 Leaflet에서 User Control 등록하기(거리재기) (0) | 2019.01.11 |