概述
很多时候,我们有这样的使用场景:外业人员在外作业,我们需要知道人员的当前的实时位置和人员信息,如何实现呢?本文将为大家简单的说明该场景下我们应该实现。
效果


思路
解决实时位置的展示,最核心的有两点:1、数据的传输与存储;2、设备端如何和监控端进行数据交互。
首先,我们来说第一个的问题:数据的传输与存储。大多时候,设备传输过来的位置信息数需要做存储的,除了个别情况外。因此,我们可以考虑在数据库中建立一张表,来记录设备的实时位置数据。
-- 创建表
CREATE TABLE location_track
(
id serial NOT NULL,
lon double precision NOT NULL,
lat double precision NOT NULL,
create_time time(10) with time zone NOT NULL,
geom geometry not null,
PRIMARY KEY (id)
)
其次,数据交互问题。这个问题的解决方式有两种:1、前端的定时刷新;2、后端的实时推送。如果是前端的定时刷新,我们可以用setInterval(function, time)来处理;如果是后端的实时推送,这里面涉及两个方面的思考:a、位置信息传输过来入库后的触发器;b、websocket数据的实时推送。
实现
- 在本demo中,为了实现效果,表创建完成后,先在在表中插入了一批数据,以作测试。
insert into location_track(lon, lat, create_time, geom) values(116.379883, 39.865601, now(), st_point(116.379883, 39.865601));
insert into location_track(lon, lat, create_time, geom) values(116.379997, 39.865498, now(), st_point(116.379997, 39.865498));
insert into location_track(lon, lat, create_time, geom) values(116.380104, 39.865364, now(), st_point(116.380104, 39.865364));
- 一次性将全部数据取出来,做个定时处理,来模拟位置的实时更新效果(在实际中,只需要在触发器里面获取最新的记录即可)。
package com.lzugis.web.websocket;
import com.lzugis.services.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
@RequestMapping("/websocket")
public class LocationTrackEndPoint extends TextWebSocketHandler {
@Autowired
private TestService testService;
private Timer timer;
private static int rownum = 1;
private List gpsData;
@Override
protected void handleTextMessage(WebSocketSession session,
TextMessage message) throws Exception {
if(!session.isOpen()){
timer.cancel();
return;
}
super.handleTextMessage(session, message);
session.sendMessage(message);
}
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
timer = new Timer(true);
long delay = 0;
rownum = 0;
OrderTimeTask orderTimeTask = new OrderTimeTask(session);
gpsData = testService.getGpsData();
timer.schedule(orderTimeTask, delay, 1000);// 设定指定的时间time,此处为5s
}
class OrderTimeTask extends TimerTask{
private WebSocketSession session;
public OrderTimeTask(WebSocketSession session){
this.session = session;
}
@Override
public void run() {
try {
String lonlat = ((Map)gpsData.get(rownum)).get("lonlat").toString();
TextMessage textMessage = new TextMessage(lonlat);
handleMessage(session,textMessage);
rownum++;
if(rownum>gpsData.size()-1){
rownum = 0;
}
} catch (Exception e){
e.printStackTrace();
}
}
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
System.out.println("Connection Closed!");
}
}
3、前端获取位置,并将所有的位置信息保存下来,用以渲染回显路径。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>websocket</title>
<link rel="stylesheet" type="text/css" href="plugin/ol4/ol.css"/>
<style>
body, #map {
border: 0px;
margin: 0px;
padding: 0px;
width: 100%;
height: 100%;
font-size: 13px;
overflow: hidden;
}
#map{
background: #000000;
}
</style>
</head>
<body>
<div id="map"></div>
<script src="plugin/ol4/ol.js"></script>
<script type="text/javascript">
function getTdtSource(lyr) {
var url = "http://t0.tianditu.com/DataServer?T=" + lyr + "&X={x}&Y={y}&L={z}";
return new ol.source.XYZ({
url: url
});
}
var base_lyr = new ol.layer.Tile({
source: getTdtSource("vec_w")
});
var anno_lyr = new ol.layer.Tile({
source: getTdtSource("cva_w")
});
var vector = new ol.layer.Vector({
source: null,
style:new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#3a8c4a',
width: 4
}),
image: new ol.style.Circle({
radius: 8,
stroke: new ol.style.Stroke({
color: '#ffffff',
width: 2
}),
fill: new ol.style.Fill({
color: '#ab2e2a'
})
})
})
});
var projection = new ol.proj.Projection({
code: 'EPSG:3857',
units: 'm'
});
var linesdata = [];
var map = new ol.Map({
controls: ol.control.defaults({
attribution: false
}),
target: 'map',
layers: [
base_lyr,
anno_lyr,
vector
],
view: new ol.View({
projection: projection,
center: ol.proj.transform([116.397428, 39.90923], 'EPSG:4326', 'EPSG:3857'),
zoom: 13
})
});
var websocket = null;
//判断当前浏览器是否支持WebSocket
if ('WebSocket' in window) {
websocket = new WebSocket("ws://localhost:8081/lzugis-web/websocket");
}
else {
alert('当前浏览器 Not support websocket')
}
//连接发生错误的回调方法
websocket.onerror = function () {
console.log("WebSocket连接发生错误");
};
//连接成功建立的回调方法
websocket.onopen = function () {
console.log("WebSocket连接成功");
};
//接收到消息的回调方法
websocket.onmessage = function (event) {
setMessageInnerHTML(event.data);
};
//连接关闭的回调方法
websocket.onclose = function () {
console.log("WebSocket连接关闭");
};
//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function () {
closeWebSocket();
};
//将消息显示在网页上
function setMessageInnerHTML(data) {
var features = [];
var location = data.split(",");
var coord = ol.proj.transform([parseFloat(location[0]),parseFloat(location[1])],"EPSG:4326","EPSG:3857");
linesdata.push(coord);
if(linesdata.length>1){
var line = new ol.Feature({
geometry: new ol.geom.LineString(linesdata)
});
features.push(line);
}
var feature = new ol.Feature({
geometry: new ol.geom.Point(coord)
});
features.push(feature);
var source = new ol.source.Vector({
features: features
});
vector.setSource(source);
}
//关闭WebSocket连接
function closeWebSocket() {
websocket.close();
}
</script>
</body>
</html>
技术博客
CSDN:http://blog.csdn.NET/gisshixisheng
博客园:http://www.cnblogs.com/lzugis/
在线教程
https://edu.csdn.net/course/detail/7471
Github
https://github.com/lzugis/
联系方式
类型 | 内容 |
---|---|
1004740957 | |
公众号 | lzugis15 |
niujp08@qq.com | |
webgis群 | 452117357 |
Android群 | 337469080 |
GIS数据可视化群 | 458292378 |
网友评论