Merge 'master' into 'feature/beidou'

This commit is contained in:
fengyarnom 2024-11-28 09:21:40 +08:00
commit 69da1b6c94
14 changed files with 176 additions and 103 deletions

View File

@ -35,4 +35,10 @@ beidou-exapi 9908(外)
3幅度压缩压缩值=上个周期平滑值+(单位周期解算值-上个周期平滑值)*幅度压缩系数,平滑值=滤波窗口内avg(压缩值) 3幅度压缩压缩值=上个周期平滑值+(单位周期解算值-上个周期平滑值)*幅度压缩系数,平滑值=滤波窗口内avg(压缩值)
4初值作为参考点的有效时长缺省为1个周期。从初始值更新时间开始算起 4初值作为参考点的有效时长缺省为1个周期。从初始值更新时间开始算起
小树林算法1b+2b+3高程0.1+4的48小时 小树林算法1b+2b+3高程0.1+4的48小时
2024-11
告警:
1离线设备记录最后一次收到任何数据的时间。定时任务检查设备最后一次时间如果与当前时间差距大于门限则判断为离线D3F0/D3F2清除离线告警
2连续无效解每次解算完如果是无效解则无效解次数加1否则清0如果等于N则产生一次告警。
3连续无固定解每个周期结束如果是有效解解则记录当前时间D3F2检测当前时间和最近一次有效解时间差距如果大于N则产生一次告警。

View File

@ -38,8 +38,8 @@ public class WarningCfg {
public static final String TYPE_NAME_LESS_B562 = "固定解少"; public static final String TYPE_NAME_LESS_B562 = "固定解少";
public static final int TYPE_NO_FIXED_RESULT = 0x100; public static final int TYPE_NO_FIXED_RESULT = 0x100;
public static final String TYPE_NAME_NO_FIXED_RESULT = "连续无固定解"; public static final String TYPE_NAME_NO_FIXED_RESULT = "连续无固定解";
//public static final int TYPE_BS_NO_RESULT = 0x200; public static final int TYPE_CONT_INVALID_RESULT = 0x200;
//public static final String TYPE_NAME_BS_NO_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 = "异常倾斜";
@ -66,7 +66,7 @@ public class WarningCfg {
if((code & TYPE_LESS_D3XX) !=0) warningInfo.add(TYPE_NAME_LESS_D3XX); if((code & TYPE_LESS_D3XX) !=0) warningInfo.add(TYPE_NAME_LESS_D3XX);
if((code & TYPE_LESS_B562) !=0) warningInfo.add(TYPE_NAME_LESS_B562); if((code & TYPE_LESS_B562) !=0) warningInfo.add(TYPE_NAME_LESS_B562);
if((code & TYPE_NO_FIXED_RESULT) !=0) warningInfo.add(TYPE_NAME_NO_FIXED_RESULT); if((code & TYPE_NO_FIXED_RESULT) !=0) warningInfo.add(TYPE_NAME_NO_FIXED_RESULT);
//if((code & TYPE_BS_NO_RESULT) !=0) warningInfo.add(TYPE_NAME_BS_NO_RESULT); if((code & TYPE_CONT_INVALID_RESULT) !=0) warningInfo.add(TYPE_NAME_CONT_INVALID_RESULT);
if((code & TYPE_INCLINE) !=0) warningInfo.add(TYPE_NAME_INCLINE); if((code & TYPE_INCLINE) !=0) warningInfo.add(TYPE_NAME_INCLINE);
return warningInfo; return warningInfo;
} }

View File

@ -203,8 +203,6 @@ public class SingleLineGNSSCalcService implements GNSSDataCalcService {
future = ThreadManager.getScheduledThreadPool().schedule(() -> { future = ThreadManager.getScheduledThreadPool().schedule(() -> {
try { try {
calCycleResult(device, groupCalc,date); calCycleResult(device, groupCalc,date);
// 清除统计
device.clearStat();
} catch (Exception e) { } catch (Exception e) {
logger.error(e.toString()); logger.error(e.toString());
} }
@ -283,6 +281,13 @@ public class SingleLineGNSSCalcService implements GNSSDataCalcService {
} }
} }
//更新有效解时间
if(locationRecord.getEnabled()){
if(device.getLastValidCalcDataTime()==null || device.getLastValidCalcDataTime().isBefore(resultTime)){
device.setLastValidCalcDataTime(resultTime);
}
}
// 记录本次位置作为下次的参考 // 记录本次位置作为下次的参考
if(focusCalculator.getVer()==6) { if(focusCalculator.getVer()==6) {
if(locationRecord.getRpose()!=null) { if(locationRecord.getRpose()!=null) {

View File

@ -40,18 +40,11 @@ public class D331RtcmMessageExecutor implements Executor<D331RtcmMessage, Void>
public Void execute(D331RtcmMessage message) { public Void execute(D331RtcmMessage message) {
String id = message.getId(); String id = message.getId();
// 补齐tenantId // 补齐tenantId
Device device1 = deviceService.findByDeviceId(id); Device deviceBs = deviceService.findByDeviceId(id);
if(device1 == null || device1.getOpMode() == GnssDevice.OP_MODE_UNUSE) return null; if(deviceBs == null || deviceBs.getOpMode() == GnssDevice.OP_MODE_UNUSE) return null;
// 原始码流输出到日志文件 -- INFO 级别
// 只有测站开了日志记录或者消息来自基站才将原码记录到日志文件
if(device1.getLoggingmode() == GnssDevice.LOGGING_MODE_FULL || device1.getDeviceType() == GnssDevice.TYPE_REFERENCE_STATION){
logger.info("receive {} d331 message: {}", message.getId(), DataTypeUtil.getHexString(message.getSrcData()));
logger.info("receive d331 rtcm message of device: {}, seq:{}, len:{}", message.getId(), message.getSeq(), message.getLen());
}
// 推送基站数据 // 推送基站数据
if(device1.getOpMode() == GnssDevice.OP_MODE_USE) { if(deviceBs.getOpMode() == GnssDevice.OP_MODE_USE) {
byte[] forwardBytes = message.getSrcData(); byte[] forwardBytes = message.getSrcData();
// 要求快速转发因此用缓存不要每次都查数据库 // 要求快速转发因此用缓存不要每次都查数据库
List<Device> deviceList = deviceService.findByParentId(id); List<Device> deviceList = deviceService.findByParentId(id);
@ -74,26 +67,31 @@ public class D331RtcmMessageExecutor implements Executor<D331RtcmMessage, Void>
} }
// 如果30分钟内收到不到d3f0和d3f2则根据UDP最后一个报文触发状态更新和统计 // 如果30分钟内收到不到d3f0和d3f2则根据UDP最后一个报文触发状态更新和统计
LocalDateTime now = LocalDateTime.now(); if(deviceBs.getD3xxbytes()>0){
if(device1.getLastRxTime()!=null && LocalDateTime now = LocalDateTime.now();
device1.getLastRxTime().isBefore(now.minusMinutes(1))){ if(deviceBs.getLastRxTime().isBefore(now.minusMinutes(1)) &&
if(device1.getLastD3f0f2Time() == null || (deviceBs.getLastD3f2Time() == null ||
device1.getLastD3f0f2Time().isBefore(now.minusMinutes(30))) { deviceBs.getLastD3f2Time().isBefore(now.minusMinutes(30)))) {
// new cycle // new cycle
logger.info("device {} rx {} d331 in a cycle while not d3f0f2",device1.getDeviceId(),device1.getD3xxCount()); logger.info("device {} rx {} d331 in a cycle while not d3f0f2",deviceBs.getDeviceId(),deviceBs.getD3xxCount());
Device lastCycleDevice = new Device(); Device lastCycleDevice = new Device();
lastCycleDevice.setDeviceId(device1.getDeviceId()); lastCycleDevice.setDeviceId(deviceBs.getDeviceId());
lastCycleDevice.setTenantId(device1.getTenantId()); lastCycleDevice.setDeviceType(deviceBs.getDeviceType());
lastCycleDevice.setD3xxbytes(device1.getD3xxbytes()); lastCycleDevice.setTenantId(deviceBs.getTenantId());
lastCycleDevice.setD3xxCount(device1.getD3xxCount()); lastCycleDevice.setD341bytes(deviceBs.getD341bytes());
lastCycleDevice.setLastRxTime(device1.getLastRxTime()); lastCycleDevice.setD341Count(deviceBs.getD341Count());
lastCycleDevice.setSatelitesInUse(device1.getSatelitesInUse()); lastCycleDevice.setFixedNum(deviceBs.getFixedNum());
device1.clearStat(); lastCycleDevice.setFloatNum(deviceBs.getFloatNum());
lastCycleDevice.setNoFixedAndFloatResult(deviceBs.getNoFixedAndFloatResult());
lastCycleDevice.setLastRxTime(deviceBs.getLastRxTime());
lastCycleDevice.setLastValidCalcDataTime(deviceBs.getLastValidCalcDataTime());
lastCycleDevice.setSatelitesInUse(deviceBs.getSatelitesInUse());
deviceBs.clearStat();
ThreadManager.getFixedThreadPool().submit(() -> { ThreadManager.getFixedThreadPool().submit(() -> {
// 通知上线 // 通知上线
try { try {
beidouClient.onDeviceActive(device1.getDeviceId(), device1.getTenantId()); beidouClient.onDeviceActive(deviceBs.getDeviceId(), deviceBs.getTenantId());
} catch (Exception e) { } catch (Exception e) {
logger.error(e.toString()); logger.error(e.toString());
} }
@ -103,18 +101,26 @@ public class D331RtcmMessageExecutor implements Executor<D331RtcmMessage, Void>
} }
// update trx // update trx
device1.updateRx(message.getHeader(),message.getLen(),message.getPacketNum()); deviceBs.updateRx(message.getHeader(),message.getLen(),message.getPacketNum());
// update gga // update gga
Gga gga = message.getGga(); Gga gga = message.getGga();
if(gga != null) { if(gga != null) {
device1.updateSatelitesNum(gga.getSatellitesInUsed()); deviceBs.updateSatelitesNum(gga.getSatellitesInUsed());
//if(gga.isFixed()) { //基站的quality不会是4 //if(gga.isFixed()) { //基站的quality不会是4
device1.setLatitude(gga.getLatitude()); deviceBs.setLatitude(gga.getLatitude());
device1.setLongitude(gga.getLongitude()); deviceBs.setLongitude(gga.getLongitude());
device1.setAltitude(gga.getAltitude()); deviceBs.setAltitude(gga.getAltitude());
//} //}
} }
ThreadManager.getFixedThreadPool().submit(() -> {
// 原始码流输出到日志文件 -- INFO 级别
// 只有测站开了日志记录或者消息来自基站才将原码记录到日志文件
if(deviceBs.getLoggingmode() == GnssDevice.LOGGING_MODE_FULL){
logger.info("receive {} d331 message: {}", message.getId(), DataTypeUtil.getHexString(message.getSrcData()));
}
});
return null; return null;
} }

View File

@ -37,32 +37,28 @@ public class D341LocationMessageExecutor implements Executor<D341LocationMessage
private DataPersistService dataPersistService; private DataPersistService dataPersistService;
@Override @Override
public Void execute(D341LocationMessage message) { public Void execute(D341LocationMessage message) {
// 补齐tenantId要求快速处理因此用缓存不要每次都查数据库 // 更新device对象统计
Device device = deviceService.findByDeviceId(message.getId()); Device device = deviceService.findByDeviceId(message.getId());
if(device == null) return null; if(device == null) return null;
message.setTenantId(device.getTenantId());
// 原始码流输出到日志文件 -- INFO 级别 // 如果没有收到d3f2,这里判断是否是一个新的周期上一次收到D341的时间大于两分钟且上次收到d3f2的时间大于30分钟
if(device.getLoggingmode() == GnssDevice.LOGGING_MODE_FULL){ if(device.getD341Count()>0) {
logger.info("receive "+message.getId()+" d341 message: "+ DataTypeUtil.getHexString(message.getSrcData())); LocalDateTime now = LocalDateTime.now();
logger.info("receive d341 message of device: "+message.getId()+", seq:"+message.getSeq()+", len:"+message.getLen()); if (device.getLastRxTime().isBefore(now.minusMinutes(1)) &&
} (device.getLastD3f2Time() == null ||
device.getLastD3f2Time().isBefore(now.minusMinutes(30)))) {
// trx cycle stat
LocalDateTime now = LocalDateTime.now();
if(device.getLastRxTime()!=null &&
device.getLastRxTime().isBefore(now.minusMinutes(2))){
if(device.getLastD3f0f2Time() == null ||
device.getLastD3f0f2Time().isBefore(now.minusMinutes(30))) {
// new cycle // new cycle
Device lastCycleDevice = new Device(); Device lastCycleDevice = new Device();
lastCycleDevice.setDeviceId(device.getDeviceId()); lastCycleDevice.setDeviceId(device.getDeviceId());
lastCycleDevice.setDeviceType(device.getDeviceType());
lastCycleDevice.setTenantId(device.getTenantId()); lastCycleDevice.setTenantId(device.getTenantId());
lastCycleDevice.setD341bytes(device.getD341bytes()); lastCycleDevice.setD341bytes(device.getD341bytes());
lastCycleDevice.setD341Count(device.getD341Count()); lastCycleDevice.setD341Count(device.getD341Count());
lastCycleDevice.setFixedNum(device.getFixedNum()); lastCycleDevice.setFixedNum(device.getFixedNum());
lastCycleDevice.setFloatNum(device.getFloatNum()); lastCycleDevice.setFloatNum(device.getFloatNum());
lastCycleDevice.setNoFixedAndFloatResult(device.getNoFixedAndFloatResult());
lastCycleDevice.setLastRxTime(device.getLastRxTime()); lastCycleDevice.setLastRxTime(device.getLastRxTime());
lastCycleDevice.setLastValidCalcDataTime(device.getLastValidCalcDataTime());
lastCycleDevice.setSatelitesInUse(device.getSatelitesInUse()); lastCycleDevice.setSatelitesInUse(device.getSatelitesInUse());
device.clearStat(); device.clearStat();
ThreadManager.getFixedThreadPool().submit(() -> { ThreadManager.getFixedThreadPool().submit(() -> {
@ -78,6 +74,7 @@ public class D341LocationMessageExecutor implements Executor<D341LocationMessage
} }
// update trx // update trx
message.setTenantId(device.getTenantId());
device.updateRx(message.getHeader(), message.getLen(), 1); device.updateRx(message.getHeader(), message.getLen(), 1);
if(device.isB562AsCalc()) { if(device.isB562AsCalc()) {
double[] pos = message.getB562_loc(); double[] pos = message.getB562_loc();
@ -91,13 +88,6 @@ public class D341LocationMessageExecutor implements Executor<D341LocationMessage
device.setLatitude(gga.getLatitude()); device.setLatitude(gga.getLatitude());
device.setLongitude(gga.getLongitude()); device.setLongitude(gga.getLongitude());
device.setAltitude(gga.getAltitude()); device.setAltitude(gga.getAltitude());
}else{
// 若不是固定解则打印原始码流到日志里
if(device.getLoggingmode() == GnssDevice.LOGGING_MODE_SIMPLE){
logger.info("receive {} d341 message: {}", message.getId(), DataTypeUtil.getHexString(message.getSrcData()));
logger.info("receive d341 message of device: {}, seq:{}, len:{}", message.getId(), message.getSeq(), message.getLen());
}
} }
if(!device.isB562AsCalc()){ if(!device.isB562AsCalc()){
device.updateCalcQuality(gga.getQuality()); device.updateCalcQuality(gga.getQuality());
@ -106,6 +96,17 @@ public class D341LocationMessageExecutor implements Executor<D341LocationMessage
ThreadManager.getFixedThreadPool().submit(() -> { ThreadManager.getFixedThreadPool().submit(() -> {
gnssCalcService.calcSingle(message,true); gnssCalcService.calcSingle(message,true);
// 原始码流输出到日志文件 -- INFO 级别
if(device.getLoggingmode() == GnssDevice.LOGGING_MODE_FULL){
logger.info("receive {} d341 message: {}", message.getId(), DataTypeUtil.getHexString(message.getSrcData()));
}
else {
Gga gga1 = message.getGga();
if (gga1 != null && !gga1.isFixed()) {
// 若不是固定解则打印原始码流到日志里
logger.info("receive {} d341 message: {}", message.getId(), DataTypeUtil.getHexString(message.getSrcData()));
}
}
}); });
return null; return null;

View File

@ -25,6 +25,10 @@ import java.time.LocalDateTime;
/** /**
* @author Layton * @author Layton
* @date 2023/2/2 20:40 * @date 2023/2/2 20:40
* 1回ACK以便终端判断是否连接上服务器后台
* 2同步参数
* 3判断是否发冷启动指令
* 4保存状态信息判断是否有低电压等告警清除离线告警
*/ */
@Component @Component
public class D3F0SelfCheckMessageExecutor implements Executor<D3F0SelfCheckMessage, Void> { public class D3F0SelfCheckMessageExecutor implements Executor<D3F0SelfCheckMessage, Void> {
@ -49,30 +53,31 @@ public class D3F0SelfCheckMessageExecutor implements Executor<D3F0SelfCheckMessa
Device device = deviceService.findByDeviceId(message.getId()); Device device = deviceService.findByDeviceId(message.getId());
if(device == null) return null; if(device == null) return null;
// 补齐tenantId
message.setTenantId(device.getTenantId());
//应答 //应答
sendD3F1Ack(device); sendD3F1Ack(device);
//更新统计
// 检查是否需要对设备的F9P进行冷启动操作
checkAndSendF9PColdStartCommand(device);
// 补齐tenantId
message.setTenantId(device.getTenantId());
device.updateRx(message.getHeader(),message.getLen(),1); device.updateRx(message.getHeader(),message.getLen(),1);
ThreadManager.getFixedThreadPool().submit(() -> { ThreadManager.getFixedThreadPool().submit(() -> {
// 检查是否需要对设备的F9P进行冷启动操作
checkAndSendF9PColdStartCommand(device);
// 通知beidou服务设备上线这里会触发参数同步
GnssStatus lastGnssStatus = dataPersistService.getDeviceState(message.getId()); GnssStatus lastGnssStatus = dataPersistService.getDeviceState(message.getId());
try { try {
if (lastGnssStatus != null && lastGnssStatus.getState() == GnssStatus.STATE_OFFLINE) { if (lastGnssStatus != null && lastGnssStatus.getState() == GnssStatus.STATE_OFFLINE) {
beidouClient.onLine(lastGnssStatus.getDeviceid(), beidouClient.onLine(lastGnssStatus.getDeviceid(),
lastGnssStatus.getTenantid(), lastGnssStatus.getUpdatetime()); lastGnssStatus.getTenantid(), lastGnssStatus.getUpdatetime());
} else { } else {
// 通知beidou服务设备上线
beidouClient.onDeviceActive(message.getId(), device.getTenantId()); beidouClient.onDeviceActive(message.getId(), device.getTenantId());
} }
} }
catch (Exception e){ catch (Exception e){
} }
//保存状态信息判断是否有低电压等告警清除离线告警
dataPersistService.saveDeviceState(message); dataPersistService.saveDeviceState(message);
}); });
@ -84,7 +89,7 @@ public class D3F0SelfCheckMessageExecutor implements Executor<D3F0SelfCheckMessa
return D3F0SelfCheckMessage.class; return D3F0SelfCheckMessage.class;
} }
private void checkAndSendF9PPowerOffCommand(Device device){ /*private void checkAndSendF9PPowerOffCommand(Device device){
if(device.getDeviceId().startsWith("2419") && device.getDeviceType() == Device.DEVICE_ROVER){ if(device.getDeviceId().startsWith("2419") && device.getDeviceType() == Device.DEVICE_ROVER){
// 连续6个周期无解则立即发送F9P断电指令 // 连续6个周期无解则立即发送F9P断电指令
if(device.getNoFixedAndFloatResult() >= 6){ if(device.getNoFixedAndFloatResult() >= 6){
@ -93,14 +98,15 @@ public class D3F0SelfCheckMessageExecutor implements Executor<D3F0SelfCheckMessa
device.clearNoResultStat(); device.clearNoResultStat();
} }
} }
} }*/
private void checkAndSendF9PColdStartCommand(Device device){ private void checkAndSendF9PColdStartCommand(Device device){
if(device.getModel() == GnssDevice.MODEL_G505){ if(device.getModel() == GnssDevice.MODEL_G505 &&
device.getDeviceType() == Device.DEVICE_ROVER){
// 连续6个周期无解则发送 F9P 冷启动指令 // 连续6个周期无解则发送 F9P 冷启动指令
if(device.getNoFixedAndFloatResult() >= 6){ if(device.getNoFixedAndFloatResult() >= 6){
sendF9PColdStartCommand(device); //sendF9PColdStartCommand(device);
logger.debug("{}: 连续{}次无固定解和浮点解,发送 F9P 冷启动指令",device.getDeviceId(), device.getNoFixedAndFloatResult()); logger.info("{}: 连续{}次无固定解和浮点解,发送 F9P 冷启动指令",device.getDeviceId(), device.getNoFixedAndFloatResult());
device.clearNoResultStat(); device.clearNoResultStat();
} }
} }
@ -122,7 +128,7 @@ public class D3F0SelfCheckMessageExecutor implements Executor<D3F0SelfCheckMessa
gnssMsg.setContent(content.substring(0,128)); gnssMsg.setContent(content.substring(0,128));
msgMapper.insert(gnssMsg); msgMapper.insert(gnssMsg);
} }
/*
void sendF9PPowerOffCommand(Device device){ void sendF9PPowerOffCommand(Device device){
int flag = 0xD313; int flag = 0xD313;
String sendCmd = "2500"; String sendCmd = "2500";
@ -135,7 +141,7 @@ public class D3F0SelfCheckMessageExecutor implements Executor<D3F0SelfCheckMessa
rtcmClient.config(device.getDeviceId(), sendCmd); rtcmClient.config(device.getDeviceId(), sendCmd);
saveMsg(device.getDeviceId(), device.getTenantId(),0xD313, sendCmd, true); saveMsg(device.getDeviceId(), device.getTenantId(),0xD313, sendCmd, true);
} }
*/
void sendF9PColdStartCommand(Device device){ void sendF9PColdStartCommand(Device device){
int msgType = 0xD310; int msgType = 0xD310;
// F9P 冷启动 b5 62 06 04 04 00 00 00 02 00 10 68 // F9P 冷启动 b5 62 06 04 04 00 00 00 02 00 10 68

View File

@ -11,7 +11,6 @@ import com.imdroid.sideslope.sal.Device;
import com.imdroid.sideslope.sal.DeviceService; import com.imdroid.sideslope.sal.DeviceService;
import com.imdroid.sideslope.service.DataPersistService; import com.imdroid.sideslope.service.DataPersistService;
import com.imdroid.sideslope.service.GnssSingleBufferServiceImpl; import com.imdroid.sideslope.service.GnssSingleBufferServiceImpl;
import com.imdroid.sideslope.service.WarningService;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -24,6 +23,9 @@ import java.time.LocalDateTime;
* 停止指示消息处理器 * 停止指示消息处理器
* *
* @author LiGang * @author LiGang
* 1更新统计
* 2启动单周期固定解处理
* 3保存统计信息判断是否有连续无固定解连续无有效解等告警清除离线告警
*/ */
@Component @Component
public class D3F2StopIndicationMessageExecutor implements Executor<D3F2StopIndicationMessage, Void> { public class D3F2StopIndicationMessageExecutor implements Executor<D3F2StopIndicationMessage, Void> {
@ -40,23 +42,21 @@ public class D3F2StopIndicationMessageExecutor implements Executor<D3F2StopIndic
private GNSSDataCalcService gnssCalcService; private GNSSDataCalcService gnssCalcService;
@Autowired @Autowired
MultiLineGNSSCalcService multiLineGNSSCalcService; MultiLineGNSSCalcService multiLineGNSSCalcService;
@Autowired
WarningService warningService;
@Autowired @Autowired
GnssSingleBufferServiceImpl gnssSingleBufferService; GnssSingleBufferServiceImpl gnssSingleBufferService;
@Override @Override
public Void execute(D3F2StopIndicationMessage message) { public Void execute(D3F2StopIndicationMessage message) {
logger.info("receive d3f2 message of {} device: {}", message.getId(), DataTypeUtil.getHexString(message.getSrcData())); logger.info("receive d3f2 message of {} device: {}", message.getId(), DataTypeUtil.getHexString(message.getSrcData()));
// 补齐tenantId // 补齐tenantId
String deviceId = message.getId(); String deviceId = message.getId();
Device device = deviceService.findByDeviceId(deviceId); Device device = deviceService.findByDeviceId(deviceId);
if(device == null) return null; if(device == null) return null;
device.updateRx(message.getHeader(), message.getLen(),1);
message.setTenantId(device.getTenantId()); message.setTenantId(device.getTenantId());
//更新统计
device.updateRx(message.getHeader(), message.getLen(),1);
GnssTrxMsg gnssTrxMsg = message.getTrxMsg(); GnssTrxMsg gnssTrxMsg = message.getTrxMsg();
gnssTrxMsg.setTenantid(device.getTenantId()); gnssTrxMsg.setTenantid(device.getTenantId());
gnssTrxMsg.setD3xxbytes(device.getD3xxbytes()); gnssTrxMsg.setD3xxbytes(device.getD3xxbytes());
@ -67,8 +67,12 @@ public class D3F2StopIndicationMessageExecutor implements Executor<D3F2StopIndic
// 储设备收发字节数统计信息 // 储设备收发字节数统计信息
ThreadManager.getFixedThreadPool().submit(() -> { ThreadManager.getFixedThreadPool().submit(() -> {
// 开始周期解算
LocalDateTime uploadTime = multiLineGNSSCalcService.checkUploadTime( LocalDateTime uploadTime = multiLineGNSSCalcService.checkUploadTime(
device.getDeviceId(), device.getTenantId()); device.getDeviceId(), device.getTenantId());
gnssCalcService.calSingleDone(device, null, message.getCreateTime());
// 保存统计判断是否有连续无固定解连续无有效解等告警清除离线告警
dataPersistService.saveDeviceTrxStat(message, (uploadTime!=null), device); dataPersistService.saveDeviceTrxStat(message, (uploadTime!=null), device);
// 保存缓存中的 GNSS 单次解析结果 // 保存缓存中的 GNSS 单次解析结果
@ -87,15 +91,8 @@ public class D3F2StopIndicationMessageExecutor implements Executor<D3F2StopIndic
catch (Exception e){ catch (Exception e){
} }
// 检查告警 // 清除统计
if(device.getDeviceType() == Device.DEVICE_BASE_STATION) { device.clearStat();
warningService.checkD3xxNum(device);
}
else{
warningService.checkB562Num(device);
}
// 开始周期解算
gnssCalcService.calSingleDone(device, null, message.getCreateTime());
}); });
return null; return null;

View File

@ -63,7 +63,7 @@ public class Device {
Double iPosd; Double iPosd;
LocalDateTime lastRxTime; LocalDateTime lastRxTime;
LocalDateTime lastD3f0f2Time; LocalDateTime lastD3f2Time;
short noFixedAndFloatResult=0; short noFixedAndFloatResult=0;
// 日志记录控制 // 日志记录控制
@ -73,25 +73,28 @@ public class Device {
int fixedNum = 0; int fixedNum = 0;
int floatNum = 0; int floatNum = 0;
LocalDateTime lastValidCalcDataTime; //最近一次有效解
public void updateRx(int head, int bytes,int count){ public void updateRx(int head, int bytes,int count){
lastRxHead = head; lastRxHead = head;
lastRxTime = LocalDateTime.now();
switch (head){ switch (head){
case 0xd3f0: case 0xd3f0:
lastD3f0f2Time = LocalDateTime.now(); //lastD3f0f2Time = LocalDateTime.now();
clearStat(); //clearStat();
break; break;
case 0xd3f2: case 0xd3f2:
lastD3f0f2Time = LocalDateTime.now(); lastD3f2Time = LocalDateTime.now();
break; break;
case 0xd331: case 0xd331:
d3xxCount+=count; d3xxCount+=count;
d3xxbytes += bytes; d3xxbytes += bytes;
lastRxTime = LocalDateTime.now();
break; break;
case 0xd341: case 0xd341:
d341Count+=count; d341Count+=count;
d341bytes += bytes; d341bytes += bytes;
lastRxTime = LocalDateTime.now();
break; break;
case 0xd342: case 0xd342:
d342Count ++; d342Count ++;
@ -120,7 +123,7 @@ public class Device {
} }
public void clearStat(){ public void clearStat(){
if(fixedNum+floatNum == 0) noFixedAndFloatResult++; if(fixedNum+floatNum == 0 && d3xxCount>0) noFixedAndFloatResult++;
else noFixedAndFloatResult = 0; else noFixedAndFloatResult = 0;
d3xxCount = 0; d3xxCount = 0;

View File

@ -130,6 +130,16 @@ public class DataPersistServiceImpl implements DataPersistService {
deviceState.setAltitude(device.getAltitude()); deviceState.setAltitude(device.getAltitude());
deviceState.setState(isUploading?GnssStatus.STATE_UPLOADING:GnssStatus.STATE_IDLE); deviceState.setState(isUploading?GnssStatus.STATE_UPLOADING:GnssStatus.STATE_IDLE);
deviceStateRepository.updateById(deviceState); deviceStateRepository.updateById(deviceState);
warningService.checkDeviceStatus(null, deviceState);
// 检查GNSS质量
if(device.getDeviceType() == Device.DEVICE_BASE_STATION){
warningService.checkD3xxNum(device);
}
else{
warningService.checkB562Num(device);
}
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();

View File

@ -2,6 +2,7 @@ package com.imdroid.sideslope.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.imdroid.common.util.NumberUtils; import com.imdroid.common.util.NumberUtils;
import com.imdroid.common.util.WarningLogExecutor;
import com.imdroid.secapi.dto.*; import com.imdroid.secapi.dto.*;
import com.imdroid.sideslope.sal.Device; import com.imdroid.sideslope.sal.Device;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -9,6 +10,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import java.time.Duration;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -23,6 +25,8 @@ public class WarningServiceImpl implements WarningService {
@Autowired @Autowired
GnssStatusMapper gnssStatusMapper; GnssStatusMapper gnssStatusMapper;
@Value("${warning.log.directory}")
private String logDirectory;
// warning type <-> level & value // warning type <-> level & value
Map<Integer, int[]> cfgMap = new ConcurrentHashMap<>(); Map<Integer, int[]> cfgMap = new ConcurrentHashMap<>();
@ -64,13 +68,41 @@ public class WarningServiceImpl implements WarningService {
isUpdated=true; isUpdated=true;
} }
//清除连续无b562 //连续无固定解
if(0 != device.getFixedNum()){ if ((status.getWarningcode() & WarningCfg.TYPE_NO_FIXED_RESULT) != 0) {
if ((status.getWarningcode() & WarningCfg.TYPE_NO_FIXED_RESULT) != 0) { if(0 != device.getFixedNum()) {
status.setWarningcode(status.getWarningcode() & ~WarningCfg.TYPE_NO_FIXED_RESULT); status.setWarningcode(status.getWarningcode() & ~WarningCfg.TYPE_NO_FIXED_RESULT);
isUpdated = true; isUpdated = true;
} }
} }
else{
if(check(status, WarningCfg.TYPE_NO_FIXED_RESULT,
WarningCfg.TYPE_NAME_NO_FIXED_RESULT,false,
(int) device.getNoFixedAndFloatResult(),null,
"连续无固定解:"+device.getNoFixedAndFloatResult())){
isUpdated=true;
}
}
//连续无有效解
if ((status.getWarningcode() & WarningCfg.TYPE_CONT_INVALID_RESULT) != 0) {
int[] warningValues = cfgMap.get(WarningCfg.TYPE_CONT_INVALID_RESULT);
if(warningValues!=null && device.getLastValidCalcDataTime()!=null){
if(LocalDateTime.now().isBefore(device.getLastValidCalcDataTime().plusHours(warningValues[1]))){
status.setWarningcode(status.getWarningcode() & ~WarningCfg.TYPE_CONT_INVALID_RESULT);
isUpdated = true;
}
}
}
else{
if(device.getLastValidCalcDataTime()!=null &&
check(status, WarningCfg.TYPE_CONT_INVALID_RESULT,
WarningCfg.TYPE_NAME_CONT_INVALID_RESULT,false,
(int) Duration.between(device.getLastValidCalcDataTime(), LocalDateTime.now()).toHours(),null,
"长时间无有效解:"+device.getLastValidCalcDataTime())){
isUpdated=true;
}
}
if(isUpdated){ if(isUpdated){
// 根据告警码确定告警级别 // 根据告警码确定告警级别
@ -176,6 +208,9 @@ public class WarningServiceImpl implements WarningService {
warningMsgMapper.insert(warningMsg); warningMsgMapper.insert(warningMsg);
//告警级别 //告警级别
curStatus.setWarningcode(curStatus.getWarningcode() | warningType); curStatus.setWarningcode(curStatus.getWarningcode() | warningType);
// 新告警出现后生成对应设备的 warning 日志文件
//generate_warning_logs(curStatus.getDeviceid(),warningType,auxInfo);
} }
isUpdated = true; isUpdated = true;
} }
@ -222,4 +257,11 @@ public class WarningServiceImpl implements WarningService {
} }
} }
public void generate_warning_logs(String device_id,int warning_type,String warning_type_name){
if (warning_type == WarningCfg.TYPE_LOW_VOLTAGE) {
WarningLogExecutor warningLogExecutor = new WarningLogExecutor(logDirectory);
warningLogExecutor.generateWarningLogs(device_id, warning_type_name);
}
}
} }

View File

@ -61,7 +61,7 @@ public class IndexController extends BasicController{
if(status.getState() == GnssStatus.STATE_OFFLINE) { if(status.getState() == GnssStatus.STATE_OFFLINE) {
deviceOfflineNum++; deviceOfflineNum++;
} }
else if((status.getWarningcode()&WarningCfg.TYPE_NO_FIXED_RESULT) != 0) { else if((status.getWarningcode()&WarningCfg.TYPE_CONT_INVALID_RESULT) != 0) {
noFix++; noFix++;
} }
@ -127,8 +127,7 @@ public class IndexController extends BasicController{
queryWrapper.eq("state",GnssStatus.STATE_OFFLINE); queryWrapper.eq("state",GnssStatus.STATE_OFFLINE);
} }
else if(query.equals("nofixed")){ else if(query.equals("nofixed")){
queryWrapper.ge("warningcode",256); queryWrapper.eq("warningcode&"+WarningCfg.TYPE_CONT_INVALID_RESULT,WarningCfg.TYPE_CONT_INVALID_RESULT);
queryWrapper.le("warningcode",512);
} }
else if(query.equals("warning1")){ else if(query.equals("warning1")){
queryWrapper.eq("warning",WarningCfg.LEVEL_1); queryWrapper.eq("warning",WarningCfg.LEVEL_1);

View File

@ -38,7 +38,7 @@ public class WarningController extends BasicController implements CommonExcelSer
@PostConstruct @PostConstruct
public static void init() { public static void init() {
warningMap.put(WarningCfg.TYPE_DEVICE_OFF_LINE, WarningCfg.TYPE_NAME_DEVICE_OFF_LINE); warningMap.put(WarningCfg.TYPE_DEVICE_OFF_LINE, WarningCfg.TYPE_NAME_DEVICE_OFF_LINE);
//warningMap.put(WarningCfg.TYPE_BS_NO_RESULT, WarningCfg.TYPE_NAME_BS_NO_RESULT); warningMap.put(WarningCfg.TYPE_CONT_INVALID_RESULT, WarningCfg.TYPE_NAME_CONT_INVALID_RESULT);
warningMap.put(WarningCfg.TYPE_NO_FIXED_RESULT, WarningCfg.TYPE_NAME_NO_FIXED_RESULT); warningMap.put(WarningCfg.TYPE_NO_FIXED_RESULT, WarningCfg.TYPE_NAME_NO_FIXED_RESULT);
warningMap.put(WarningCfg.TYPE_LESS_INUSE_SAT, WarningCfg.TYPE_NAME_LESS_INUSE_SAT); warningMap.put(WarningCfg.TYPE_LESS_INUSE_SAT, WarningCfg.TYPE_NAME_LESS_INUSE_SAT);
warningMap.put(WarningCfg.TYPE_LESS_D3XX, WarningCfg.TYPE_NAME_LESS_D3XX); warningMap.put(WarningCfg.TYPE_LESS_D3XX, WarningCfg.TYPE_NAME_LESS_D3XX);

View File

@ -1,7 +1,5 @@
package com.imdroid.beidou.task; package com.imdroid.beidou.task;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.yulichang.query.MPJQueryWrapper;
import com.imdroid.beidou.service.NotificationService; import com.imdroid.beidou.service.NotificationService;
import com.imdroid.secapi.dto.*; import com.imdroid.secapi.dto.*;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -99,8 +97,8 @@ public class DeviceStatusChecker {
now.format(formatter), WarningCfg.LEVEL_2); now.format(formatter), WarningCfg.LEVEL_2);
} }
} }
/*
@Scheduled(cron = "0 28 * * * ?") // 每小时执行一次 @Scheduled(cron = "0 27 * * * ?") // 每小时执行一次
void checkRoverStationCalcData() throws ExecutionException, InterruptedException { void checkRoverStationCalcData() throws ExecutionException, InterruptedException {
// 获取无固定解告警配置 // 获取无固定解告警配置
QueryWrapper<WarningCfg> warningCfgQueryWrapper = new QueryWrapper<>(); QueryWrapper<WarningCfg> warningCfgQueryWrapper = new QueryWrapper<>();
@ -109,7 +107,7 @@ public class DeviceStatusChecker {
WarningCfg warningCfg = warningCfgMapper.selectOne(warningCfgQueryWrapper); WarningCfg warningCfg = warningCfgMapper.selectOne(warningCfgQueryWrapper);
if(warningCfg == null) return; if(warningCfg == null) return;
// 获取所有n个小时内无固定解的测站 // 获取所有warningCfg.getValue()个小时内无固定解的测站
LocalDateTime now = LocalDateTime.now(); LocalDateTime now = LocalDateTime.now();
LocalDateTime beginTime = now.minusHours(warningCfg.getValue()); LocalDateTime beginTime = now.minusHours(warningCfg.getValue());
QueryWrapper<GnssCalcData> calcDataQueryWrapper = new QueryWrapper<>(); QueryWrapper<GnssCalcData> calcDataQueryWrapper = new QueryWrapper<>();
@ -169,5 +167,5 @@ public class DeviceStatusChecker {
WarningCfg.LEVEL_2); WarningCfg.LEVEL_2);
} }
} }
*/
} }

View File

@ -78,7 +78,7 @@
</div> </div>
<div class="layui-col-xs3 layui-col-md4"> <div class="layui-col-xs3 layui-col-md4">
<a href="#" onclick="queryDevices('offline')" style="color: #bd3004" th:text="'掉线数 '+${deviceOfflineNum}">0</a><br> <a href="#" onclick="queryDevices('offline')" style="color: #bd3004" th:text="'掉线数 '+${deviceOfflineNum}">0</a><br>
<div th:if="${noFix>0}"><a href="#" onclick="queryDevices('nofixed')" style="color: #bd3004" th:text="'长期无解 '+${noFix}">0</a><br></div> <div th:if="${noFix>0}"><a href="#" onclick="queryDevices('nofixed')" style="color: #bd3004" th:text="'长期无解 '+${noFix}">0</a><br></div>
<a style="color: #000000" th:text="'装机量 '+${deviceDeployedNum}">2020</a> <a style="color: #000000" th:text="'装机量 '+${deviceDeployedNum}">2020</a>
</div> </div>
</div> </div>