优化log机制
This commit is contained in:
parent
86776c2405
commit
7c9a5b0d26
@ -25,6 +25,9 @@ public class GnssDevice {
|
|||||||
public static final short MODEL_G505 = 0; //F9P
|
public static final short MODEL_G505 = 0; //F9P
|
||||||
public static final short MODEL_G510 = 1; //博通
|
public static final short MODEL_G510 = 1; //博通
|
||||||
|
|
||||||
|
public static final short LOGGING_MODE_SIMPLE = 0; // 精简模式( 仅D3F0和D3F2 )
|
||||||
|
public static final short LOGGING_MODE_FULL = 1; // 完整模式
|
||||||
|
|
||||||
@TableId(value = "id", type = IdType.AUTO)
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
private Long id;
|
private Long id;
|
||||||
private Integer tenantid;
|
private Integer tenantid;
|
||||||
@ -60,4 +63,7 @@ public class GnssDevice {
|
|||||||
private String imei;
|
private String imei;
|
||||||
private Short model;
|
private Short model;
|
||||||
|
|
||||||
|
// 日志记录控制
|
||||||
|
private Short loggingmode;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,44 @@
|
|||||||
|
package com.imdroid.secapi.dto;
|
||||||
|
|
||||||
|
import com.alibaba.excel.annotation.ExcelIgnore;
|
||||||
|
import com.alibaba.excel.annotation.ExcelProperty;
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName(value = "gnssdevicesinglerecords")
|
||||||
|
public class GnssSingleData {
|
||||||
|
public static final short MODEL_G505 = 0; //F9P
|
||||||
|
public static final short MODEL_G510 = 1; //博通
|
||||||
|
|
||||||
|
|
||||||
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
|
@ExcelIgnore
|
||||||
|
Long id;
|
||||||
|
@ExcelProperty("设备编号")
|
||||||
|
String deviceid;
|
||||||
|
|
||||||
|
@ExcelProperty("记录时间")
|
||||||
|
LocalDateTime createtime;
|
||||||
|
|
||||||
|
// 博通的 GGA 经纬度数据
|
||||||
|
// F9P 的私有格式 B562 的 ECEF 数据
|
||||||
|
@ExcelProperty("型号")
|
||||||
|
Short model;
|
||||||
|
|
||||||
|
@ExcelProperty("东")
|
||||||
|
double x; // GGA时是 latitude, ECEF时是 x
|
||||||
|
@ExcelProperty("北")
|
||||||
|
double y; // GGA时是 longitude, ECEF时是 y
|
||||||
|
@ExcelProperty("天")
|
||||||
|
double z; // GGA时是 altitude, ECEF时是 z
|
||||||
|
|
||||||
|
// GGA 时 GPS状态,0初始化,1单点定位,2码差分,3无效PPS,4固定解,5浮点解,6正在估算7,人工输入固定值,8模拟模式,9WAAS差分
|
||||||
|
// ECEF 时 0无B562,1 浮点解,2 固定解
|
||||||
|
@ExcelProperty("状态")
|
||||||
|
int status;
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
package com.imdroid.secapi.dto;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.github.yulichang.base.MPJBaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface GnssSingleDataMapper extends MPJBaseMapper<GnssSingleData> {
|
||||||
|
Page<GnssSingleData> queryByDeviceId(@Param("page") IPage page, @Param("deviceId") String deviceId,
|
||||||
|
@Param("beginTime") String beginTime, @Param("endTime") String endTime, @Param("count") Integer count);
|
||||||
|
}
|
||||||
18
sec-api/src/main/resources/mapper/GnssSingleDataMapper.xml
Normal file
18
sec-api/src/main/resources/mapper/GnssSingleDataMapper.xml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.imdroid.secapi.dto.GnssSingleDataMapper">
|
||||||
|
|
||||||
|
<select id="queryByDeviceId" resultType="com.imdroid.secapi.dto.GnssSingleData">
|
||||||
|
select c.* from (select @n:=@n+1 as n, a.* from (select * from gnssdevicesinglerecords
|
||||||
|
<where>
|
||||||
|
deviceid = #{deviceId}
|
||||||
|
<if test="beginTime != null and beginTime != ''">
|
||||||
|
and createtime >= #{beginTime}
|
||||||
|
</if>
|
||||||
|
<if test="endTime != null and endTime != ''">
|
||||||
|
and createtime <= #{endTime}
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
order by createtime desc)a,(select @n:=0)b)c where c.n%#{count}=1
|
||||||
|
</select>
|
||||||
|
</mapper>
|
||||||
@ -3,16 +3,14 @@ package com.imdroid.sideslope.calc;
|
|||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.imdroid.common.util.DataTypeUtil;
|
import com.imdroid.common.util.DataTypeUtil;
|
||||||
import com.imdroid.common.util.ThreadManager;
|
import com.imdroid.common.util.ThreadManager;
|
||||||
import com.imdroid.secapi.dto.GnssCalcData;
|
import com.imdroid.secapi.dto.*;
|
||||||
import com.imdroid.secapi.dto.GnssCalcDataMapper;
|
|
||||||
import com.imdroid.secapi.dto.GnssGroupCalc;
|
|
||||||
import com.imdroid.secapi.dto.GnssGroupCalcMapper;
|
|
||||||
import com.imdroid.sideslope.bd.*;
|
import com.imdroid.sideslope.bd.*;
|
||||||
import com.imdroid.sideslope.message.D341LocationMessage;
|
import com.imdroid.sideslope.message.D341LocationMessage;
|
||||||
import com.imdroid.sideslope.sal.Device;
|
import com.imdroid.sideslope.sal.Device;
|
||||||
import com.imdroid.sideslope.sal.DeviceService;
|
import com.imdroid.sideslope.sal.DeviceService;
|
||||||
import com.imdroid.sideslope.server.DeviceChannel;
|
import com.imdroid.sideslope.server.DeviceChannel;
|
||||||
import com.imdroid.sideslope.server.OnlineChannels;
|
import com.imdroid.sideslope.server.OnlineChannels;
|
||||||
|
import com.imdroid.sideslope.service.GnssSingleBufferService;
|
||||||
import com.imdroid.sideslope.service.WarningService;
|
import com.imdroid.sideslope.service.WarningService;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
@ -56,6 +54,9 @@ public class SingleLineGNSSCalcService implements GNSSDataCalcService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
GnssCalcDataMapper dataMapper;
|
GnssCalcDataMapper dataMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private GnssSingleBufferService gnssSingleDataService;
|
||||||
|
|
||||||
// 非线程安全,需加同步保护
|
// 非线程安全,需加同步保护
|
||||||
List<GnssGroupCalc> groupCalcList;
|
List<GnssGroupCalc> groupCalcList;
|
||||||
|
|
||||||
@ -149,6 +150,32 @@ public class SingleLineGNSSCalcService implements GNSSDataCalcService {
|
|||||||
hardResetDevice(deviceId);
|
hardResetDevice(deviceId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 若是该设备开启了日志记录,则保存单次解析的数据
|
||||||
|
if(device.getLoggingmode() == GnssDevice.LOGGING_MODE_FULL){
|
||||||
|
// 保存单次解析的原始数据,受 loggingmode 字段控制
|
||||||
|
GnssSingleData gnssSingleData = new GnssSingleData();
|
||||||
|
gnssSingleData.setDeviceid(device.getDeviceId());
|
||||||
|
gnssSingleData.setCreatetime(LocalDateTime.now());
|
||||||
|
gnssSingleData.setModel(device.getModel());
|
||||||
|
if((device.getModel() == GnssDevice.MODEL_G505) && (doubles !=null)){
|
||||||
|
gnssSingleData.setX(doubles[0]);
|
||||||
|
gnssSingleData.setY(doubles[1]);
|
||||||
|
gnssSingleData.setZ(doubles[2]);
|
||||||
|
gnssSingleData.setStatus((int) doubles[3]);
|
||||||
|
gnssSingleDataService.addData(gnssSingleData);
|
||||||
|
}
|
||||||
|
else if((device.getModel() == GnssDevice.MODEL_G510) && (gga !=null)){
|
||||||
|
gnssSingleData.setX(gga.getLatitude());
|
||||||
|
gnssSingleData.setY(gga.getLongitude());
|
||||||
|
gnssSingleData.setZ(gga.getAltitude());
|
||||||
|
gnssSingleData.setStatus(gga.getQuality());
|
||||||
|
gnssSingleDataService.addData(gnssSingleData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package com.imdroid.sideslope.executor;
|
package com.imdroid.sideslope.executor;
|
||||||
|
|
||||||
|
import com.imdroid.common.util.DataTypeUtil;
|
||||||
import com.imdroid.common.util.ThreadManager;
|
import com.imdroid.common.util.ThreadManager;
|
||||||
import com.imdroid.secapi.client.BeidouClient;
|
import com.imdroid.secapi.client.BeidouClient;
|
||||||
import com.imdroid.secapi.dto.GnssDevice;
|
import com.imdroid.secapi.dto.GnssDevice;
|
||||||
@ -41,7 +42,13 @@ public class D331RtcmMessageExecutor implements Executor<D331RtcmMessage, Void>
|
|||||||
// 补齐tenantId
|
// 补齐tenantId
|
||||||
Device device1 = deviceService.findByDeviceId(id);
|
Device device1 = deviceService.findByDeviceId(id);
|
||||||
if(device1 == null || device1.getOpMode() == GnssDevice.OP_MODE_UNUSE) return null;
|
if(device1 == null || device1.getOpMode() == GnssDevice.OP_MODE_UNUSE) return null;
|
||||||
logger.debug("receive d331 rtcm message of device: "+message.getId()+", seq:"+message.getSeq()+", len:"+message.getLen());
|
|
||||||
|
// 原始码流输出到日志文件 -- 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(device1.getOpMode() == GnssDevice.OP_MODE_USE) {
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
package com.imdroid.sideslope.executor;
|
package com.imdroid.sideslope.executor;
|
||||||
|
|
||||||
|
import com.imdroid.common.util.DataTypeUtil;
|
||||||
import com.imdroid.common.util.ThreadManager;
|
import com.imdroid.common.util.ThreadManager;
|
||||||
import com.imdroid.secapi.client.BeidouClient;
|
import com.imdroid.secapi.client.BeidouClient;
|
||||||
|
import com.imdroid.secapi.dto.GnssDevice;
|
||||||
import com.imdroid.sideslope.bd.Gga;
|
import com.imdroid.sideslope.bd.Gga;
|
||||||
import com.imdroid.sideslope.calc.GNSSDataCalcService;
|
import com.imdroid.sideslope.calc.GNSSDataCalcService;
|
||||||
import com.imdroid.sideslope.message.D341LocationMessage;
|
import com.imdroid.sideslope.message.D341LocationMessage;
|
||||||
@ -35,14 +37,17 @@ public class D341LocationMessageExecutor implements Executor<D341LocationMessage
|
|||||||
private DataPersistService dataPersistService;
|
private DataPersistService dataPersistService;
|
||||||
@Override
|
@Override
|
||||||
public Void execute(D341LocationMessage message) {
|
public Void execute(D341LocationMessage message) {
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug("receive d341 message of device: "+message.getId()+", seq:"+message.getSeq()+", len:"+message.getLen());
|
|
||||||
}
|
|
||||||
// 补齐tenantId,要求快速处理,因此用缓存,不要每次都查数据库
|
// 补齐tenantId,要求快速处理,因此用缓存,不要每次都查数据库
|
||||||
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());
|
message.setTenantId(device.getTenantId());
|
||||||
|
|
||||||
|
// 原始码流输出到日志文件 -- INFO 级别
|
||||||
|
if(device.getLoggingmode() == GnssDevice.LOGGING_MODE_FULL){
|
||||||
|
logger.info("receive "+message.getId()+" d341 message: "+ DataTypeUtil.getHexString(message.getSrcData()));
|
||||||
|
logger.info("receive d341 message of device: "+message.getId()+", seq:"+message.getSeq()+", len:"+message.getLen());
|
||||||
|
}
|
||||||
|
|
||||||
// trx cycle stat
|
// trx cycle stat
|
||||||
LocalDateTime now = LocalDateTime.now();
|
LocalDateTime now = LocalDateTime.now();
|
||||||
if(device.getLastRxTime()!=null &&
|
if(device.getLastRxTime()!=null &&
|
||||||
@ -86,6 +91,13 @@ 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());
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package com.imdroid.sideslope.executor;
|
package com.imdroid.sideslope.executor;
|
||||||
|
|
||||||
|
import com.imdroid.common.util.DataTypeUtil;
|
||||||
import com.imdroid.common.util.HexUtil;
|
import com.imdroid.common.util.HexUtil;
|
||||||
import com.imdroid.common.util.ThreadManager;
|
import com.imdroid.common.util.ThreadManager;
|
||||||
import com.imdroid.secapi.client.BeidouClient;
|
import com.imdroid.secapi.client.BeidouClient;
|
||||||
@ -43,9 +44,7 @@ public class D3F0SelfCheckMessageExecutor implements Executor<D3F0SelfCheckMessa
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void execute(D3F0SelfCheckMessage message) {
|
public Void execute(D3F0SelfCheckMessage message) {
|
||||||
if (logger.isDebugEnabled()) {
|
logger.info("receive d3f0 message of {} device: {}", message.getId(), DataTypeUtil.getHexString(message.getSrcData()));
|
||||||
logger.debug("receive d3f0 message of device: "+message.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
Device device = deviceService.findByDeviceId(message.getId());
|
Device device = deviceService.findByDeviceId(message.getId());
|
||||||
if(device == null) return null;
|
if(device == null) return null;
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package com.imdroid.sideslope.executor;
|
package com.imdroid.sideslope.executor;
|
||||||
|
|
||||||
|
import com.imdroid.common.util.DataTypeUtil;
|
||||||
import com.imdroid.common.util.ThreadManager;
|
import com.imdroid.common.util.ThreadManager;
|
||||||
import com.imdroid.secapi.client.BeidouClient;
|
import com.imdroid.secapi.client.BeidouClient;
|
||||||
import com.imdroid.secapi.dto.GnssTrxMsg;
|
import com.imdroid.secapi.dto.GnssTrxMsg;
|
||||||
@ -9,6 +10,7 @@ import com.imdroid.sideslope.message.D3F2StopIndicationMessage;
|
|||||||
import com.imdroid.sideslope.sal.Device;
|
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.WarningService;
|
import com.imdroid.sideslope.service.WarningService;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@ -41,11 +43,14 @@ public class D3F2StopIndicationMessageExecutor implements Executor<D3F2StopIndic
|
|||||||
@Autowired
|
@Autowired
|
||||||
WarningService warningService;
|
WarningService warningService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
GnssSingleBufferServiceImpl gnssSingleBufferService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void execute(D3F2StopIndicationMessage message) {
|
public Void execute(D3F2StopIndicationMessage message) {
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug("receive d3f2 message of device: "+message.getId());
|
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);
|
||||||
@ -65,6 +70,10 @@ public class D3F2StopIndicationMessageExecutor implements Executor<D3F2StopIndic
|
|||||||
LocalDateTime uploadTime = multiLineGNSSCalcService.checkUploadTime(
|
LocalDateTime uploadTime = multiLineGNSSCalcService.checkUploadTime(
|
||||||
device.getDeviceId(), device.getTenantId());
|
device.getDeviceId(), device.getTenantId());
|
||||||
dataPersistService.saveDeviceTrxStat(message, (uploadTime!=null), device);
|
dataPersistService.saveDeviceTrxStat(message, (uploadTime!=null), device);
|
||||||
|
|
||||||
|
// 保存缓存中的 GNSS 单次解析结果
|
||||||
|
gnssSingleBufferService.flush();
|
||||||
|
|
||||||
// 通知beidou服务设备休眠
|
// 通知beidou服务设备休眠
|
||||||
try {
|
try {
|
||||||
beidouClient.onDeviceStop(deviceId, device.getTenantId());
|
beidouClient.onDeviceStop(deviceId, device.getTenantId());
|
||||||
|
|||||||
@ -38,6 +38,8 @@ public class D341LocationMessage extends BaseMessage {
|
|||||||
// b562
|
// b562
|
||||||
b562_loc = UBXUtil.getLocation(src);
|
b562_loc = UBXUtil.getLocation(src);
|
||||||
gga = Gga.getFrom(src);
|
gga = Gga.getFrom(src);
|
||||||
|
this.srcData = new byte[src.readableBytes()];
|
||||||
|
src.readBytes(this.srcData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -58,6 +58,11 @@ public class D3F0SelfCheckMessage extends BaseMessage {
|
|||||||
" reboot:"+src.readUnsignedShort();
|
" reboot:"+src.readUnsignedShort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// read 会移动 bytebuf 的指针,所以保存原始码流需要将此指针挑拨回开始处
|
||||||
|
src.readerIndex(0);
|
||||||
|
this.srcData = new byte[src.readableBytes()];
|
||||||
|
src.readBytes(this.srcData);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -60,6 +60,11 @@ public class D3F2StopIndicationMessage extends BaseMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// read 会移动 bytebuf 的指针,所以保存原始码流需要将此指针挑拨回开始处
|
||||||
|
src.readerIndex(0);
|
||||||
|
this.srcData = new byte[src.readableBytes()];
|
||||||
|
src.readBytes(this.srcData);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,6 +30,7 @@ public class DbDeviceServiceImpl implements DeviceService {
|
|||||||
device.setTenantId(gnssDevice.getTenantid());
|
device.setTenantId(gnssDevice.getTenantid());
|
||||||
device.setDeviceId(gnssDevice.getDeviceid());
|
device.setDeviceId(gnssDevice.getDeviceid());
|
||||||
device.setDeviceType(gnssDevice.getDevicetype());
|
device.setDeviceType(gnssDevice.getDevicetype());
|
||||||
|
device.setModel(gnssDevice.getModel());
|
||||||
device.setParentId(gnssDevice.getParentid());
|
device.setParentId(gnssDevice.getParentid());
|
||||||
device.setName(gnssDevice.getName());
|
device.setName(gnssDevice.getName());
|
||||||
device.setProjectId(gnssDevice.getProject_id());
|
device.setProjectId(gnssDevice.getProject_id());
|
||||||
@ -42,6 +43,7 @@ public class DbDeviceServiceImpl implements DeviceService {
|
|||||||
device.setEcefx(gnssDevice.getEcefx());
|
device.setEcefx(gnssDevice.getEcefx());
|
||||||
device.setEcefy(gnssDevice.getEcefy());
|
device.setEcefy(gnssDevice.getEcefy());
|
||||||
device.setEcefz(gnssDevice.getEcefz());
|
device.setEcefz(gnssDevice.getEcefz());
|
||||||
|
device.setLoggingmode(gnssDevice.getLoggingmode());
|
||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -35,6 +35,7 @@ public class Device {
|
|||||||
private String fwdId;
|
private String fwdId;
|
||||||
|
|
||||||
private Integer deviceType;
|
private Integer deviceType;
|
||||||
|
private Short model;
|
||||||
|
|
||||||
private Integer calcGroupId;
|
private Integer calcGroupId;
|
||||||
private Short opMode;
|
private Short opMode;
|
||||||
@ -65,6 +66,9 @@ public class Device {
|
|||||||
LocalDateTime lastD3f0f2Time;
|
LocalDateTime lastD3f0f2Time;
|
||||||
short noFixedAndFloatResult=0;
|
short noFixedAndFloatResult=0;
|
||||||
|
|
||||||
|
// 日志记录控制
|
||||||
|
Short loggingmode;
|
||||||
|
|
||||||
int lastRxHead = 0;
|
int lastRxHead = 0;
|
||||||
|
|
||||||
int fixedNum = 0;
|
int fixedNum = 0;
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
package com.imdroid.sideslope.server.tcp;
|
package com.imdroid.sideslope.server.tcp;
|
||||||
|
|
||||||
import com.imdroid.common.util.DataTypeUtil;
|
|
||||||
import com.imdroid.sideslope.executor.BizExecutors;
|
import com.imdroid.sideslope.executor.BizExecutors;
|
||||||
import com.imdroid.sideslope.executor.MessageParser;
|
import com.imdroid.sideslope.executor.MessageParser;
|
||||||
import com.imdroid.sideslope.message.BaseMessage;
|
import com.imdroid.sideslope.message.BaseMessage;
|
||||||
@ -19,11 +18,11 @@ public class RtcmTcpHandler extends SimpleChannelInboundHandler<ByteBuf> {
|
|||||||
private final Logger logger = LoggerFactory.getLogger(RtcmTcpServer.class);
|
private final Logger logger = LoggerFactory.getLogger(RtcmTcpServer.class);
|
||||||
@Override
|
@Override
|
||||||
public void channelRead0(ChannelHandlerContext ctx, ByteBuf src) throws Exception{
|
public void channelRead0(ChannelHandlerContext ctx, ByteBuf src) throws Exception{
|
||||||
if (logger.isDebugEnabled()) {
|
/*if (logger.isDebugEnabled()) {
|
||||||
byte[] data = new byte[src.readableBytes()];
|
byte[] data = new byte[src.readableBytes()];
|
||||||
src.getBytes(0, data);
|
src.getBytes(0, data);
|
||||||
logger.debug("receive message:" + DataTypeUtil.getHexString(data));
|
logger.debug("receive message:" + DataTypeUtil.getHexString(data));
|
||||||
}
|
}*/
|
||||||
try {
|
try {
|
||||||
BaseMessage message = MessageParser.instance.parse(src);
|
BaseMessage message = MessageParser.instance.parse(src);
|
||||||
OnlineChannels.INSTANCE.updateConfigChannel(message.getId(), ctx.channel(), null);
|
OnlineChannels.INSTANCE.updateConfigChannel(message.getId(), ctx.channel(), null);
|
||||||
|
|||||||
@ -0,0 +1,10 @@
|
|||||||
|
package com.imdroid.sideslope.service;
|
||||||
|
|
||||||
|
import com.imdroid.secapi.dto.GnssSingleData;
|
||||||
|
|
||||||
|
public interface GnssSingleBufferService {
|
||||||
|
void addData(GnssSingleData data);
|
||||||
|
void flush();
|
||||||
|
void clear();
|
||||||
|
int getBufferSize();
|
||||||
|
}
|
||||||
@ -0,0 +1,81 @@
|
|||||||
|
package com.imdroid.sideslope.service;
|
||||||
|
|
||||||
|
import com.imdroid.secapi.dto.GnssSingleData;
|
||||||
|
import com.imdroid.secapi.dto.GnssSingleDataMapper;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class GnssSingleBufferServiceImpl implements GnssSingleBufferService {
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
private final List<GnssSingleData> buffer = new ArrayList<>();
|
||||||
|
|
||||||
|
// BUFFER_SIZE 暂定此大小
|
||||||
|
private static final int BUFFER_SIZE = 1024;
|
||||||
|
// 资源锁
|
||||||
|
private final Object lock = new Object();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private GnssSingleDataMapper gnssSingleDataMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addData(GnssSingleData data) {
|
||||||
|
if (data == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
synchronized (lock) {
|
||||||
|
buffer.add(data);
|
||||||
|
if (buffer.size() >= BUFFER_SIZE) {
|
||||||
|
// 溢出时直接保存
|
||||||
|
// 此处暂定,但很有必要引入一个线程来保存,避免阻塞主线程
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void flush() {
|
||||||
|
synchronized (lock) {
|
||||||
|
if (buffer.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
List<GnssSingleData> batchList = new ArrayList<>(buffer);
|
||||||
|
buffer.clear();
|
||||||
|
// 由于每秒写数据库操作频繁,这里采用批量保存的方式
|
||||||
|
saveBatch(batchList);
|
||||||
|
|
||||||
|
logger.debug("批量插入{}条数据成功", batchList.size());
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("批量插入数据失败", e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveBatch(List<GnssSingleData> dataList) {
|
||||||
|
for (GnssSingleData data : dataList) {
|
||||||
|
gnssSingleDataMapper.insert(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
synchronized (lock) {
|
||||||
|
buffer.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBufferSize() {
|
||||||
|
synchronized(lock) {
|
||||||
|
return buffer.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,9 +2,11 @@ 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;
|
||||||
|
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;
|
||||||
@ -22,6 +24,9 @@ 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<>();
|
||||||
int warningLevel2Code = 0;
|
int warningLevel2Code = 0;
|
||||||
@ -174,6 +179,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;
|
||||||
}
|
}
|
||||||
@ -219,4 +227,12 @@ 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,93 @@
|
|||||||
|
package com.imdroid.beidou.controller;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.imdroid.beidou.service.CommonExcelService;
|
||||||
|
import com.imdroid.secapi.dto.GnssSingleData;
|
||||||
|
import com.imdroid.secapi.dto.GnssSingleDataMapper;
|
||||||
|
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;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
public class GnssSingleDataController extends BasicController implements CommonExcelService<GnssSingleData, GnssSingleData> {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
GnssSingleDataMapper gnssSingleDataMapper;
|
||||||
|
|
||||||
|
final DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
|
|
||||||
|
@RequestMapping("/page/gnss_single_data")
|
||||||
|
public String gnssSingleData(Model m, HttpSession session){
|
||||||
|
initModel(m, session);
|
||||||
|
|
||||||
|
return "/page/gnss_single_data";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@RequestMapping("/gnss/data/list_single_data")
|
||||||
|
@ResponseBody
|
||||||
|
public JSONObject listData(HttpSession session, Integer page, Integer limit, String searchParams) {
|
||||||
|
// 检查查询条件
|
||||||
|
JSONObject search = null;
|
||||||
|
if (searchParams != null) {
|
||||||
|
search = (JSONObject) JSONObject.parse(searchParams);
|
||||||
|
System.out.println(search);
|
||||||
|
String deviceId = search.getString("deviceid");
|
||||||
|
Integer freqency = search.getInteger("freqency");
|
||||||
|
String begin = search.getString("dgt_.createtime");
|
||||||
|
String end = search.getString("dlt_.createtime");
|
||||||
|
|
||||||
|
if(deviceId != null && !deviceId.isEmpty() && freqency!=0){
|
||||||
|
Page pageable = new Page<>(page == null ? 1 : page, limit == null ? 10 : limit);
|
||||||
|
|
||||||
|
// 缺省按1小时采样,如果时间跨度较大,则按最多300条记录的采样率采样
|
||||||
|
int sample = 6;
|
||||||
|
|
||||||
|
if(freqency == 2){
|
||||||
|
LocalDateTime endTime = LocalDateTime.now();
|
||||||
|
LocalDateTime beginTime = endTime.minusDays(30);
|
||||||
|
if(begin!=null && !begin.isEmpty()){
|
||||||
|
beginTime = LocalDateTime.parse(begin,df);
|
||||||
|
}
|
||||||
|
if(end!=null && !end.isEmpty()){
|
||||||
|
endTime = LocalDateTime.parse(end,df);
|
||||||
|
}
|
||||||
|
Duration duration = Duration.between(beginTime, endTime);
|
||||||
|
int hours = (int)duration.toHours();
|
||||||
|
if(hours > 300) sample = hours*6/300;
|
||||||
|
}
|
||||||
|
Page<GnssSingleData> calcDataList = gnssSingleDataMapper.queryByDeviceId(pageable, deviceId,begin,end,sample);
|
||||||
|
|
||||||
|
JSONObject jsonObject = new JSONObject();
|
||||||
|
jsonObject.put("code", 0);
|
||||||
|
jsonObject.put("msg", "");
|
||||||
|
jsonObject.put("count", calcDataList.getTotal());
|
||||||
|
jsonObject.put("data", calcDataList.getRecords());
|
||||||
|
return jsonObject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.pageList(session, page, limit, searchParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<GnssSingleData> getEntityClass() {
|
||||||
|
return GnssSingleData.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BaseMapper<GnssSingleData> getMapper() {
|
||||||
|
return gnssSingleDataMapper;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,9 +3,11 @@ package com.imdroid.beidou.task;
|
|||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.github.yulichang.query.MPJQueryWrapper;
|
import com.github.yulichang.query.MPJQueryWrapper;
|
||||||
import com.imdroid.beidou.service.NotificationService;
|
import com.imdroid.beidou.service.NotificationService;
|
||||||
|
import com.imdroid.common.util.WarningLogExecutor;
|
||||||
import com.imdroid.secapi.dto.*;
|
import com.imdroid.secapi.dto.*;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
@ -44,6 +46,10 @@ public class DeviceStatusChecker {
|
|||||||
GnssCalcDataMapper dataMapper;
|
GnssCalcDataMapper dataMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
GnssDeviceMapper deviceMapper;
|
GnssDeviceMapper deviceMapper;
|
||||||
|
|
||||||
|
@Value("${warning.log.directory}")
|
||||||
|
private String logDirectory;
|
||||||
|
|
||||||
static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
@Scheduled(cron = "0 18,48 * * * ?") // 每半时执行一次
|
@Scheduled(cron = "0 18,48 * * * ?") // 每半时执行一次
|
||||||
@ -153,6 +159,12 @@ public class DeviceStatusChecker {
|
|||||||
status.setWarningcode(status.getWarningcode() | WarningCfg.TYPE_NO_FIXED_RESULT);
|
status.setWarningcode(status.getWarningcode() | WarningCfg.TYPE_NO_FIXED_RESULT);
|
||||||
status.setWarning(WarningCfg.LEVEL_2);
|
status.setWarning(WarningCfg.LEVEL_2);
|
||||||
deviceIds.add(status.getDeviceid());
|
deviceIds.add(status.getDeviceid());
|
||||||
|
|
||||||
|
// 生成 Warning 日志
|
||||||
|
WarningLogExecutor warningLogExecutor = new WarningLogExecutor(logDirectory);
|
||||||
|
warningLogExecutor.generateWarningLogs(status.getDeviceid(),WarningCfg.TYPE_NAME_NO_FIXED_RESULT);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
gnssStatusMapper.updateById(status);
|
gnssStatusMapper.updateById(status);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,6 +53,12 @@
|
|||||||
"icon": "fa fa-calculator",
|
"icon": "fa fa-calculator",
|
||||||
"target": "_self"
|
"target": "_self"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"title": "Log",
|
||||||
|
"href": "page/gnss_single_data",
|
||||||
|
"icon": "fa fa-clipboard",
|
||||||
|
"target": "_self"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"title": "配置管理",
|
"title": "配置管理",
|
||||||
"href": "",
|
"href": "",
|
||||||
|
|||||||
@ -0,0 +1,249 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>单次解算记录</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 10px 10px 10px">
|
||||||
|
<form class="layui-form layui-form-pane" action="" id="searchFrm">
|
||||||
|
<div class="layui-form-item">
|
||||||
|
<div class="layui-inline">
|
||||||
|
<label class="layui-form-label">设备号</label>
|
||||||
|
<div class="layui-input-inline">
|
||||||
|
<input type="text" name="deviceid" id="input_deviceid" class="layui-input" style="position:absolute;z-index:2;width:85%;" value="" autocomplete="off">
|
||||||
|
<select id="deviceid" lay-search="" lay-filter="device" >
|
||||||
|
<option value="">全部</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="layui-inline">
|
||||||
|
<label class="layui-form-label">范围</label>
|
||||||
|
<div class="layui-input-inline">
|
||||||
|
<input type="text" name="dgt_createtime" autocomplete="off" id="ID-laydate-start-date" class="layui-input" placeholder="开始日期">
|
||||||
|
</div>
|
||||||
|
<div class="layui-input-inline">
|
||||||
|
<input type="text" name="dlt_createtime" autocomplete="off" id="ID-laydate-end-date" class="layui-input" placeholder="结束日期">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-inline">
|
||||||
|
<label class="layui-form-label">粒度</label>
|
||||||
|
<div class="layui-input-inline">
|
||||||
|
<select name="freqency" id="freqency" lay-search="">
|
||||||
|
<option value="0">次</option>
|
||||||
|
<option value="1">小时</option>
|
||||||
|
<option value="2">自动</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="layui-inline">
|
||||||
|
<button type="submit" class="layui-btn layui-btn-primary" lay-submit lay-filter="data-search-btn"><i class="layui-icon"></i> 搜 索</button>
|
||||||
|
<button type="submit" class="layui-btn layui-btn-primary" lay-submit lay-filter="data-export-btn"><i class="layui-icon"></i>导出</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
<div class="layui-tab layui-tab-card" lay-filter="data-tab">
|
||||||
|
<ul class="layui-tab-title">
|
||||||
|
<li class="layui-this">数据表格</li>
|
||||||
|
<li>单个设备曲线</li>
|
||||||
|
</ul>
|
||||||
|
<div class="layui-tab-content">
|
||||||
|
<div class="layui-tab-item layui-show">
|
||||||
|
<table class="layui-hide" id="currentTableId" lay-filter="currentTableFilter"></table>
|
||||||
|
</div>
|
||||||
|
<div class="layui-tab-item">
|
||||||
|
<div id="echarts-gnss" style="min-height:300px;padding: 10px"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/html" id="currentTableBar">
|
||||||
|
<a class="layui-btn layui-btn-normal layui-btn-xs data-count-edit" lay-event="cmd">命令行</a>
|
||||||
|
</script>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script src="../js/lay-module/echarts/echartsTheme.js" charset="utf-8"></script>
|
||||||
|
<script src="../js/lay-module/echarts/echarts.js" charset="utf-8"></script>
|
||||||
|
<script src="../lib/layui-v2.6.3/layui.js" charset="utf-8"></script>
|
||||||
|
<script th:inline="javascript">
|
||||||
|
layui.use(['form', 'table','laydate','element'], function () {
|
||||||
|
var $ = layui.$,
|
||||||
|
form = layui.form,
|
||||||
|
table = layui.table,
|
||||||
|
laydate = layui.laydate;
|
||||||
|
var searchDeviceId = false;
|
||||||
|
var echartsDevice = echarts.init(document.getElementById('echarts-gnss'), 'walden');
|
||||||
|
var data_cols = [
|
||||||
|
{field: 'deviceid', title: '设备号'},
|
||||||
|
{field: 'createtime', title: '产生时间', width:'18%', templet: "<div>{{layui.util.toDateString(d.createtime, 'yyyy-MM-dd HH:mm:ss')}}</div>"},
|
||||||
|
{field: 'x', title: '东'},
|
||||||
|
{field: 'y', title: '北'},
|
||||||
|
{field: 'z', title: '天'},
|
||||||
|
{field: 'status', title: '状态'}
|
||||||
|
];
|
||||||
|
/**
|
||||||
|
* 初始化表单,要加上,不然刷新部分组件可能会不加载
|
||||||
|
*/
|
||||||
|
form.render();
|
||||||
|
|
||||||
|
laydate.render({
|
||||||
|
elem: '#ID-laydate-start-date',
|
||||||
|
type: 'datetime'
|
||||||
|
});
|
||||||
|
laydate.render({
|
||||||
|
elem: '#ID-laydate-end-date',
|
||||||
|
type: 'datetime'
|
||||||
|
});
|
||||||
|
|
||||||
|
table.render({
|
||||||
|
elem: '#currentTableId',
|
||||||
|
url: '/gnss/data/list_single_data',
|
||||||
|
toolbar: '#toolbarDemo', //开启头部工具栏
|
||||||
|
defaultToolbar: ['filter'],
|
||||||
|
cols: [
|
||||||
|
data_cols
|
||||||
|
],
|
||||||
|
limits: [20, 50, 100, 200, 300],
|
||||||
|
limit: 20,
|
||||||
|
page: true,
|
||||||
|
skin: 'line',
|
||||||
|
done: function (result, curr, count) {
|
||||||
|
if(searchDeviceId){
|
||||||
|
console.log(result.data);
|
||||||
|
showChart(result.data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 监听搜索操作
|
||||||
|
form.on('submit(data-search-btn)', function (data) {
|
||||||
|
var result = JSON.stringify(data.field);
|
||||||
|
var deviceId = $('#input_deviceid').val();
|
||||||
|
searchDeviceId = !isNaN(deviceId);
|
||||||
|
//执行搜索重载
|
||||||
|
table.reload('currentTableId', {
|
||||||
|
page: {
|
||||||
|
curr: 1
|
||||||
|
}
|
||||||
|
, where: {
|
||||||
|
searchParams: result
|
||||||
|
}
|
||||||
|
}, 'data');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 监听导出操作
|
||||||
|
form.on('submit(data-export-btn)', function (data) {
|
||||||
|
var result = $('#searchFrm').serialize();
|
||||||
|
var u = "/gnss/data/calc/export?" + result;
|
||||||
|
window.open(u, "_blank");
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
form.on('select(device)', function (data) {
|
||||||
|
//对select和input进行监控渲染
|
||||||
|
if (data.value != "") {
|
||||||
|
$("#input_deviceid").val(data.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//监听Tab切换,重新resize图表,否则显示不出来
|
||||||
|
layui.element.on('tab(data-tab)', function(data){
|
||||||
|
if (data.index == 1) {
|
||||||
|
echartsDevice.resize();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function showChart(chartData){
|
||||||
|
var sortedData = chartData.sort((a, b) => new Date(a.createtime) - new Date(b.createtime));
|
||||||
|
// 处理数据
|
||||||
|
var times = sortedData.map(item => {
|
||||||
|
let date = new Date(item.createtime);
|
||||||
|
return date.toLocaleTimeString();
|
||||||
|
});
|
||||||
|
var xValues = sortedData.map(item => item.x);
|
||||||
|
var yValues = sortedData.map(item => item.y);
|
||||||
|
var zValues = sortedData.map(item => item.z);
|
||||||
|
|
||||||
|
// 图表配置
|
||||||
|
var option = {
|
||||||
|
title: {
|
||||||
|
text: 'GNSS 单次解记录',
|
||||||
|
left: 'center'
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
formatter: function(params) {
|
||||||
|
let result = params[0].name + '<br/>';
|
||||||
|
params.forEach(param => {
|
||||||
|
result += param.seriesName + ': ' +
|
||||||
|
param.value.toFixed(2) + '<br/>';
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: ['X坐标', 'Y坐标', 'Z坐标'],
|
||||||
|
top: '30px'
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '3%',
|
||||||
|
right: '4%',
|
||||||
|
bottom: '3%',
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: times,
|
||||||
|
axisLabel: {
|
||||||
|
rotate: 45
|
||||||
|
}
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
axisLabel: {
|
||||||
|
formatter: '{value}'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: 'X坐标',
|
||||||
|
type: 'line',
|
||||||
|
data: xValues,
|
||||||
|
smooth: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Y坐标',
|
||||||
|
type: 'line',
|
||||||
|
data: yValues,
|
||||||
|
smooth: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Z坐标',
|
||||||
|
type: 'line',
|
||||||
|
data: zValues,
|
||||||
|
smooth: true,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
echartsDevice.setOption(option);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -34,6 +34,16 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="layui-inline">
|
||||||
|
<label class="layui-form-label required">日志记录</label>
|
||||||
|
<div class="layui-input-inline">
|
||||||
|
<select name="loggingmode" id="loggingmode" lay-verify="required" lay-search="">
|
||||||
|
<option value="0">不记录(除了自检和停止消息)</option>
|
||||||
|
<option value="1">记录</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layui-form-item">
|
<div class="layui-form-item">
|
||||||
<div class="layui-inline">
|
<div class="layui-inline">
|
||||||
@ -292,6 +302,7 @@
|
|||||||
$('#fwd_group_id').val(data.fwd_group_id);
|
$('#fwd_group_id').val(data.fwd_group_id);
|
||||||
$('#fwd_group_id2').val(data.fwd_group_id2);
|
$('#fwd_group_id2').val(data.fwd_group_id2);
|
||||||
$('#opmode').val(data.opmode);
|
$('#opmode').val(data.opmode);
|
||||||
|
$('#loggingmode').val(data.loggingmode);
|
||||||
$('#fwddeviceid').val(data.fwddeviceid);
|
$('#fwddeviceid').val(data.fwddeviceid);
|
||||||
$('#ipose').val(data.ipose);
|
$('#ipose').val(data.ipose);
|
||||||
$('#iposn').val(data.iposn);
|
$('#iposn').val(data.iposn);
|
||||||
|
|||||||
@ -0,0 +1,89 @@
|
|||||||
|
package com.imdroid.common.util;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.file.*;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class WarningLogExecutor {
|
||||||
|
|
||||||
|
private final String logDirectory;
|
||||||
|
private final ExecutorService executor;
|
||||||
|
// 记录已初始化的文件
|
||||||
|
private final ConcurrentHashMap<String, Boolean> initializedFiles = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public WarningLogExecutor(String logDirectory) {
|
||||||
|
this.logDirectory = logDirectory;
|
||||||
|
this.executor = ThreadManager.getSingleThreadPool("warning_log_thread");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void generateWarningLogs(String keyword, String warningTypeName) {
|
||||||
|
try {
|
||||||
|
String date = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmm"));
|
||||||
|
String warningFileName = "Warning-" + keyword + "-" + date + ".log";
|
||||||
|
Path warningFile = Paths.get(logDirectory, warningFileName);
|
||||||
|
|
||||||
|
// 如果是新文件,先写入初始化信息
|
||||||
|
if (initializedFiles.putIfAbsent(warningFileName, true) == null) {
|
||||||
|
initializeWarningFile(warningFile, keyword, warningTypeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 找到日志文件
|
||||||
|
List<Path> logFiles = Files.list(Paths.get(logDirectory))
|
||||||
|
.filter(Files::isRegularFile)
|
||||||
|
.filter(path -> path.getFileName().toString().matches("sideslopertcm(\\.\\d{4}-\\d{2}-\\d{2}\\.\\d+)?\\.log"))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
for (Path logFile : logFiles) {
|
||||||
|
executor.submit(() -> processFile(logFile, keyword, warningTypeName, warningFile));
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
executor.shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeWarningFile(Path warningFile, String keyword, String warningTypeName) {
|
||||||
|
try (BufferedWriter writer = Files.newBufferedWriter(warningFile,
|
||||||
|
StandardOpenOption.CREATE, StandardOpenOption.APPEND)) {
|
||||||
|
writer.write("=== Warning Log File ===");
|
||||||
|
writer.newLine();
|
||||||
|
writer.write("Created Time: " + LocalDateTime.now());
|
||||||
|
writer.newLine();
|
||||||
|
writer.write("Warning Type Name: " + warningTypeName);
|
||||||
|
writer.newLine();
|
||||||
|
writer.write("Keyword: " + keyword);
|
||||||
|
writer.newLine();
|
||||||
|
writer.write("==============================");
|
||||||
|
writer.newLine();
|
||||||
|
writer.newLine();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processFile(Path logFile, String keyword, String warningTypeName, Path warningFile) {
|
||||||
|
try (BufferedReader reader = Files.newBufferedReader(logFile);
|
||||||
|
BufferedWriter writer = Files.newBufferedWriter(warningFile,
|
||||||
|
StandardOpenOption.CREATE, StandardOpenOption.APPEND)) {
|
||||||
|
|
||||||
|
writer.write("Processing source file: " + logFile.getFileName());
|
||||||
|
writer.newLine();
|
||||||
|
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
if (line.contains(keyword)) {
|
||||||
|
writer.write(line);
|
||||||
|
writer.newLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user