feat: 新增事务回填
This commit is contained in:
parent
27535fc82e
commit
87135fdaf0
@ -0,0 +1,23 @@
|
||||
package com.imdroid.secapi.dto;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@TableName(value = "rtktransaction")
|
||||
public class RtkTransaction {
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
Integer id;
|
||||
String device_id;
|
||||
Double latitude;
|
||||
Double longitude;
|
||||
Double altitude;
|
||||
Double ecef_x;
|
||||
Double ecef_y;
|
||||
Double ecef_z;
|
||||
Short status;
|
||||
Short checked;
|
||||
}
|
||||
|
||||
@ -0,0 +1,7 @@
|
||||
package com.imdroid.secapi.dto;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
public interface RtkTransactionMapper extends BaseMapper<RtkTransaction> {
|
||||
}
|
||||
|
||||
@ -412,6 +412,7 @@ public class APIController extends BasicController {
|
||||
}
|
||||
if(q >= 0){
|
||||
rtkMonitorService.onSolution(deviceId, q);
|
||||
try{ rtkMonitorService.onSolutionLLH(deviceId, q, lat, lon, h);}catch(Exception ignore){}
|
||||
}
|
||||
} catch (Exception e){
|
||||
String msg = "RTK " + deviceId + " " + line;
|
||||
|
||||
@ -0,0 +1,43 @@
|
||||
package com.imdroid.beidou.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.imdroid.secapi.dto.RtkTransaction;
|
||||
import com.imdroid.secapi.dto.RtkTransactionMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
@Controller
|
||||
public class RtkTransactionController extends BasicController {
|
||||
@Autowired
|
||||
RtkTransactionMapper mapper;
|
||||
|
||||
@RequestMapping("/page/rtk_transactions")
|
||||
public String page(Model m, HttpSession session){
|
||||
initModel(m, session);
|
||||
return "/page/rtk_transactions";
|
||||
}
|
||||
|
||||
@RequestMapping("/rtk/transaction/list")
|
||||
@ResponseBody
|
||||
public JSONObject list(int page, int limit, String device_id){
|
||||
Page<RtkTransaction> pageable = new Page<>(page, limit);
|
||||
QueryWrapper<RtkTransaction> qw = new QueryWrapper<>();
|
||||
if(device_id!=null && !device_id.isEmpty()) qw.eq("device_id", device_id);
|
||||
IPage<RtkTransaction> cs = mapper.selectPage(pageable, qw);
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("code",0);
|
||||
json.put("msg","");
|
||||
json.put("count", cs.getTotal());
|
||||
json.put("data", cs.getRecords());
|
||||
return json;
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
public class RtkMonitorService {
|
||||
private final Map<String, Integer> consecFix = new ConcurrentHashMap<>();
|
||||
private final Map<String, Boolean> running = new ConcurrentHashMap<>();
|
||||
private final Map<String, java.util.LinkedList<double[]>> fixBuffer = new ConcurrentHashMap<>();
|
||||
|
||||
@Autowired
|
||||
RtkrcvClient rtkrcvClient;
|
||||
@ -21,10 +22,12 @@ public class RtkMonitorService {
|
||||
public void onStart(String deviceId){
|
||||
running.put(deviceId, true);
|
||||
consecFix.put(deviceId, 0);
|
||||
fixBuffer.remove(deviceId);
|
||||
}
|
||||
public void onStop(String deviceId){
|
||||
running.remove(deviceId);
|
||||
consecFix.remove(deviceId);
|
||||
fixBuffer.remove(deviceId);
|
||||
}
|
||||
public void onSolution(String deviceId, int q){
|
||||
if(Boolean.TRUE.equals(running.get(deviceId))){
|
||||
@ -32,9 +35,17 @@ public class RtkMonitorService {
|
||||
consecFix.merge(deviceId, 1, Integer::sum);
|
||||
} else {
|
||||
consecFix.put(deviceId, 0);
|
||||
fixBuffer.remove(deviceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
public void onSolutionLLH(String deviceId, int q, double lat, double lon, double h){
|
||||
if(Boolean.TRUE.equals(running.get(deviceId)) && q==1){
|
||||
java.util.LinkedList<double[]> buf = fixBuffer.computeIfAbsent(deviceId,k->new java.util.LinkedList<>());
|
||||
buf.add(new double[]{lat,lon,h});
|
||||
if(buf.size()>100) buf.removeFirst();
|
||||
}
|
||||
}
|
||||
|
||||
@Scheduled(fixedRate = 30000)
|
||||
public void check(){
|
||||
@ -44,6 +55,7 @@ public class RtkMonitorService {
|
||||
if(Boolean.TRUE.equals(running.get(dev)) && cnt != null && cnt >= 40){
|
||||
try { rtkrcvClient.stop(dev); } catch (Exception ignore) {}
|
||||
running.remove(dev);
|
||||
try { writeTransaction(dev); } catch (Exception ignore) {}
|
||||
try {
|
||||
com.alibaba.fastjson.JSONObject ctrl = new com.alibaba.fastjson.JSONObject();
|
||||
ctrl.put("type","rtk_ctrl");
|
||||
@ -55,4 +67,41 @@ public class RtkMonitorService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@org.springframework.beans.factory.annotation.Autowired
|
||||
com.imdroid.secapi.dto.RtkTransactionMapper rtkTransactionMapper;
|
||||
|
||||
private void writeTransaction(String deviceId){
|
||||
java.util.LinkedList<double[]> buf = fixBuffer.get(deviceId);
|
||||
if(buf==null || buf.size()<40) return;
|
||||
java.util.List<double[]> last = buf.subList(Math.max(buf.size()-40,0), buf.size());
|
||||
double[] latArr = new double[last.size()];
|
||||
double[] lonArr = new double[last.size()];
|
||||
double[] hArr = new double[last.size()];
|
||||
for(int i=0;i<last.size();i++){ latArr[i]=last.get(i)[0]; lonArr[i]=last.get(i)[1]; hArr[i]=last.get(i)[2]; }
|
||||
double lat = trimmedMean(latArr);
|
||||
double lon = trimmedMean(lonArr);
|
||||
double alt = trimmedMean(hArr);
|
||||
com.imdroid.beidou.util.GeoCoordConverterUtil.LLA_Coordinate L = new com.imdroid.beidou.util.GeoCoordConverterUtil.LLA_Coordinate(lat,lon,alt);
|
||||
com.imdroid.beidou.util.GeoCoordConverterUtil.ECEF_Coordinate E = com.imdroid.beidou.util.GeoCoordConverterUtil.LLA2ECEF(L);
|
||||
com.imdroid.secapi.dto.RtkTransaction t = new com.imdroid.secapi.dto.RtkTransaction();
|
||||
t.setDevice_id(deviceId);
|
||||
t.setLatitude(lat);
|
||||
t.setLongitude(lon);
|
||||
t.setAltitude(alt);
|
||||
t.setEcef_x(E.ECEF_X);
|
||||
t.setEcef_y(E.ECEF_Y);
|
||||
t.setEcef_z(E.ECEF_Z);
|
||||
t.setStatus((short)1);
|
||||
t.setChecked((short)0);
|
||||
rtkTransactionMapper.insert(t);
|
||||
fixBuffer.remove(deviceId);
|
||||
}
|
||||
|
||||
private double trimmedMean(double[] arr){
|
||||
java.util.Arrays.sort(arr);
|
||||
if(arr.length<=2){ return arr.length==0?0: (arr.length==1?arr[0]:(arr[0]+arr[1])/2.0); }
|
||||
double sum=0; for(int i=1;i<arr.length-1;i++) sum+=arr[i];
|
||||
return sum/(arr.length-2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,33 @@
|
||||
package com.imdroid.beidou.util;
|
||||
|
||||
public class GeoCoordConverterUtil {
|
||||
public static class LLA_Coordinate {
|
||||
public double Latitude;
|
||||
public double Longitude;
|
||||
public double Altitude;
|
||||
public LLA_Coordinate(double lat,double lon,double alt){ this.Latitude=lat; this.Longitude=lon; this.Altitude=alt; }
|
||||
}
|
||||
public static class ECEF_Coordinate {
|
||||
public double ECEF_X;
|
||||
public double ECEF_Y;
|
||||
public double ECEF_Z;
|
||||
public ECEF_Coordinate(double x,double y,double z){ this.ECEF_X=x; this.ECEF_Y=y; this.ECEF_Z=z; }
|
||||
}
|
||||
public static ECEF_Coordinate LLA2ECEF(LLA_Coordinate L){
|
||||
double a = 6378137.0;
|
||||
double e2 = 6.69437999014e-3;
|
||||
double lat = Math.toRadians(L.Latitude);
|
||||
double lon = Math.toRadians(L.Longitude);
|
||||
double h = L.Altitude;
|
||||
double sinLat = Math.sin(lat);
|
||||
double cosLat = Math.cos(lat);
|
||||
double cosLon = Math.cos(lon);
|
||||
double sinLon = Math.sin(lon);
|
||||
double N = a / Math.sqrt(1 - e2 * sinLat * sinLat);
|
||||
double x = (N + h) * cosLat * cosLon;
|
||||
double y = (N + h) * cosLat * sinLon;
|
||||
double z = (N * (1 - e2) + h) * sinLat;
|
||||
return new ECEF_Coordinate(x,y,z);
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,10 +54,24 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "日志",
|
||||
"href": "page/gnss_single_data",
|
||||
"title": "定位管理",
|
||||
"href": "",
|
||||
"icon": "fa fa-clipboard",
|
||||
"target": "_self"
|
||||
"target": "_self",
|
||||
"child": [
|
||||
{
|
||||
"title": "通用",
|
||||
"href": "page/rtkrcv",
|
||||
"icon": "fa fa-minus",
|
||||
"target": "_self"
|
||||
},
|
||||
{
|
||||
"title": "事务管理",
|
||||
"href": "page/rtk_transactions",
|
||||
"icon": "fa fa-minus",
|
||||
"target": "_self"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "配置管理",
|
||||
@ -82,12 +96,6 @@
|
||||
"href": "page/cmd_line",
|
||||
"icon": "fa fa-minus",
|
||||
"target": "_self"
|
||||
},
|
||||
{
|
||||
"title": "定位管理",
|
||||
"href": "page/rtkrcv",
|
||||
"icon": "fa fa-minus",
|
||||
"target": "_self"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@ -0,0 +1,62 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>RTK事务</title>
|
||||
<meta name="renderer" content="webkit">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<link rel="stylesheet" href="../lib/layui-v2.6.3/css/layui.css" media="all">
|
||||
<link rel="stylesheet" href="../css/public.css" media="all">
|
||||
</head>
|
||||
<body>
|
||||
<div class="layuimini-container">
|
||||
<div class="layuimini-main">
|
||||
<fieldset class="table-search-fieldset">
|
||||
<legend>查询</legend>
|
||||
<div style="margin:10px">
|
||||
<form class="layui-form layui-form-pane" action="" id="txSearch">
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">设备号</label>
|
||||
<div class="layui-input-inline">
|
||||
<input type="text" name="device_id" id="tx-device" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<button type="submit" class="layui-btn layui-btn-primary" lay-submit lay-filter="tx-search-btn"><i class="layui-icon"></i> 搜 索</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</fieldset>
|
||||
<table class="layui-hide" id="txTable" lay-filter="txTableFilter"></table>
|
||||
</div>
|
||||
</div>
|
||||
<script src="../lib/layui-v2.6.3/layui.js" charset="utf-8"></script>
|
||||
<script>
|
||||
layui.use(['form','table'], function(){
|
||||
var $=layui.$, form=layui.form, table=layui.table;
|
||||
function render(params){
|
||||
table.render({
|
||||
elem:'#txTable', url:'/rtk/transaction/list', where: params||{},
|
||||
cols:[ [
|
||||
{field:'device_id', title:'设备号', width:120},
|
||||
{field:'latitude', title:'纬度', width:140},
|
||||
{field:'longitude', title:'经度', width:140},
|
||||
{field:'altitude', title:'高程', width:120},
|
||||
{field:'ecef_x', title:'ECEF_X'},
|
||||
{field:'ecef_y', title:'ECEF_Y'},
|
||||
{field:'ecef_z', title:'ECEF_Z'},
|
||||
{field:'status', title:'状态', width:80, templet:function(d){ return d.status==1?'<span class="layui-badge layui-bg-green">固定</span>':'<span class="layui-badge layui-bg-orange">浮点</span>'; }},
|
||||
{field:'checked', title:'已检查', width:80, templet:function(d){ return d.checked?'<span class="layui-badge layui-bg-blue">是</span>':'<span class="layui-badge">否</span>'; }}
|
||||
] ], page:true, limits:[10,20,50,100], limit:10
|
||||
});
|
||||
}
|
||||
render({});
|
||||
form.on('submit(tx-search-btn)', function(data){ render(data.field); return false; });
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user