1、健康检查增加基站/测站/设备型号

2、增加滤波结果跳变检查
This commit is contained in:
weidong 2025-02-18 12:33:23 +08:00
parent 62f45f3fac
commit 39caedce90
13 changed files with 138 additions and 28 deletions

View File

@ -0,0 +1,36 @@
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;
import java.time.LocalDateTime;
/**
* GNSS设备配置数据
*
* @author LiGang
*/
@Data
@TableName(value = "ehm")
public class EhmJoin {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
private Integer tenantid;
private String deviceid;
private Short devicetype;
private Short model;
private LocalDateTime createtime;
private Short offlinestatdays;
private Integer offlinecount;
private Integer offlineminutes;
private Integer calcstathours;
private Float stdeve;
private Float stdevn;
private Float stdevu;
private Float fixrate;
private Float validrate;
private Integer jumpcount;
}

View File

@ -1,8 +1,8 @@
package com.imdroid.secapi.dto; package com.imdroid.secapi.dto;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.github.yulichang.base.MPJBaseMapper;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
@Mapper @Mapper
public interface EhmMapper extends BaseMapper<Ehm> { public interface EhmMapper extends MPJBaseMapper<Ehm> {
} }

View File

@ -76,6 +76,8 @@ public class GnssStatusJoin {
@ExcelProperty("设备类型") @ExcelProperty("设备类型")
Short devicetype; Short devicetype;
@ExcelProperty("设备型号")
Short model;
@ExcelIgnore @ExcelIgnore
Integer group_id; Integer group_id;

View File

@ -19,26 +19,26 @@ public interface GnssStatusMapper extends MPJBaseMapper<GnssStatus> {
@Update({"update gnssstatus set state=0,warning=#{warning},warningcode=#{warningcode} where deviceid=#{deviceid}"}) @Update({"update gnssstatus set state=0,warning=#{warning},warningcode=#{warningcode} where deviceid=#{deviceid}"})
int setOfflineByDeviceId(GnssStatusJoin status); int setOfflineByDeviceId(GnssStatusJoin status);
@Select({"select s.*, d.devicetype, d.group_id, d.name from gnssstatus s ,gnssdevices d where s.deviceid=d.deviceid and s.state <> 0"}) @Select({"select s.*, d.devicetype, d.model, d.group_id, d.name, d.project_id from gnssstatus s ,gnssdevices d where s.deviceid=d.deviceid and s.state <> 0"})
List<GnssStatusJoin> queryOnline(); List<GnssStatusJoin> queryOnline();
@Select({"select s.*, d.devicetype, d.group_id, d.name from gnssstatus s ,gnssdevices d where " + @Select({"select s.*, d.devicetype, d.model, d.group_id, d.name, d.project_id from gnssstatus s ,gnssdevices d where " +
"s.deviceid=d.deviceid and d.tenantid<>0 and d.opmode=0"}) "s.deviceid=d.deviceid and d.tenantid<>0 and d.opmode=0"})
List<GnssStatusJoin> queryDeployed(); List<GnssStatusJoin> queryDeployed();
@Select({"select s.*, d.devicetype, d.group_id, d.name, d.project_id from gnssstatus s ,gnssdevices d where " + @Select({"select s.*, d.devicetype, d.model, d.group_id, d.name, d.project_id from gnssstatus s ,gnssdevices d where " +
"s.deviceid=d.deviceid and d.tenantid = #{tenantid} and d.opmode=0"}) "s.deviceid=d.deviceid and d.tenantid = #{tenantid} and d.opmode=0"})
List<GnssStatusJoin> queryDeployedByTenant(int tenantid); List<GnssStatusJoin> queryDeployedByTenant(int tenantid);
//多个入参要用Param注解 //多个入参要用Param注解
@Select({"select s.*, d.devicetype, d.group_id, d.name, d.project_id from gnssstatus s ,gnssdevices d where " + @Select({"select s.*, d.devicetype, d.model, d.group_id, d.name, d.project_id from gnssstatus s ,gnssdevices d where " +
"s.deviceid=d.deviceid and d.tenantid = #{tenantid} and d.opmode=0 and d.project_id = #{projectName}"}) "s.deviceid=d.deviceid and d.tenantid = #{tenantid} and d.opmode=0 and d.project_id = #{projectName}"})
List<GnssStatusJoin> queryDeployedByProject(@Param("tenantid") int tenantid, @Param("projectName") String projectName); List<GnssStatusJoin> queryDeployedByProject(@Param("tenantid") int tenantid, @Param("projectName") String projectName);
// 需要关联设备类型 // 需要关联设备类型
@Select({"select s.*, d.devicetype from gnssstatus s ,gnssdevices d where s.deviceid=d.deviceid and s.deviceid = #{deviceId}"}) @Select({"select s.*, d.devicetype, d.model, d.group_id, d.name, d.project_id from gnssstatus s ,gnssdevices d where s.deviceid=d.deviceid and s.deviceid = #{deviceId}"})
GnssStatusJoin queryByDeviceId(String deviceId); GnssStatusJoin queryByDeviceId(String deviceId);
@Select({"select s.*, d.devicetype from gnssstatus s ,gnssdevices d where s.deviceid=d.deviceid"}) @Select({"select s.*, d.devicetype, d.model, d.group_id, d.name, d.project_id from gnssstatus s ,gnssdevices d where s.deviceid=d.deviceid"})
GnssStatusJoin queryAll(); GnssStatusJoin queryAll();
} }

View File

@ -42,6 +42,8 @@ public class WarningCfg {
public static final String TYPE_NAME_CONT_INVALID_RESULT = "长时间无有效解"; public static final String TYPE_NAME_CONT_INVALID_RESULT = "长时间无有效解";
public static final int TYPE_INCLINE = 0x400; public static final int TYPE_INCLINE = 0x400;
public static final String TYPE_NAME_INCLINE = "异常倾斜"; public static final String TYPE_NAME_INCLINE = "异常倾斜";
public static final int TYPE_JUMP = 0x800;
public static final String TYPE_NAME_JUMP = "滤波结果跳变";
// warning level definition // warning level definition
public static final short LEVEL_0 = 0; //正常 public static final short LEVEL_0 = 0; //正常

View File

@ -279,11 +279,15 @@ public class SingleLineGNSSCalcService implements GNSSDataCalcService {
} }
} }
// 如果本次结果有跳变则停止推送并产生严重告警
//更新有效解时间 //更新有效解时间
if(locationRecord.getEnabled()){ if(locationRecord.getEnabled()){
if(device.getLastValidCalcDataTime()==null || device.getLastValidCalcDataTime().isBefore(resultTime)){ if(device.getLastValidCalcDataTime()==null || device.getLastValidCalcDataTime().isBefore(resultTime)){
device.setLastValidCalcDataTime(resultTime); device.setLastValidCalcDataTime(resultTime);
} }
if(latestRpos!=null){
warningService.checkFilteredResultJump(latestRpos, locationRecord);
}
} }
// 记录本次位置作为下次的参考 // 记录本次位置作为下次的参考
@ -380,6 +384,7 @@ public class SingleLineGNSSCalcService implements GNSSDataCalcService {
queryWrapper.eq("deviceid",deviceId); queryWrapper.eq("deviceid",deviceId);
queryWrapper.ge("createtime",LocalDateTime.now().minusHours(12)); queryWrapper.ge("createtime",LocalDateTime.now().minusHours(12));
queryWrapper.isNotNull("rpose"); queryWrapper.isNotNull("rpose");
queryWrapper.eq("enabled",true);
queryWrapper.orderByDesc("createtime"); queryWrapper.orderByDesc("createtime");
queryWrapper.last("limit 1"); queryWrapper.last("limit 1");
GnssCalcData gnssCalcData = dataMapper.selectOne(queryWrapper); GnssCalcData gnssCalcData = dataMapper.selectOne(queryWrapper);
@ -406,4 +411,5 @@ public class SingleLineGNSSCalcService implements GNSSDataCalcService {
deviceChannel.writeAndFlush(buf); deviceChannel.writeAndFlush(buf);
} }
} }
} }

View File

@ -71,6 +71,7 @@ public class D3F2StopIndicationMessageExecutor implements Executor<D3F2StopIndic
gnssTrxMsg.setSatelliteinuse(device.getSatelitesInUse()); gnssTrxMsg.setSatelliteinuse(device.getSatelitesInUse());
gnssTrxMsg.setFixnum(device.getFixedNum()); gnssTrxMsg.setFixnum(device.getFixedNum());
gnssTrxMsg.setFloatnum(device.getFloatNum()); gnssTrxMsg.setFloatnum(device.getFloatNum());
gnssTrxMsg.setJumpcount(device.getJumpCount());
// 储设备收发字节数统计信息 // 储设备收发字节数统计信息
ThreadManager.getFixedThreadPool().submit(() -> { ThreadManager.getFixedThreadPool().submit(() -> {

View File

@ -1,5 +1,6 @@
package com.imdroid.sideslope.service; package com.imdroid.sideslope.service;
import com.imdroid.secapi.dto.GnssCalcData;
import com.imdroid.secapi.dto.GnssStatus; import com.imdroid.secapi.dto.GnssStatus;
import com.imdroid.secapi.dto.GnssStatusMsg; import com.imdroid.secapi.dto.GnssStatusMsg;
import com.imdroid.secapi.dto.GnssTrxMsg; import com.imdroid.secapi.dto.GnssTrxMsg;
@ -22,6 +23,5 @@ public interface WarningService {
/*** /***
* 检查未知报文是否较多 * 检查未知报文是否较多
*/ */
void checkTrx(GnssTrxMsg msg, GnssStatus curStatus); void checkFilteredResultJump(double[] latestRpos, GnssCalcData locationRecord);
} }

View File

@ -28,7 +28,8 @@ public class WarningServiceImpl implements WarningService {
WarningMsgMapper warningMsgMapper; WarningMsgMapper warningMsgMapper;
@Autowired @Autowired
GnssStatusMapper gnssStatusMapper; GnssStatusMapper gnssStatusMapper;
@Autowired
GnssDeviceMapper deviceMapper;
@Value("${warning.log.directory}") @Value("${warning.log.directory}")
private String logDirectory; private String logDirectory;
@ -290,4 +291,39 @@ public class WarningServiceImpl implements WarningService {
warningMsgMapper.updateById(warningMsg); warningMsgMapper.updateById(warningMsg);
} }
} }
@Override
public void checkFilteredResultJump(double[] latestRpos, GnssCalcData locationRecord){
if(Math.abs(locationRecord.getRpose()-latestRpos[0])>2 ||
Math.abs(locationRecord.getRposn()-latestRpos[1])>2 ||
Math.abs(locationRecord.getRposd()-latestRpos[2])>4){
// 停止推送
QueryWrapper<GnssDevice> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("deviceid",locationRecord.getDeviceid());
queryWrapper.last("limit 1");
GnssDevice device = deviceMapper.selectOne(queryWrapper);
String unFwdGroupName = "不推送";
if(device != null){
if(device.getTenantid() != Tenant.SAAS_PROVIDER_ID &&
!unFwdGroupName.equals(device.getFwd_group_id())){
device.setFwd_group_id(unFwdGroupName);
device.setFwd_group_id2(unFwdGroupName);
deviceMapper.updateById(device);
// 产生告警
WarningMsg warningMsg = new WarningMsg();
warningMsg.setDeviceid(device.getDeviceid());
warningMsg.setTenantid(device.getTenantid());
warningMsg.setCreatetime(LocalDateTime.now());
warningMsg.setCode(WarningCfg.TYPE_JUMP);
warningMsg.setLevel(WarningCfg.LEVEL_2);
double deltaE = locationRecord.getRpose()-latestRpos[0];
double deltaN = locationRecord.getRposn()-latestRpos[1];
double deltaU = locationRecord.getRposd()-latestRpos[2];
warningMsg.setInfo("滤波结果跳变:"+deltaE+", "+deltaN+", "+deltaU);
warningMsg.setDevicetype(WarningCfg.TYPE_GNSS);
warningMsgMapper.insert(warningMsg);
}
}
}
}
} }

View File

@ -2,6 +2,7 @@ package com.imdroid.beidou.controller;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.github.yulichang.query.MPJQueryWrapper;
import com.imdroid.beidou.service.CommonExcelService; import com.imdroid.beidou.service.CommonExcelService;
import com.imdroid.secapi.dto.*; import com.imdroid.secapi.dto.*;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@ -15,6 +16,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSession;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -26,7 +28,8 @@ import java.util.List;
*/ */
@Controller @Controller
@RequiredArgsConstructor @RequiredArgsConstructor
public class GnssEhmController extends BasicController implements CommonExcelService<Ehm, Ehm> { public class GnssEhmController extends BasicController implements CommonExcelService<Ehm, EhmJoin> {
final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Autowired @Autowired
EhmMapper ehmMapper; EhmMapper ehmMapper;
@ -47,6 +50,7 @@ public class GnssEhmController extends BasicController implements CommonExcelSer
sortItems.add("周跳次数");sortSqls.add("order by jumpcount desc"); sortItems.add("周跳次数");sortSqls.add("order by jumpcount desc");
} }
m.addAttribute("sort_items", sortItems); m.addAttribute("sort_items", sortItems);
m.addAttribute("begin_time",LocalDateTime.now().minusDays(1).format(dateFormatter));
return "/page/gnss_ehm"; return "/page/gnss_ehm";
} }
@ -54,7 +58,7 @@ public class GnssEhmController extends BasicController implements CommonExcelSer
@ResponseBody @ResponseBody
public JSONObject listTrxMsg(HttpSession session, int page, int limit, String searchParams) { public JSONObject listTrxMsg(HttpSession session, int page, int limit, String searchParams) {
if(searchParams==null){ if(searchParams==null){
searchParams = "{'dgt_createtime':'"+ LocalDateTime.now().minusDays(1)+"','_sorttype':'离线次数'}"; searchParams = "{'dgt_t.createtime':'"+ LocalDateTime.now().minusDays(1)+"','_sorttype':'离线次数'}";
} }
return this.pageList(session, page, limit, searchParams); return this.pageList(session, page, limit, searchParams);
} }
@ -95,8 +99,8 @@ public class GnssEhmController extends BasicController implements CommonExcelSer
* @return 实体类的class * @return 实体类的class
*/ */
@Override @Override
public Class<Ehm> getEntityClass() { public Class<EhmJoin> getEntityClass() {
return Ehm.class; return EhmJoin.class;
} }
/** /**
@ -123,4 +127,23 @@ public class GnssEhmController extends BasicController implements CommonExcelSer
public String getOrder() { public String getOrder() {
return null; return null;
} }
@Override
public MPJQueryWrapper<Ehm> prepareQueryWrapper() {
return new MPJQueryWrapper<Ehm>()
.selectAll(Ehm.class)
.select("d.devicetype as devicetype,d.model as model")
.leftJoin("gnssdevices d on t.deviceid = d.deviceid");
}
/**
* 是否联表查询
*
* @return 是否联表查询
*/
@Override
public boolean isJoinSelect() {
return true;
}
} }

View File

@ -203,9 +203,9 @@ public interface CommonExcelService<T, R> {
if (paraName.startsWith("s") && StringUtils.hasText((String)paraValue)) { if (paraName.startsWith("s") && StringUtils.hasText((String)paraValue)) {
addStringQueryWrapper(queryWrapper, paraName, paraValue); addStringQueryWrapper(queryWrapper, paraName, paraValue);
} }
// Number // Number,-1表示全部
else if (paraName.startsWith("n") && StringUtils.hasText((String)paraValue)) { else if (paraName.startsWith("n") && StringUtils.hasText((String)paraValue)) {
addNumberQueryWrapper(queryWrapper, paraName, paraValue); if(!paraValue.equals("-1")) addNumberQueryWrapper(queryWrapper, paraName, paraValue);
} }
// Date & Time // Date & Time
else if (paraName.startsWith("d") && StringUtils.hasText((String)paraValue)) { else if (paraName.startsWith("d") && StringUtils.hasText((String)paraValue)) {

View File

@ -123,7 +123,7 @@
{field: 'project_id', title: '项目号', width: 120, sort: true}, {field: 'project_id', title: '项目号', width: 120, sort: true},
{field: 'sector', title: '桩号', width: 120, sort: true}, {field: 'sector', title: '桩号', width: 120, sort: true},
{field: 'name', title: '监测点号', width: 80}, {field: 'name', title: '监测点号', width: 80},
{field: 'devicetype', title: '类型', width: 80,templet: '#typeTrans'}, {field: 'devicetype', title: '类型', width: 80,templet: "<div>{{d.model==0?'监测站':'基准站'}}</div>"},
{field: 'group_id', title: '基本参数组', width: 60, sort: true}, {field: 'group_id', title: '基本参数组', width: 60, sort: true},
{field: 'calc_group_id', title: '解算参数组', width: 60, sort: true}, {field: 'calc_group_id', title: '解算参数组', width: 60, sort: true},
{field: 'parentid', title: '基站编号', width: 80, sort: true}, {field: 'parentid', title: '基站编号', width: 80, sort: true},
@ -256,14 +256,6 @@
} }
</script> </script>
<script type="text/html" id="typeTrans">
{{# if(d.devicetype == 1){ }}
<span>基准站</span>
{{# } else { }}
<span>监测站</span>
{{# } }}
</script>
<script type="text/html" id="modeTrans"> <script type="text/html" id="modeTrans">
{{# if(d.opmode == 0){ }} {{# if(d.opmode == 0){ }}
<span class="layui-badge layui-bg-green">正常</span> <span class="layui-badge layui-bg-green">正常</span>

View File

@ -24,6 +24,16 @@
<input type="text" name="sl_deviceid" autocomplete="off" class="layui-input"> <input type="text" name="sl_deviceid" autocomplete="off" class="layui-input">
</div> </div>
</div> </div>
<div class="layui-inline">
<label class="layui-form-label">设备类型</label>
<div class="layui-input-inline">
<select name="n_d.devicetype" id="n_d.devicetype" lay-search="">
<option value="-1">全部</option>
<option value="0">监测站</option>
<option value="1">基准站</option>
</select>
</div>
</div>
<div class="layui-inline" > <div class="layui-inline" >
<label class="layui-form-label">TopN排序</label> <label class="layui-form-label">TopN排序</label>
<div class="layui-input-inline"> <div class="layui-input-inline">
@ -35,10 +45,10 @@
<div class="layui-inline"> <div class="layui-inline">
<label class="layui-form-label">范围</label> <label class="layui-form-label">范围</label>
<div class="layui-input-inline"> <div class="layui-input-inline">
<input type="text" name="dgt_createtime" autocomplete="off" id="ID-laydate-start-date" class="layui-input" placeholder="开始日期"> <input type="text" name="dgt_t.createtime" autocomplete="off" id="ID-laydate-start-date" class="layui-input" placeholder="开始日期" th:value="${begin_time}">
</div> </div>
<div class="layui-input-inline"> <div class="layui-input-inline">
<input type="text" name="dlt_createtime" autocomplete="off" id="ID-laydate-end-date" class="layui-input" placeholder="结束日期"> <input type="text" name="dlt_t.createtime" autocomplete="off" id="ID-laydate-end-date" class="layui-input" placeholder="结束日期">
</div> </div>
</div> </div>
<div class="layui-inline"> <div class="layui-inline">
@ -63,6 +73,8 @@
var cfg_cols = [ var cfg_cols = [
{field: 'deviceid', title: '设备号', width: 100}, {field: 'deviceid', title: '设备号', width: 100},
{field: 'devicetype', title: '类型', width: 80,templet: "<div>{{d.devicetype==0?'监测站':'基准站'}}</div>"},
{field: 'model', title: '型号', width: 80,templet: "<div>{{d.model==0?'G505':'G510'}}</div>"},
{field: 'createtime', title: '创建时间', templet: "<div>{{layui.util.toDateString(d.createtime, 'yyyy-MM-dd HH:mm:ss')}}</div>"}, {field: 'createtime', title: '创建时间', templet: "<div>{{layui.util.toDateString(d.createtime, 'yyyy-MM-dd HH:mm:ss')}}</div>"},
{field: 'offlinestatdays', title: '离线统计周期(天)'}, {field: 'offlinestatdays', title: '离线统计周期(天)'},
{field: 'calcstathours', title: '数据分析周期(小时)'}, {field: 'calcstathours', title: '数据分析周期(小时)'},