告警功能bug fixed

This commit is contained in:
weidong 2023-11-12 10:14:27 +08:00
parent 11eecd8b54
commit a34b83c1a2
28 changed files with 412 additions and 83 deletions

View File

@ -17,7 +17,6 @@ public class GnssGroup implements Serializable {
public final static short LOW_POWER_MODE = 0; public final static short LOW_POWER_MODE = 0;
public final static short NORMAL_POWER_MODE = 1; public final static short NORMAL_POWER_MODE = 1;
Integer id; Integer id;
Integer tenantid;
Integer work_cycle; Integer work_cycle;
Integer active_time; Integer active_time;

View File

@ -7,7 +7,6 @@ import lombok.Data;
@TableName(value = "gnssgroupcalc") @TableName(value = "gnssgroupcalc")
public class GnssGroupCalc { public class GnssGroupCalc {
Integer id; Integer id;
Integer tenantid;
Integer filter_hour; Integer filter_hour;
Float xy_threshold; Float xy_threshold;
Float z_threshold; Float z_threshold;

View File

@ -11,7 +11,6 @@ public class GnssGroupFwd {
public static final short FWD_TYPE_RAW = 2; //转发原始数据D331/D341 public static final short FWD_TYPE_RAW = 2; //转发原始数据D331/D341
public static final short FWD_TYPE_NTRIP = 3; //按ntrip协议转发 public static final short FWD_TYPE_NTRIP = 3; //按ntrip协议转发
Integer id; Integer id;
Integer tenantid;
String description; String description;
Short type1; Short type1;
String addr1; String addr1;

View File

@ -5,6 +5,9 @@ import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data; import lombok.Data;
import java.util.HashMap;
import java.util.Map;
/** /**
* GNSS收发统计消息每个工作周期结束的时候统计一次 * GNSS收发统计消息每个工作周期结束的时候统计一次
* *
@ -20,24 +23,28 @@ public class WarningCfg {
// warning code definition // warning code definition
public static final int TYPE_LOW_VOLTAGE = 0x01; public static final int TYPE_LOW_VOLTAGE = 0x01;
public static final String TYPE_NAME_LOW_VOLTAGE = "电压低";
public static final int TYPE_LOW_RSSI = 0x02; public static final int TYPE_LOW_RSSI = 0x02;
public static final String TYPE_NAME_LOW_RSSI = "信号弱";
public static final int TYPE_DEVICE_OFF_LINE = 0x04; public static final int TYPE_DEVICE_OFF_LINE = 0x04;
public static final String TYPE_NAME_DEVICE_OFF_LINE = "设备离线";
public static final int TYPE_RX_MUCH_UNKNOWN = 0x10; public static final int TYPE_RX_MUCH_UNKNOWN = 0x10;
public static final String TYPE_NAME_RX_MUCH_UNKNOWN = "未知报文过多";
public static final int TYPE_LESS_INUSE_SAT = 0x20; public static final int TYPE_LESS_INUSE_SAT = 0x20;
public static final String TYPE_NAME_LESS_INUSE_SAT = "可用卫星少";
public static final int TYPE_LESS_D3XX = 0x40; public static final int TYPE_LESS_D3XX = 0x40;
public static final String TYPE_NAME_LESS_D3XX = "RTCM少";
public static final int TYPE_LESS_B562 = 0x80; public static final int TYPE_LESS_B562 = 0x80;
public static final String TYPE_NAME_LESS_B562 = "B562少";
// warning level definition // warning level definition
public static final short LEVEL_0 = 0; //正常 public static final short LEVEL_0 = 0; //正常
public static final short LEVEL_1 = 1; //一般 public static final short LEVEL_1 = 1; //一般
public static final short LEVEL_2 = 2; //严重 public static final short LEVEL_2 = 2; //严重
@TableId(value = "id", type = IdType.AUTO)
Long id;
Integer tenantid;
Short devicetype; Short devicetype;
Short level;
Integer type; Integer type;
String typename; String typename;
Integer value; Integer value;
Short level;
} }

View File

@ -15,8 +15,6 @@ import java.util.Date;
@Data @Data
@TableName(value = "warninginfo") @TableName(value = "warninginfo")
public class WarningMsg { public class WarningMsg {
// device type definition
@TableId(value = "id", type = IdType.AUTO) @TableId(value = "id", type = IdType.AUTO)
Long id; Long id;
Integer tenantid; Integer tenantid;

View File

@ -3,9 +3,13 @@ package com.imdroid.sideslope.executor;
import com.imdroid.secapi.client.BeidouClient; import com.imdroid.secapi.client.BeidouClient;
import com.imdroid.sideslope.bd.ByteUtil; import com.imdroid.sideslope.bd.ByteUtil;
import com.imdroid.sideslope.message.D31xConfigAckMessage; import com.imdroid.sideslope.message.D31xConfigAckMessage;
import com.imdroid.sideslope.sal.Device;
import com.imdroid.sideslope.sal.DeviceService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/** /**
* @author Layton * @author Layton
* @date 2023/2/2 20:40 * @date 2023/2/2 20:40
@ -14,9 +18,15 @@ import org.springframework.stereotype.Component;
public class D31xConfigAckMessageExecutor implements Executor<D31xConfigAckMessage, Void> { public class D31xConfigAckMessageExecutor implements Executor<D31xConfigAckMessage, Void> {
@Autowired @Autowired
private BeidouClient beidouClient; private BeidouClient beidouClient;
@Resource(name = "local")
private DeviceService deviceService;
@Override @Override
public Void execute(D31xConfigAckMessage message) { public Void execute(D31xConfigAckMessage message) {
// 补齐tenantId
Device device = deviceService.findByDeviceId(message.getId());
if(device == null) return null;
message.setTenantId(device.getTenantId());
// 转发应答 // 转发应答
beidouClient.onConfigAck(message.getId(), ByteUtil.bytesToHexString(message.getSrcData())); beidouClient.onConfigAck(message.getId(), ByteUtil.bytesToHexString(message.getSrcData()));
return null; return null;

View File

@ -32,6 +32,11 @@ public class D331RtcmMessageExecutor implements Executor<D331RtcmMessage, Void>
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("receive d331 rtcm message of device:{}", message.getId()); logger.debug("receive d331 rtcm message of device:{}", message.getId());
} }
// 补齐tenantId
Device device1 = deviceService.findByDeviceId(message.getId());
if(device1 == null) return null;
message.setTenantId(device1.getTenantId());
String id = message.getId(); String id = message.getId();
byte[] forwardBytes = message.getSrcData(); byte[] forwardBytes = message.getSrcData();
List<Device> deviceList = deviceService.findByParentId(id); List<Device> deviceList = deviceService.findByParentId(id);

View File

@ -2,6 +2,8 @@ package com.imdroid.sideslope.executor;
import com.imdroid.sideslope.calc.GNSSCalcService; import com.imdroid.sideslope.calc.GNSSCalcService;
import com.imdroid.sideslope.message.D341LocationMessage; import com.imdroid.sideslope.message.D341LocationMessage;
import com.imdroid.sideslope.sal.Device;
import com.imdroid.sideslope.sal.DeviceService;
import com.imdroid.sideslope.service.GNSSDeviceLocationRecordService; import com.imdroid.sideslope.service.GNSSDeviceLocationRecordService;
import com.imdroid.sideslope.util.ThreadManager; import com.imdroid.sideslope.util.ThreadManager;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -9,6 +11,8 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/** /**
* @author Layton * @author Layton
* @date 2023/2/2 20:50 * @date 2023/2/2 20:50
@ -22,11 +26,19 @@ public class D341LocationMessageExecutor implements Executor<D341LocationMessage
private GNSSCalcService gnssCalcService; private GNSSCalcService gnssCalcService;
@Autowired @Autowired
private GNSSDeviceLocationRecordService dataPersistService; private GNSSDeviceLocationRecordService dataPersistService;
@Resource(name = "local")
private DeviceService deviceService;
@Override @Override
public Void execute(D341LocationMessage message) { public Void execute(D341LocationMessage message) {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("receive d341 location message of device:{}", message.getId()); logger.debug("receive d341 location message of device:{}", message.getId());
} }
// 补齐tenantId
Device device = deviceService.findByDeviceId(message.getId());
if(device == null) return null;
message.setTenantId(device.getTenantId());
ThreadManager.getFixedThreadPool().submit(() -> { ThreadManager.getFixedThreadPool().submit(() -> {
gnssCalcService.calcSingle(message); gnssCalcService.calcSingle(message);
dataPersistService.saveRawData(message); dataPersistService.saveRawData(message);

View File

@ -2,12 +2,15 @@ package com.imdroid.sideslope.executor;
import com.imdroid.secapi.client.BeidouClient; import com.imdroid.secapi.client.BeidouClient;
import com.imdroid.sideslope.message.D3F0SelfCheckMessage; import com.imdroid.sideslope.message.D3F0SelfCheckMessage;
import com.imdroid.sideslope.sal.DeviceService;
import com.imdroid.sideslope.sal.Device;
import com.imdroid.sideslope.service.DataPersistService; import com.imdroid.sideslope.service.DataPersistService;
import com.imdroid.sideslope.service.WarningService;
import com.imdroid.sideslope.util.ThreadManager; import com.imdroid.sideslope.util.ThreadManager;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/** /**
* @author Layton * @author Layton
* @date 2023/2/2 20:40 * @date 2023/2/2 20:40
@ -20,10 +23,16 @@ public class D3F0SelfCheckMessageExecutor implements Executor<D3F0SelfCheckMessa
@Autowired @Autowired
private BeidouClient beidouClient; private BeidouClient beidouClient;
@Resource(name = "local")
private DeviceService deviceService;
@Override @Override
public Void execute(D3F0SelfCheckMessage message) { public Void execute(D3F0SelfCheckMessage message) {
// 补齐tenantId
Device device = deviceService.findByDeviceId(message.getId());
if(device == null) return null;
message.setTenantId(device.getTenantId());
// 通知beidou服务 // 通知beidou服务
beidouClient.onDeviceActive(message.getId()); beidouClient.onDeviceActive(message.getId());
// 存储最新设备状态信息到数据库中 // 存储最新设备状态信息到数据库中

View File

@ -2,6 +2,7 @@ package com.imdroid.sideslope.executor;
import com.imdroid.secapi.client.BeidouClient; import com.imdroid.secapi.client.BeidouClient;
import com.imdroid.sideslope.message.D3F2StopIndicationMessage; import com.imdroid.sideslope.message.D3F2StopIndicationMessage;
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.WarningService; import com.imdroid.sideslope.service.WarningService;
@ -28,8 +29,14 @@ public class D3F2StopIndicationMessageExecutor implements Executor<D3F2StopIndic
@Autowired @Autowired
private BeidouClient beidouClient; private BeidouClient beidouClient;
@Override @Override
public Void execute(D3F2StopIndicationMessage message) { public Void execute(D3F2StopIndicationMessage message) {
// 补齐tenantId
Device device = deviceService.findByDeviceId(message.getId());
if(device == null) return null;
message.setTenantId(device.getTenantId());
// 储设备收发字节数统计信息 // 储设备收发字节数统计信息
ThreadManager.getFixedThreadPool().submit(() -> { ThreadManager.getFixedThreadPool().submit(() -> {
dataPersistService.saveDeviceTrxStat(message); dataPersistService.saveDeviceTrxStat(message);

View File

@ -15,6 +15,8 @@ public abstract class BaseMessage {
protected int len; protected int len;
protected int pps; protected int pps;
protected int tenantId;//消息所属的租户在executor里获取
protected byte[] srcData;//message在线程中处理需要把channel传递过来的数据拷贝出来 protected byte[] srcData;//message在线程中处理需要把channel传递过来的数据拷贝出来
public void decode(ByteBuf src) { public void decode(ByteBuf src) {

View File

@ -5,7 +5,7 @@ import io.netty.buffer.ByteBuf;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import java.sql.Timestamp; import java.util.Date;
/** /**
* 自检消息 * 自检消息
@ -22,8 +22,8 @@ public class D3F0SelfCheckMessage extends BaseMessage {
@Override @Override
public void decodeBody(ByteBuf src) { public void decodeBody(ByteBuf src) {
statusMsg.setDeviceid(getId()); statusMsg.setDeviceid(getId());
statusMsg.setCreatetime(new Timestamp(System.currentTimeMillis())); statusMsg.setCreatetime(new Date());
statusMsg.setDevicetime(new Timestamp(getPps()*1000)); statusMsg.setDevicetime(new Date(getPps()*1000));
statusMsg.setPitch(src.readFloat()); statusMsg.setPitch(src.readFloat());
statusMsg.setRoll(src.readFloat()); statusMsg.setRoll(src.readFloat());
statusMsg.setYaw(src.readFloat()); statusMsg.setYaw(src.readFloat());

View File

@ -5,7 +5,7 @@ import io.netty.buffer.ByteBuf;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import java.sql.Timestamp; import java.util.Date;
/** /**
* 停止指示消息 * 停止指示消息
@ -21,8 +21,8 @@ public class D3F2StopIndicationMessage extends BaseMessage {
@Override @Override
public void decodeBody(ByteBuf src) { public void decodeBody(ByteBuf src) {
trxMsg.setDeviceid(getId()); trxMsg.setDeviceid(getId());
trxMsg.setCreatetime(new Timestamp(System.currentTimeMillis())); trxMsg.setCreatetime(new Date());
trxMsg.setDevicetime(new Timestamp(getPps()*1000)); trxMsg.setDevicetime(new Date(getPps()*1000));
int keys = (this.len - 6) / 5; int keys = (this.len - 6) / 5;
for (int i = 0; i < keys; i++) { for (int i = 0; i < keys; i++) {
int key = src.readUnsignedByte(); int key = src.readUnsignedByte();

View File

@ -38,6 +38,7 @@ public class DbDeviceServiceImpl implements DeviceService {
return null; return null;
} }
Device device = new Device(); Device device = new Device();
device.setTenantId(gnssDevice.getTenantid());
device.setDeviceId(gnssDevice.getDeviceid()); device.setDeviceId(gnssDevice.getDeviceid());
device.setDeviceType(gnssDevice.getDevicetype()); device.setDeviceType(gnssDevice.getDevicetype());
device.setParentId(gnssDevice.getParentid()); device.setParentId(gnssDevice.getParentid());

View File

@ -22,6 +22,7 @@ public class Device {
public static final int DEVICE_ROVER = 0; public static final int DEVICE_ROVER = 0;
private String name; private String name;
private Integer tenantId;
private String deviceId; private String deviceId;

View File

@ -7,7 +7,7 @@ import com.imdroid.sideslope.message.D3F2StopIndicationMessage;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.sql.Timestamp; import java.util.Date;
/** /**
* 设备数据持久化实现 * 设备数据持久化实现
@ -35,6 +35,7 @@ public class DataPersistServiceImpl implements DataPersistService {
try { try {
// 保存到statusmsg数据表里 // 保存到statusmsg数据表里
GnssStatusMsg statusMsg = message.getStatusMsg(); GnssStatusMsg statusMsg = message.getStatusMsg();
statusMsg.setTenantid(message.getTenantId());
statusMsgMapper.insert(statusMsg); statusMsgMapper.insert(statusMsg);
//新增或更新到status数据表里 //新增或更新到status数据表里
@ -45,6 +46,7 @@ public class DataPersistServiceImpl implements DataPersistService {
new_flag = true; new_flag = true;
} }
//deviceState.setId(SequenceUtil.getSequence()); //deviceState.setId(SequenceUtil.getSequence());
deviceState.setTenantid(message.getTenantId());
deviceState.setDeviceid(message.getId()); deviceState.setDeviceid(message.getId());
deviceState.setUpdatetime(statusMsg.getCreatetime()); deviceState.setUpdatetime(statusMsg.getCreatetime());
deviceState.setRoll(statusMsg.getRoll()); deviceState.setRoll(statusMsg.getRoll());
@ -74,7 +76,9 @@ public class DataPersistServiceImpl implements DataPersistService {
public void saveDeviceTrxStat(D3F2StopIndicationMessage message) { public void saveDeviceTrxStat(D3F2StopIndicationMessage message) {
try { try {
// 添加到trxmsg里 // 添加到trxmsg里
trxMsgMapper.insert(message.getTrxMsg()); GnssTrxMsg trxMsg = message.getTrxMsg();
trxMsg.setTenantid(message.getTenantId());
trxMsgMapper.insert(trxMsg);
// 保存消息摘要 // 保存消息摘要
saveMsg(message); saveMsg(message);
@ -97,7 +101,8 @@ public class DataPersistServiceImpl implements DataPersistService {
void saveMsg(BaseMessage message){ void saveMsg(BaseMessage message){
GnssMsg gnssMsg = new GnssMsg(); GnssMsg gnssMsg = new GnssMsg();
gnssMsg.setCreatetime(new Timestamp(System.currentTimeMillis())); gnssMsg.setTenantid(message.getTenantId());
gnssMsg.setCreatetime(new Date());
gnssMsg.setDeviceid(message.getId()); gnssMsg.setDeviceid(message.getId());
gnssMsg.setMsgtype(((int)message.getHeader())&0xFFFF); gnssMsg.setMsgtype(((int)message.getHeader())&0xFFFF);
gnssMsg.setMsglen(message.getLen()); gnssMsg.setMsglen(message.getLen());

View File

@ -13,7 +13,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.sql.Timestamp; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -71,9 +71,8 @@ public class GNSSDeviceLocationRecordServiceImpl implements GNSSDeviceLocationRe
GnssDevice gnssDevice = gnssDeviceRepository.queryByDeviceId(locationRecord.getDeviceid()); GnssDevice gnssDevice = gnssDeviceRepository.queryByDeviceId(locationRecord.getDeviceid());
if(gnssDevice == null) return; if(gnssDevice == null) return;
//补充解算记录的设备信息 //补充解算记录的设备信息
long now = System.currentTimeMillis();
locationRecord.setTenantid(gnssDevice.getTenantid()); locationRecord.setTenantid(gnssDevice.getTenantid());
locationRecord.setCreatetime(new Timestamp(now)); locationRecord.setCreatetime(new Date());
locationRecord.setEnabled(true); locationRecord.setEnabled(true);
// 获取平滑参数 // 获取平滑参数
@ -174,8 +173,9 @@ public class GNSSDeviceLocationRecordServiceImpl implements GNSSDeviceLocationRe
@Override @Override
public void saveRawData(D341LocationMessage message){ public void saveRawData(D341LocationMessage message){
GnssRawData data = new GnssRawData(); GnssRawData data = new GnssRawData();
data.setTenantid(message.getTenantId());
data.setDeviceid(message.getId()); data.setDeviceid(message.getId());
data.setCreatetime(new Timestamp(System.currentTimeMillis())); data.setCreatetime(new Date());
Tilt tilt = message.getTilt(); Tilt tilt = message.getTilt();
data.setRoll(tilt.getRoll()); data.setRoll(tilt.getRoll());
data.setPitch(tilt.getPitch()); data.setPitch(tilt.getPitch());

View File

@ -50,6 +50,7 @@ public class WarningServiceImpl implements WarningService {
public void checkDeviceStatus(GnssStatusMsg statusMsg, GnssStatus curStatus){ public void checkDeviceStatus(GnssStatusMsg statusMsg, GnssStatus curStatus){
if(cfgMap.size() == 0) refreshCfg(); if(cfgMap.size() == 0) refreshCfg();
// 清除离线告警 // 清除离线告警
if(curStatus.getWarningcode() == null) curStatus.setWarningcode(0);
curStatus.setWarningcode(curStatus.getWarningcode() & ~WarningCfg.TYPE_DEVICE_OFF_LINE); curStatus.setWarningcode(curStatus.getWarningcode() & ~WarningCfg.TYPE_DEVICE_OFF_LINE);
// 检测电压和RSSI // 检测电压和RSSI

View File

@ -4,42 +4,76 @@ import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.imdroid.beidou.common.HttpResult;
import com.imdroid.beidou.entity.Tenant; import com.imdroid.beidou.entity.Tenant;
import com.imdroid.secapi.dto.*; import com.imdroid.secapi.dto.*;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;
@Controller @Controller
public class WarningController extends BasicController{ public class WarningController extends BasicController {
@Autowired @Autowired
WarningMsgMapper warningMapper; WarningMsgMapper warningMsgMapper;
@Autowired
WarningCfgMapper warningCfgMapper;
public static final Map<Integer, String> warningMap = new HashMap<>();
@PostConstruct
public static void init() {
warningMap.put(WarningCfg.TYPE_LOW_VOLTAGE, WarningCfg.TYPE_NAME_LOW_VOLTAGE);
warningMap.put(WarningCfg.TYPE_LOW_RSSI, WarningCfg.TYPE_NAME_LOW_RSSI);
warningMap.put(WarningCfg.TYPE_DEVICE_OFF_LINE, WarningCfg.TYPE_NAME_DEVICE_OFF_LINE);
warningMap.put(WarningCfg.TYPE_RX_MUCH_UNKNOWN, WarningCfg.TYPE_NAME_RX_MUCH_UNKNOWN);
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_B562, WarningCfg.TYPE_NAME_LESS_B562);
}
/**** 推送页面 *****/ /**** 推送页面 *****/
@RequestMapping("/page/warning") @RequestMapping("/page/warning")
public String warning()throws Exception { public String warning() throws Exception {
return "/page/warning"; return "/page/warning";
} }
@RequestMapping("/page/warning_cfg")
public String warningCfg() throws Exception {
return "/page/warning_cfg";
}
@RequestMapping("/page/table/warning_add")
public String warningUpdate(Model m) throws Exception {
m.addAttribute("warn_map", warningMap);
return "/page/table/warning_add";
}
/**** 推送数据 *****/ /**** 推送数据 *****/
@RequestMapping("/warning/list") @RequestMapping("/warning/msg")
@ResponseBody @ResponseBody
public JSONObject listMsg(HttpSession session, int page, int limit, String searchParams) { public JSONObject listMsg(HttpSession session, int page, int limit, String searchParams) {
Page<WarningMsg> pageable = new Page<>(page, limit); Page<WarningMsg> pageable = new Page<>(page, limit);
QueryWrapper<WarningMsg> queryWrapper = new QueryWrapper<>(); QueryWrapper<WarningMsg> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc("createtime"); queryWrapper.orderByDesc("createtime");
Integer tenantId = getTenantId(session); Integer tenantId = getTenantId(session);
if(tenantId != null && tenantId != Tenant.SAAS_PROVIDER_ID) { if (tenantId != null && tenantId != Tenant.SAAS_PROVIDER_ID) {
queryWrapper.eq("tenantid", tenantId); queryWrapper.eq("tenantid", tenantId);
} }
// 条件查询 // 条件查询
if(searchParams != null) { if (searchParams != null) {
JSONObject search = (JSONObject) JSONObject.parse(searchParams); JSONObject search = (JSONObject) JSONObject.parse(searchParams);
//设备号 //设备号
String deviceid = search.getString("deviceid"); String deviceid = search.getString("deviceid");
@ -53,11 +87,11 @@ public class WarningController extends BasicController{
} }
String q_end = search.getString("q_end"); String q_end = search.getString("q_end");
if (!StringUtils.isEmpty(q_end)) { if (!StringUtils.isEmpty(q_end)) {
queryWrapper.le("createtime", q_end+" 23:59:59"); queryWrapper.le("createtime", q_end + " 23:59:59");
} }
} }
IPage<WarningMsg> cs = warningMapper.selectPage(pageable, queryWrapper); IPage<WarningMsg> cs = warningMsgMapper.selectPage(pageable, queryWrapper);
JSONObject jsonObject = new JSONObject(); JSONObject jsonObject = new JSONObject();
jsonObject.put("code", 0); jsonObject.put("code", 0);
@ -67,4 +101,42 @@ public class WarningController extends BasicController{
return jsonObject; return jsonObject;
} }
@RequestMapping("/warning/cfg")
@ResponseBody
public JSONObject listCfg(int page, int limit, String searchParams) {
Page<WarningCfg> pageable = new Page<>(page, limit);
IPage<WarningCfg> cs = warningCfgMapper.selectPage(pageable, null);
JSONObject jsonObject = new JSONObject();
jsonObject.put("code", 0);
jsonObject.put("msg", "");
jsonObject.put("count", cs.getTotal());
jsonObject.put("data", cs.getRecords());
return jsonObject;
}
@PostMapping("/warning/update")
@ResponseBody
public String update(@RequestBody JSONObject object) throws Exception {
// 从请求参数中创建对象
WarningCfg cfg = JSONObject.toJavaObject(object, WarningCfg.class);
cfg.setTypename(warningMap.get(cfg.getType()));
// 检测该对象是否已存在
int num = 0;
QueryWrapper<WarningCfg> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("devicetype", cfg.getDevicetype());
queryWrapper.eq("type", cfg.getType());
if (warningCfgMapper.selectCount(queryWrapper) == 0) {
num = warningCfgMapper.insert(cfg);
} else num = warningCfgMapper.update(cfg, queryWrapper);
if (num == 0) {
return HttpResult.failed();
} else {
return HttpResult.ok();
}
}
} }

View File

@ -73,20 +73,18 @@ public class ServiceEnvInit implements ApplicationRunner {
private void createDefaultWarningCfg() { private void createDefaultWarningCfg() {
WarningCfg warningCfg = new WarningCfg(); WarningCfg warningCfg = new WarningCfg();
warningCfg.setTenantid(Tenant.SAAS_PROVIDER_ID);
warningCfg.setDevicetype(WarningCfg.TYPE_GNSS); warningCfg.setDevicetype(WarningCfg.TYPE_GNSS);
warningCfg.setLevel(WarningCfg.LEVEL_2); warningCfg.setLevel(WarningCfg.LEVEL_2);
warningCfg.setType(WarningCfg.TYPE_LOW_VOLTAGE); warningCfg.setType(WarningCfg.TYPE_LOW_VOLTAGE);
warningCfg.setTypename("低电压"); warningCfg.setTypename(WarningCfg.TYPE_NAME_LOW_VOLTAGE);
warningCfg.setValue(9500); warningCfg.setValue(9500);
warningCfgMapper.insert(warningCfg); warningCfgMapper.insert(warningCfg);
warningCfg = new WarningCfg(); warningCfg = new WarningCfg();
warningCfg.setTenantid(Tenant.SAAS_PROVIDER_ID);
warningCfg.setDevicetype(WarningCfg.TYPE_GNSS); warningCfg.setDevicetype(WarningCfg.TYPE_GNSS);
warningCfg.setLevel(WarningCfg.LEVEL_2); warningCfg.setLevel(WarningCfg.LEVEL_2);
warningCfg.setType(WarningCfg.TYPE_DEVICE_OFF_LINE); warningCfg.setType(WarningCfg.TYPE_DEVICE_OFF_LINE);
warningCfg.setTypename("离线"); warningCfg.setTypename(WarningCfg.TYPE_NAME_DEVICE_OFF_LINE);
warningCfg.setValue(0); warningCfg.setValue(0);
warningCfgMapper.insert(warningCfg); warningCfgMapper.insert(warningCfg);
} }

View File

@ -248,12 +248,10 @@ CREATE TABLE IF NOT EXISTS `warninginfo` (
0x100x20,使0x40,d331少于d341; 0x80b562比例少 0x100x20,使0x40,d331少于d341; 0x80b562比例少
*/ */
CREATE TABLE IF NOT EXISTS `warningcfg` ( CREATE TABLE IF NOT EXISTS `warningcfg` (
`id` bigint AUTO_INCREMENT, `devicetype` smallint NOT NULL,
`tenantid` int NOT NULL, `type` int NOT NULL,
`devicetype` smallint DEFAULT NULL,
`level` smallint DEFAULT 0, `level` smallint DEFAULT 0,
`type` int DEFAULT NULL,
`typename` varchar(50) NOT NULL, `typename` varchar(50) NOT NULL,
`value` int DEFAULT NULL, `value` int NOT NULL,
PRIMARY KEY (`id`) PRIMARY KEY (`devicetype`,`type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

View File

@ -23,9 +23,23 @@
}, },
{ {
"title": "告警管理", "title": "告警管理",
"href": "page/warning", "href": "",
"icon": "fa fa-bell-o", "icon": "fa fa-bell-o",
"target": "_self" "target": "",
"child": [
{
"title": "告警消息",
"href": "page/warning",
"icon": "fa fa-minus",
"target": "_self"
},
{
"title": "告警参数",
"href": "page/warning_cfg",
"icon": "fa fa-minus",
"target": "_self"
}
]
}, },
{ {
"title": "北斗", "title": "北斗",

View File

@ -1,28 +0,0 @@
{
"code": 0,
"msg": "",
"count": 1000,
"data": [
{
"rp_time": "2023-01-01 12:23:56",
"device_id": "2307001",
"device_type": "北斗",
"level": "一般",
"content": "位移加速"
},
{
"rp_time": "2023-02-01 12:23:56",
"device_id": "1602301001",
"device_type": "测斜仪",
"level": "一般",
"content": "位移加速"
},
{
"rp_time": "2023-03-01 12:23:56",
"device_id": "861380138000",
"device_type": "光伏DTU",
"level": "严重",
"content": "低电压"
}
]
}

View File

@ -150,7 +150,7 @@
{field: 'filter_hour', title: '平滑窗口(小时)'}, {field: 'filter_hour', title: '平滑窗口(小时)'},
{field: 'xy_threshold', title: '水平异常门限(cm)'}, {field: 'xy_threshold', title: '水平异常门限(cm)'},
{field: 'z_threshold', title: '垂直异常门限(cm)'}, {field: 'z_threshold', title: '垂直异常门限(cm)'},
{field: 'auto_filter', title: '自适应平滑'}, {field: 'auto_filter', title: '自适应平滑', templet: '#autoFilterTrans'},
{field: 'filter_max_hour', title: '最大平滑窗口'}, {field: 'filter_max_hour', title: '最大平滑窗口'},
{field: 'shock', title: 'shock'}, {field: 'shock', title: 'shock'},
{field: 'device_num', title: '关联设备数'}, {field: 'device_num', title: '关联设备数'},
@ -347,6 +347,14 @@
} }
</script> </script>
<script type="text/html" id="autoFilterTrans">
{{# if(d.auto_filter == 1){ }}
<span>启用</span>
{{# } else { }}
<span>禁用</span>
{{# } }}
</script>
<script type="text/html" id="modeTrans"> <script type="text/html" id="modeTrans">
{{# if(d.power_mode == 0){ }} {{# if(d.power_mode == 0){ }}
<span>低功耗</span> <span>低功耗</span>

View File

@ -10,40 +10,40 @@
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label required">平滑窗口(小时)</label> <label class="layui-form-label required">平滑窗口(小时)</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input type="number" name="filter_hour" id="filter_hour" lay-verify="required" lay-reqtext="不能为空" placeholder="请输入长周期" value="25" class="layui-input"> <input type="number" name="filter_hour" id="filter_hour" lay-verify="required" lay-reqtext="不能为空" class="layui-input">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label required">水平异常门限(cm)</label> <label class="layui-form-label required">水平异常门限(cm)</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input type="number" name="xy_threshold" id="xy_threshold" lay-verify="required" lay-reqtext="不能为空" placeholder="请输入短周期" value="4" class="layui-input"> <input type="number" name="xy_threshold" id="xy_threshold" lay-verify="required" lay-reqtext="不能为空" class="layui-input">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label required">垂直异常门限(cm)</label> <label class="layui-form-label required">垂直异常门限(cm)</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input type="number" name="z_threshold" id="z_threshold" lay-verify="required" lay-reqtext="不能为空" placeholder="请输入短周期" value="4" class="layui-input"> <input type="number" name="z_threshold" id="z_threshold" lay-verify="required" lay-reqtext="不能为空" class="layui-input">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label required">自适应平滑</label> <label class="layui-form-label">自适应平滑</label>
<div class="layui-input-inline"> <div class="layui-input-inline">
<select name="auto_filter" id="auto_filter" lay-filter="type1"> <select name="auto_filter" id="auto_filter" lay-filter="type1">
<option value="0">禁用</option> <option value="false">禁用</option>
<option value="1">启用</option> <option value="true">启用</option>
</select> </select>
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">最大平滑窗口(小时)</label> <label class="layui-form-label">最大平滑窗口(小时)</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input type="number" name="filter_max_hour" id="filter_max_hour" lay-verify="required" lay-reqtext="不能为空" placeholder="请输入长周期" value="25" class="layui-input"> <input type="number" name="filter_max_hour" id="filter_max_hour" class="layui-input">
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">shock</label> <label class="layui-form-label">shock</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input type="number" name="shock" id="shock" lay-verify="required" lay-reqtext="不能为空" placeholder="请输入Shock值" value="1.5" class="layui-input"> <input type="number" name="shock" id="shock" class="layui-input">
</div> </div>
</div> </div>

View File

@ -0,0 +1,85 @@
<div class="layuimini-main">
<div class="layui-form layuimini-form">
<div class="layui-form-item">
<label class="layui-form-label required">设备类型</label>
<div class="layui-input-inline">
<select name="devicetype" id="devicetype" lay-verify="required" lay-search="">
<option value="1">GNSS</option>
<option value="2">光伏DTU</option>
<option value="3">测斜仪</option>
</select>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label required">告警类型</label>
<div class="layui-input-inline">
</select>
<select name="type" id="type" lay-verify="required" lay-search="">
<option th:each="item : ${warn_map}" th:text="${item.value}" th:value="${item.key}"></option>
</select>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label required">告警门限</label>
<div class="layui-input-block">
<input type="number" name="value" id="value" placeholder="请输入门限值" value="" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label required">告警等级</label>
<div class="layui-input-inline">
<select name="level" id="level" lay-verify="required" lay-search="">
<option value="1">一般</option>
<option value="2">严重</option>
</select>
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn layui-btn-normal" lay-submit lay-filter="saveBtn">确认保存</button>
</div>
</div>
</div>
</div>
<script>
layui.use(['form', 'table'], function () {
var form = layui.form,
layer = layui.layer,
table = layui.table,
$ = layui.$;
/**
* 初始化表单,要加上,不然刷新部分组件可能会不加载
*/
setTimeout(function(){
//console.log("timeout!");
form.render();
},200)
// 当前弹出层防止ID被覆盖
var parentIndex = layer.index;
//监听提交
form.on('submit(saveBtn)', function (data) {
console.log(JSON.stringify(data.field));
$.ajax({
type:"POST",
url:"/warning/update",
contentType: "application/json;charset=UTF-8",
data: JSON.stringify(data.field),
success: function (result) {
parent.onCfgUpdated();
},
error: function () {
console.log("ajax error");
}
});
layer.close(parentIndex);
return false;
});
});
</script>

View File

@ -59,14 +59,14 @@
table.render({ table.render({
elem: '#currentTableId', elem: '#currentTableId',
url: 'warning/list', url: '/warning/msg',
defaultToolbar: ['filter', 'exports', 'print', { defaultToolbar: ['filter', 'exports', 'print', {
title: '提示', title: '提示',
layEvent: 'LAYTABLE_TIPS', layEvent: 'LAYTABLE_TIPS',
icon: 'layui-icon-tips' icon: 'layui-icon-tips'
}], }],
cols: [[ cols: [[
{field: 'createtime', title: '时间', sort: true}, {field: 'createtime', title: '上报时间', templet: "<div>{{layui.util.toDateString(d.createtime, 'yyyy-MM-dd HH:mm:ss')}}</div>"},
{field: 'deviceid', title: '设备号'}, {field: 'deviceid', title: '设备号'},
{field: 'devicetype', title: '设备类型'}, {field: 'devicetype', title: '设备类型'},
{field: 'level', title: '告警级别'}, {field: 'level', title: '告警级别'},

View File

@ -0,0 +1,127 @@
<div class="layuimini-container layuimini-page-anim">
<div class="layuimini-main">
<table class="layui-hide" id="currentTableId" lay-filter="currentTableFilter"></table>
<script type="text/html" id="currentTableBar">
<a class="layui-btn layui-btn-normal layui-btn-xs data-count-edit" lay-event="edit">编辑</a>
<a class="layui-btn layui-btn-xs layui-btn-danger data-count-delete" lay-event="delete">删除</a>
</script>
<script type="text/html" id="toolbarTop">
<div class="layui-btn-container">
<button class="layui-btn layui-btn-normal layui-btn-sm data-add-btn" lay-event="add"> 添加 </button>
</div>
</script>
</div>
</div>
<script th:inline="none">
layui.use(['form', 'table','miniPage','element'], function () {
var $ = layui.jquery,
form = layui.form,
table = layui.table,
miniPage = layui.miniPage;
/**
* 初始化表单,要加上,不然刷新部分组件可能会不加载
*/
form.render();
table.render({
elem: '#currentTableId',
url: '/warning/cfg',
toolbar: '#toolbarTop',
cols: [[
{field: 'devicetype', title: '设备类型'},
{field: 'type', title: '告警类型'},
{field: 'typename', title: '类型描述'},
{field: 'value', title: '告警门限'},
{field: 'level', title: '告警级别'},
{title: '操作', toolbar: '#currentTableBar', align: "center", minWidth: 120}
]],
limits: [10, 15, 20, 25, 50, 100],
limit: 15,
page: true,
skin: 'line'
});
/**
* toolbar事件监听
*/
table.on('toolbar(currentTableFilter)', function (obj) {
if (obj.event === 'add') { // 监听添加操作
var content = miniPage.getHrefContent('page/table/warning_add');
var openWH = miniPage.getOpenWidthHeight();
var index = layer.open({
title: '新增告警类型',
type: 1,
shade: 0.2,
maxmin:true,
shadeClose: true,
area: [openWH[0] + 'px', openWH[1] + 'px'],
offset: [openWH[2] + 'px', openWH[3] + 'px'],
content: content,
});
$(window).on("resize", function () {
layer.full(index);
});
}
});
table.on('tool(currentTableFilter)', function (obj) {
var data = obj.data;
if (obj.event === 'edit') {
var content = miniPage.getHrefContent('page/table/warning_add');
var openWH = miniPage.getOpenWidthHeight();
var index = layer.open({
title: '修改告警参数',
type: 1,
shade: 0.2,
maxmin:true,
shadeClose: true,
area: [openWH[0] + 'px', openWH[1] + 'px'],
offset: [openWH[2] + 'px', openWH[3] + 'px'],
content: content,
success: function (layero, index) {
var device_type = layero.find('#devicetype');
device_type.val(data.devicetype);
device_type.attr('readonly',true);
var warning_type = layero.find('#type');
warning_type.val(data.type);
warning_type.attr('readonly',true);
layero.find('#value').val(data.value);
layero.find('#level').val(data.level);
}
});
$(window).on("resize", function () {
layer.full(index);
});
return false;
} else if (obj.event === 'delete') {
layer.confirm('确定删除?', function(index){
$.ajax({
type:"POST",
url:"/warning/delete",
data:{
'del_id':data.deviceid
},
success: function (data) {
//data是cotroller相应处理函数的返回值
table.reload('currentTableId');
},
error: function () {
console.log("ajax error");
}
});
layer.close(index);
});
}
});
});
function onCfgUpdated(){
layui.table.reload('currentTableId');
}
</script>