feat(device): 实现设备监控报警功能

- 添加设备监控报警服务和数据访问接口- 实现阈值检查逻辑,支持模拟量和开关量报警
- 新增报警数据处理,包括存储到数据库和Redis缓存
- 实现告警信息表(tb_iron_warninfo)的创建和更新逻辑
- 添加设备节点报警状态跟踪机制
- 完善数据采集时间字段,替换固定值为实际时间
- 增加A枪和B枪工作位状态判断逻辑- 优化设备ID和PLC名称等字段的获取逻辑
-修复除尘器设备不参与报警检查的逻辑
- 添加ConcurrentHashMap用于线程安全的报警状态管理
dev
wangyan 2025-11-12 16:47:29 +08:00
parent 4c601b846c
commit 8ea3c56abd
7 changed files with 667 additions and 8 deletions

View File

@ -5,7 +5,9 @@ import com.xxl.job.core.context.XxlJobHelper;
import com.zcloud.entity.PageData;
import com.zcloud.mapper.datasource.tbIron.TbIronPlcMapper;
import com.zcloud.mapper.dsno2.target.MesDeviceMonitoringMapper;
import com.zcloud.service.deviceMonitoringSrevice.DeviceMonitoringAlarmSrevice;
import com.zcloud.util.*;
import com.zcloud.mapper.datasource.tbIron.TbIronWarnInfoDao;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
@ -13,6 +15,7 @@ import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
@ -24,9 +27,18 @@ public class AppPosiDeviceController {
@Resource
private MesDeviceMonitoringMapper mesDeviceMonitoringMapper;
@Resource
private DeviceMonitoringAlarmSrevice deviceMonitoringAlarmSrevice;
@Resource
private RedisUtil redisUtil;
@Resource
private TbIronWarnInfoDao tbIronWarnInfoDao;
// 用于跟踪设备节点的报警状态
private final Map<String, PageData> alarmStatusMap = new ConcurrentHashMap<>();
@PostMapping("/test1")
public R test1(@RequestBody HashMap<String, String> parma) throws Exception {
@ -172,7 +184,10 @@ public class AppPosiDeviceController {
String currentValue = parma.get(bitNo);
// 添加到数据列表
dataList.add(saveData(currentValue, equipmentId, targetAllList, processingBatchId, processingTime));
Map<String, Object> data = saveData(currentValue, equipmentId, targetAllList, processingBatchId, processingTime);
// 检查阈值是否超出范围
checkThreshold(data);
dataList.add(data);
}
}
}
@ -183,6 +198,9 @@ public class AppPosiDeviceController {
// 将物联网数据存入Redis缓存
redisUtil.set("WMK_DATA_LIST", JSONObject.toJSONString(dataList));
XxlJobHelper.log("成功保存{}条物联网模块数据到本地数据库", dataList.size());
// 处理报警数据
processAlarmData(dataList);
}
}
@ -198,8 +216,7 @@ public class AppPosiDeviceController {
data.put("PROCESSING_BATCH_ID", processingBatchId);
data.put("INSERT_TIME", DateUtil.date2Str(new Date()));
data.put("WARNING", 0); // 是否告警 要完善相关告警逻辑进行判断
data.put("GATHER_TIME", 5);
data.put("PLC_NAME", "");
data.put("GATHER_TIME", DateUtil.date2Str(new Date()));
data.put("OVERVIEW_OF_ALERTS", "");
data.put("EQUIPMENT_ID", EQUIPMENT_ID);
// 每个设备只有一个监测数据阈值,也就是一氧化碳浓度
@ -207,7 +224,9 @@ public class AppPosiDeviceController {
PageData pageData = collect.get(0);
data.put("TARGET_NAME", pageData.getString("TARGET_NAME"));
data.put("IPCDEVICE_ID", pageData.getString("IPCDEVICE_ID"));
data.put("DEVICE_ID", pageData.getString("DEVICE_ID"));
data.put("PLC_ID", pageData.getString("PLC_ID"));
data.put("PLC_NAME", pageData.getString("PLC_NAME"));
data.put("TARGET_TYPE", pageData.getString("TARGET_TYPE"));
data.put("TARGET_PLACE", pageData.getString("TARGET_PLACE"));
data.put("TARGET_UNIT", pageData.getString("TARGET_UNIT"));
@ -226,7 +245,9 @@ public class AppPosiDeviceController {
data.put("REPORT_ID", pageData.getString("REPORT_ID"));
} else {
data.put("IPCDEVICE_ID", "");
data.put("DEVICE_ID", "");
data.put("PLC_ID", "");
data.put("PLC_NAME", "");
data.put("TARGET_TYPE", "");
data.put("TARGET_PLACE", "");
data.put("TARGET_UNIT", "");
@ -246,6 +267,207 @@ public class AppPosiDeviceController {
}
return data;
}
/**
*
* @param data
*/
private void checkThreshold(Map<String, Object> data) {
try {
String currentValueStr = String.valueOf(data.get("CURRENT_VALUE"));
String thresholdUpLimitStr = (String) data.get("THRESHOLD_UP_LIMIT");
String thresholdUpUpLimitStr = (String) data.get("THRESHOLD_UP_UP_LIMIT");
String thresholdDownLimitStr = (String) data.get("THRESHOLD_DOWN_LIMIT");
String thresholdDownDownLimitStr = (String) data.get("THRESHOLD_DOWN_DOWN_LIMIT");
if (currentValueStr == null || "null".equals(currentValueStr)) {
return;
}
double currentValue = Double.parseDouble(currentValueStr);
// 检查高高报
if (thresholdUpUpLimitStr != null && !"".equals(thresholdUpUpLimitStr) && !"null".equals(thresholdUpUpLimitStr)) {
double thresholdUpUpLimit = Double.parseDouble(thresholdUpUpLimitStr);
if (currentValue >= thresholdUpUpLimit) {
data.put("WARNING", 1);
data.put("OVERVIEW_OF_ALERTS", "高高报警");
return;
}
}
// 检查高报
if (thresholdUpLimitStr != null && !"".equals(thresholdUpLimitStr) && !"null".equals(thresholdUpLimitStr)) {
double thresholdUpLimit = Double.parseDouble(thresholdUpLimitStr);
if (currentValue >= thresholdUpLimit) {
data.put("WARNING", 1);
data.put("OVERVIEW_OF_ALERTS", "高报警");
return;
}
}
// 检查低报
if (thresholdDownLimitStr != null && !"".equals(thresholdDownLimitStr) && !"null".equals(thresholdDownLimitStr)) {
double thresholdDownLimit = Double.parseDouble(thresholdDownLimitStr);
if (currentValue >= thresholdDownLimit) {
data.put("WARNING", 1);
data.put("OVERVIEW_OF_ALERTS", "低报警");
return;
}
}
// 检查低低报
if (thresholdDownDownLimitStr != null && !"".equals(thresholdDownDownLimitStr) && !"null".equals(thresholdDownDownLimitStr)) {
double thresholdDownDownLimit = Double.parseDouble(thresholdDownDownLimitStr);
if (currentValue >= thresholdDownDownLimit) {
data.put("WARNING", 1);
data.put("OVERVIEW_OF_ALERTS", "低低报警");
return;
}
}
} catch (Exception e) {
XxlJobHelper.log("检查阈值时发生异常: {}", e.getMessage());
}
}
/**
*
* @param mesSaveList
*/
private void processAlarmData(List<Map<String, Object>> mesSaveList) {
ArrayList<PageData> alarmLogArrayList = new ArrayList<>();
ArrayList<PageData> activeAlarms = new ArrayList<>();
for (Map<String, Object> item : mesSaveList) {
// 检查是否有报警且是模拟量
Object warningObj = item.get("WARNING");
if (warningObj != null && "1".equals(String.valueOf(warningObj))) {
// 有告警 且是模拟量
PageData itemPageData = new PageData();
itemPageData.put("ALARM_MONITORING_ID", UuidUtil.get32UUID());
itemPageData.put("PLC_NAME", item.get("PLC_NAME"));
itemPageData.put("PLC_ID", item.get("PLC_ID"));
itemPageData.put("DEVICE_ID", item.get("DEVICE_ID"));
itemPageData.put("EQUIPMENT_ID", item.get("EQUIPMENT_ID"));
itemPageData.put("CURRENT_VALUE", item.get("CURRENT_VALUE"));
itemPageData.put("THRESHOLD_UP_LIMIT", item.get("THRESHOLD_UP_LIMIT"));
itemPageData.put("THRESHOLD_UP_UP_LIMIT", item.get("THRESHOLD_UP_UP_LIMIT"));
itemPageData.put("THRESHOLD_DOWN_LIMIT", item.get("THRESHOLD_DOWN_LIMIT"));
itemPageData.put("THRESHOLD_DOWN_DOWN_LIMIT", item.get("THRESHOLD_DOWN_DOWN_LIMIT"));
itemPageData.put("GATHER_TIME", item.get("GATHER_TIME"));
itemPageData.put("RANGE_UP", item.get("RANGE_UP"));
itemPageData.put("RANGE_DOWN", item.get("RANGE_DOWN"));
itemPageData.put("OVERVIEW_OF_ALERTS", item.get("OVERVIEW_OF_ALERTS"));
itemPageData.put("CORPINFO_ID", item.get("CORPINFO_ID"));
itemPageData.put("OPERATTIME", DateUtil.date2Str(new Date()));
itemPageData.put("CREATTIME", DateUtil.date2Str(new Date()));
alarmLogArrayList.add(itemPageData);
// 添加到活跃报警列表用于处理warninfo表
activeAlarms.add(itemPageData);
}
}
// 把报警的数据转存到数据库里
if (!alarmLogArrayList.isEmpty()) {
deviceMonitoringAlarmSrevice.saveBatch(alarmLogArrayList);
XxlJobHelper.log("成功保存{}条报警数据到报警表", alarmLogArrayList.size());
}
// 将报警数据存入Redis
if (!activeAlarms.isEmpty()) {
redisUtil.set("WMK_ALARM_DATA_LIST", JSONObject.toJSONString(activeAlarms));
XxlJobHelper.log("成功将{}条报警数据存入Redis", activeAlarms.size());
}
// 处理告警信息表(tb_iron_warninfo)
processWarnInfo(activeAlarms);
}
/**
* (tb_iron_warninfo)
* @param activeAlarms
*/
private void processWarnInfo(ArrayList<PageData> activeAlarms) {
// 获取当前时间
String currentTime = DateUtil.date2Str(new Date());
// 处理新产生的报警
for (PageData alarm : activeAlarms) {
String key = alarm.getString("EQUIPMENT_ID") + "_" + alarm.getString("PLC_ID") + "_" + alarm.getString("PLC_NAME");
// 检查该监测点是否已有报警记录
if (!alarmStatusMap.containsKey(key)) {
// 新报警,创建告警信息
PageData warnInfo = new PageData();
warnInfo.put("WARN_ID", UuidUtil.get32UUID());
warnInfo.put("WARN_STATUS", "0"); // 0表示未消警
warnInfo.put("WARN_ORG", "山西新泰钢铁有限公司");
if ("低低报警".equals(alarm.get("OVERVIEW_OF_ALERTS")) || "低报警".equals(alarm.get("OVERVIEW_OF_ALERTS"))){
warnInfo.put("WARN_RANK", "3");
}else if ("高报警".equals(alarm.get("OVERVIEW_OF_ALERTS"))){
warnInfo.put("WARN_RANK", "2");
}else if ("高高报警".equals(alarm.get("OVERVIEW_OF_ALERTS"))){
warnInfo.put("WARN_RANK", "1");
}
warnInfo.put("MESSAGE", "设备名称:"+ alarm.get("DEVICE_ID")+",监测节点:"+ alarm.get("PLC_NAME")+",报警内容:"+ alarm.get("OVERVIEW_OF_ALERTS"));
warnInfo.put("START_TIME", currentTime); // 预警开始时间
warnInfo.put("CORPINFO_ID", alarm.get("CORPINFO_ID"));
warnInfo.put("CREATTIME", currentTime);
warnInfo.put("OPERATTIME", currentTime);
warnInfo.put("ISDELETE", "0");
warnInfo.put("FEED_BACK", "1");
// 保存到数据库
tbIronWarnInfoDao.saveWarnInfo(warnInfo);
// 保存到alarmStatusMap中用于跟踪状态
alarmStatusMap.put(key, warnInfo);
XxlJobHelper.log("创建新的告警信息: 设备ID={}, PLC_ID={}, 报警内容={}",
alarm.get("EQUIPMENT_ID"), alarm.get("PLC_ID"), alarm.get("OVERVIEW_OF_ALERTS"));
} else {
// 已存在报警,更新当前值和时间
PageData existingWarn = alarmStatusMap.get(key);
existingWarn.put("MESSAGE", "设备名称:"+ alarm.get("DEVICE_ID")+",监测节点:"+ alarm.get("PLC_NAME")+",报警内容:"+ alarm.get("OVERVIEW_OF_ALERTS"));
existingWarn.put("OPERATTIME", currentTime);
alarmStatusMap.put(key, existingWarn);
}
}
// 检查是否有报警恢复的节点
Set<String> activeAlarmKeys = new HashSet<>();
for (PageData alarm : activeAlarms) {
String key = alarm.getString("EQUIPMENT_ID") + "_" + alarm.getString("PLC_ID") + "_" + alarm.getString("PLC_NAME");
activeAlarmKeys.add(key);
}
// 检查之前报警但现在不报警的节点
Iterator<Map.Entry<String, PageData>> iterator = alarmStatusMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, PageData> entry = iterator.next();
String key = entry.getKey();
PageData warnInfo = entry.getValue();
if (!activeAlarmKeys.contains(key)) {
// 该节点之前报警,但现在不报警了,需要更新状态为已消警
warnInfo.put("WARN_STATUS", "1"); // 1表示已消警
warnInfo.put("END_TIME", currentTime); // 预警结束时间
warnInfo.put("OPERATTIME", currentTime);
// 更新数据库中的记录
tbIronWarnInfoDao.updateWarnInfo(warnInfo);
XxlJobHelper.log("更新告警信息为已消警: 设备ID={}, PLC_ID={}, 报警内容={}",
warnInfo.get("EQUIPMENT_ID"), warnInfo.get("PLC_ID"), warnInfo.get("OVERVIEW_OF_ALERTS"));
// 从跟踪map中移除
iterator.remove();
}
}
}
// 参数示例
// {
// "td1": "node0101", -》设备的CO浓度
@ -267,4 +489,4 @@ public class AppPosiDeviceController {
// "display area": "1#高炉中控室", -》安装地点
// "host id": "T001-T002" -》
// }
}
}

View File

@ -0,0 +1,28 @@
package com.zcloud.mapper.datasource.tbIron;
import com.zcloud.entity.Page;
import com.zcloud.entity.PageData;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface TbIronWarnInfoDao {
List<PageData> listPage(Page page);
PageData getOneFeedBackByWarnId(PageData page);
/**
*
* @param pageData
*/
void saveWarnInfo(PageData pageData);
/**
*
* @param pageData
*/
void updateWarnInfo(PageData pageData);
}

View File

@ -9,15 +9,18 @@ import com.zcloud.mapper.datasource.tbIron.TbIronPlcMapper;
import com.zcloud.mapper.dsno2.monitoring.MesDataMapper;
import com.zcloud.mapper.dsno2.monitoring2.MesDataMapper2;
import com.zcloud.mapper.dsno2.target.MesDeviceMonitoringMapper;
import com.zcloud.service.deviceMonitoringSrevice.DeviceMonitoringAlarmSrevice;
import com.zcloud.util.DateUtil;
import com.zcloud.util.RedisUtil;
import com.zcloud.util.UuidUtil;
import com.zcloud.mapper.datasource.tbIron.TbIronWarnInfoDao;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
import java.util.concurrent.ConcurrentHashMap;
/**
* MES
@ -39,9 +42,18 @@ public class MesDataScheduled extends IJobHandler {
@Resource
private MesDeviceMonitoringMapper mesDeviceMonitoringMapper;
@Resource
private DeviceMonitoringAlarmSrevice deviceMonitoringAlarmSrevice;
@Resource
private RedisUtil redisUtil;
@Resource
private TbIronWarnInfoDao tbIronWarnInfoDao;
// 用于跟踪设备节点的报警状态
private final Map<String, PageData> alarmStatusMap = new ConcurrentHashMap<>();
@Override
@XxlJob(value = "mesDataJob")
@ -182,6 +194,12 @@ public class MesDataScheduled extends IJobHandler {
ArrayList<Map<String, Object>> mesSaveList = new ArrayList<>();
for (Map<String, Object> map : mesDataList) {
Set<String> keySet = map.keySet();
// 获取A枪和B枪的工作位状态
Object aGunWorkPos1 = map.get("A枪工作位_1");
Object bGunWorkPos1 = map.get("B枪工作位_1");
Object aGunWorkPos2 = map.get("A枪工作位_2");
Object bGunWorkPos2 = map.get("B枪工作位_2");
for (String key : keySet) {
HashMap<String, Object> mesData = new HashMap<>();
mesData.put("MONITORING_ID", UuidUtil.get32UUID());
@ -191,7 +209,7 @@ public class MesDataScheduled extends IJobHandler {
mesData.put("PROCESSING_BATCH_ID", processingBatchId);
mesData.put("INSERT_TIME", DateUtil.date2Str(new Date()));
mesData.put("WARNING", 0); // 是否告警 要完善相关告警逻辑进行判断
mesData.put("GATHER_TIME", 5);
mesData.put("GATHER_TIME", DateUtil.date2Str(new Date()));
mesData.put("OVERVIEW_OF_ALERTS", "");
// 下面是在已经填报的
String[] parts = key.split("_", 2); // split("_", 2) 限制分割为2部分
@ -208,10 +226,48 @@ public class MesDataScheduled extends IJobHandler {
collect = jll2TargetList.stream().filter(item -> item.getString("TARGET_NAME").equals(key)).collect(Collectors.toList());
} else if (suffix.equals("A1") || suffix.equals("B1")) {
mesData.put("EQUIPMENT_ID", "21a32f0f65a41f2949ac832ac39714f0");
collect = zl1TargetList.stream().filter(item -> item.getString("TARGET_NAME").equals(key)).collect(Collectors.toList());
// 根据枪的工作位状态决定匹配规则
if ("A1".equals(suffix)) {
// 当处理A1数据时
if (aGunWorkPos1 != null && "0".equals(aGunWorkPos1.toString())) {
// A枪工作位为0时正常匹配A1数据
collect = zl1TargetList.stream().filter(item -> item.getString("TARGET_NAME").equals(key)).collect(Collectors.toList());
} else if (bGunWorkPos1 != null && "0".equals(bGunWorkPos1.toString())) {
// B枪工作位为0时用A1的阈值匹配B1数据
collect = zl1TargetList.stream().filter(item -> item.getString("TARGET_NAME").equals(key.replace("_B1", "_A1"))).collect(Collectors.toList());
}
} else if ("B1".equals(suffix)) {
// 当处理B1数据时
if (bGunWorkPos1 != null && "0".equals(bGunWorkPos1.toString())) {
// B枪工作位为0时用A1的阈值匹配B1数据
collect = zl1TargetList.stream().filter(item -> item.getString("TARGET_NAME").equals(key.replace("_B1", "_A1"))).collect(Collectors.toList());
} else if (aGunWorkPos1 != null && "0".equals(aGunWorkPos1.toString())) {
// A枪工作位为0时正常匹配B1数据
collect = zl1TargetList.stream().filter(item -> item.getString("TARGET_NAME").equals(key)).collect(Collectors.toList());
}
}
} else if (suffix.equals("A2") || suffix.equals("B2")) {
mesData.put("EQUIPMENT_ID", "2c83b99df54e80a674be5657b11db55c");
collect = zl2TargetList.stream().filter(item -> item.getString("TARGET_NAME").equals(key)).collect(Collectors.toList());
// 根据枪的工作位状态决定匹配规则
if ("A2".equals(suffix)) {
// 当处理A2数据时
if (aGunWorkPos2 != null && "0".equals(aGunWorkPos2.toString())) {
// A枪工作位为0时正常匹配A2数据
collect = zl2TargetList.stream().filter(item -> item.getString("TARGET_NAME").equals(key)).collect(Collectors.toList());
} else if (bGunWorkPos2 != null && "0".equals(bGunWorkPos2.toString())) {
// B枪工作位为0时用A2的阈值匹配B2数据
collect = zl2TargetList.stream().filter(item -> item.getString("TARGET_NAME").equals(key.replace("_B2", "_A2"))).collect(Collectors.toList());
}
} else if ("B2".equals(suffix)) {
// 当处理B2数据时
if (bGunWorkPos2 != null && "0".equals(bGunWorkPos2.toString())) {
// B枪工作位为0时用A2的阈值匹配B2数据
collect = zl2TargetList.stream().filter(item -> item.getString("TARGET_NAME").equals(key.replace("_B2", "_A2"))).collect(Collectors.toList());
} else if (aGunWorkPos2 != null && "0".equals(aGunWorkPos2.toString())) {
// A枪工作位为0时正常匹配B2数据
collect = zl2TargetList.stream().filter(item -> item.getString("TARGET_NAME").equals(key)).collect(Collectors.toList());
}
}
} else if (key.contains("1#高炉")) {
mesData.put("EQUIPMENT_ID", "c6825a6e1c959c3e5c800433516b2e8d");
collect = gl1TargetList.stream().filter(item -> item.getString("TARGET_NAME").equals(key)).collect(Collectors.toList());
@ -237,6 +293,7 @@ public class MesDataScheduled extends IJobHandler {
if (collect.size() > 0) {
PageData pageData = collect.get(0);
mesData.put("IPCDEVICE_ID", pageData.getString("IPCDEVICE_ID"));
mesData.put("DEVICE_ID", pageData.getString("DEVICE_ID"));
mesData.put("PLC_ID", pageData.getString("PLC_ID"));
mesData.put("PLC_NAME", pageData.getString("PLC_NAME"));
mesData.put("TARGET_TYPE", pageData.getString("TARGET_TYPE"));
@ -255,8 +312,15 @@ public class MesDataScheduled extends IJobHandler {
mesData.put("TARGET_STATUS", pageData.getString("TARGET_STATUS"));
mesData.put("CORPINFO_ID", pageData.getString("CORPINFO_ID"));
mesData.put("REPORT_ID", pageData.getString("REPORT_ID"));
// 检查是否需要报警
// 除尘器设备不需要检查报警
if (!key.contains("除尘器")) {
checkThreshold(mesData);
}
} else {
mesData.put("IPCDEVICE_ID", "");
mesData.put("DEVICE_ID","");
mesData.put("PLC_ID", "");
mesData.put("PLC_NAME", "");
mesData.put("TARGET_TYPE", "");
@ -328,6 +392,231 @@ public class MesDataScheduled extends IJobHandler {
// 将数据存入Redis缓存
redisUtil.set("MES_DATA_LIST", JSONObject.toJSONString(mesSaveList));
XxlJobHelper.log("已将MES数据存入Redis缓存");
// 处理报警数据
processAlarmData(mesSaveList);
}
}
}
/**
*
* @param data
*/
private void checkThreshold(Map<String, Object> data) {
try {
String signalType = (String) data.get("SIGNAL_TYPE");
// 只处理模拟量数据(信号类型为"1"
if ("1".equals(signalType)) {
String currentValueStr = String.valueOf(data.get("CURRENT_VALUE"));
String thresholdUpLimitStr = (String) data.get("THRESHOLD_UP_LIMIT");
String thresholdUpUpLimitStr = (String) data.get("THRESHOLD_UP_UP_LIMIT");
String thresholdDownLimitStr = (String) data.get("THRESHOLD_DOWN_LIMIT");
String thresholdDownDownLimitStr = (String) data.get("THRESHOLD_DOWN_DOWN_LIMIT");
if (currentValueStr == null || "null".equals(currentValueStr)) {
return;
}
double currentValue = Double.parseDouble(currentValueStr);
// 检查高高报
if (thresholdUpUpLimitStr != null && !"".equals(thresholdUpUpLimitStr) && !"null".equals(thresholdUpUpLimitStr)) {
double thresholdUpUpLimit = Double.parseDouble(thresholdUpUpLimitStr);
if (currentValue >= thresholdUpUpLimit) {
data.put("WARNING", 1);
data.put("OVERVIEW_OF_ALERTS", "高高报警");
return;
}
}
// 检查高报
if (thresholdUpLimitStr != null && !"".equals(thresholdUpLimitStr) && !"null".equals(thresholdUpLimitStr)) {
double thresholdUpLimit = Double.parseDouble(thresholdUpLimitStr);
if (currentValue >= thresholdUpLimit) {
data.put("WARNING", 1);
data.put("OVERVIEW_OF_ALERTS", "高报警");
return;
}
}
// 检查低报
if (thresholdDownLimitStr != null && !"".equals(thresholdDownLimitStr) && !"null".equals(thresholdDownLimitStr)) {
double thresholdDownLimit = Double.parseDouble(thresholdDownLimitStr);
if (currentValue <= thresholdDownLimit) {
data.put("WARNING", 1);
data.put("OVERVIEW_OF_ALERTS", "低报警");
return;
}
}
// 检查低低报
if (thresholdDownDownLimitStr != null && !"".equals(thresholdDownDownLimitStr) && !"null".equals(thresholdDownDownLimitStr)) {
double thresholdDownDownLimit = Double.parseDouble(thresholdDownDownLimitStr);
if (currentValue <= thresholdDownDownLimit) {
data.put("WARNING", 1);
data.put("OVERVIEW_OF_ALERTS", "低低报警");
return;
}
}
} else {
// 处理开关量报警
String currentValueStr = String.valueOf(data.get("CURRENT_VALUE"));
String alarmValueStr = (String) data.get("ALARM_VALUE");
if (currentValueStr != null && alarmValueStr != null &&
!"".equals(currentValueStr) && !"".equals(alarmValueStr) &&
!"null".equals(currentValueStr) && !"null".equals(alarmValueStr)) {
int currentValue = (int) Double.parseDouble(currentValueStr);
int alarmValue = (int) Double.parseDouble(alarmValueStr);
if (currentValue == alarmValue) {
data.put("WARNING", 1);
data.put("OVERVIEW_OF_ALERTS", "联锁投入报警");
}
}
}
} catch (Exception e) {
XxlJobHelper.log("检查阈值时发生异常: {}", e.getMessage());
}
}
/**
*
* @param mesSaveList
*/
private void processAlarmData(ArrayList<Map<String, Object>> mesSaveList) {
ArrayList<PageData> alarmLogArrayList = new ArrayList<>();
ArrayList<PageData> activeAlarms = new ArrayList<>();
for (Map<String, Object> item : mesSaveList) {
// 检查是否有报警且是模拟量
Object warningObj = item.get("WARNING");
if (warningObj != null && "1".equals(String.valueOf(warningObj))) {
// 有告警 且是模拟量
PageData itemPageData = new PageData();
itemPageData.put("ALARM_MONITORING_ID", UuidUtil.get32UUID());
itemPageData.put("PLC_NAME", item.get("PLC_NAME"));
itemPageData.put("PLC_ID", item.get("PLC_ID"));
itemPageData.put("DEVICE_ID", item.get("DEVICE_ID"));
itemPageData.put("EQUIPMENT_ID", item.get("EQUIPMENT_ID"));
itemPageData.put("CURRENT_VALUE", item.get("CURRENT_VALUE"));
itemPageData.put("THRESHOLD_UP_LIMIT", item.get("THRESHOLD_UP_LIMIT"));
itemPageData.put("THRESHOLD_UP_UP_LIMIT", item.get("THRESHOLD_UP_UP_LIMIT"));
itemPageData.put("THRESHOLD_DOWN_LIMIT", item.get("THRESHOLD_DOWN_LIMIT"));
itemPageData.put("THRESHOLD_DOWN_DOWN_LIMIT", item.get("THRESHOLD_DOWN_DOWN_LIMIT"));
itemPageData.put("GATHER_TIME", item.get("GATHER_TIME"));
itemPageData.put("RANGE_UP", item.get("RANGE_UP"));
itemPageData.put("RANGE_DOWN", item.get("RANGE_DOWN"));
itemPageData.put("OVERVIEW_OF_ALERTS", item.get("OVERVIEW_OF_ALERTS"));
itemPageData.put("CORPINFO_ID", item.get("CORPINFO_ID"));
itemPageData.put("OPERATTIME", DateUtil.date2Str(new Date()));
itemPageData.put("CREATTIME", DateUtil.date2Str(new Date()));
alarmLogArrayList.add(itemPageData);
// 添加到活跃报警列表用于处理warninfo表
activeAlarms.add(itemPageData);
}
}
// 把报警的数据转存到数据库里
if (!alarmLogArrayList.isEmpty()) {
deviceMonitoringAlarmSrevice.saveBatch(alarmLogArrayList);
XxlJobHelper.log("成功保存{}条报警数据到报警表", alarmLogArrayList.size());
}
// 将报警数据存入Redis
if (!activeAlarms.isEmpty()) {
redisUtil.set("MES_ALARM_DATA_LIST", JSONObject.toJSONString(activeAlarms));
XxlJobHelper.log("成功将{}条报警数据存入Redis", activeAlarms.size());
}
// 处理告警信息表(tb_iron_warninfo)
processWarnInfo(activeAlarms, mesSaveList);
}
/**
* (tb_iron_warninfo)
* @param activeAlarms
* @param allData
*/
private void processWarnInfo(ArrayList<PageData> activeAlarms, ArrayList<Map<String, Object>> allData) {
// 获取当前时间
String currentTime = DateUtil.date2Str(new Date());
// 处理新产生的报警
for (PageData alarm : activeAlarms) {
String key = alarm.getString("EQUIPMENT_ID") + "_" + alarm.getString("PLC_ID") + "_" + alarm.getString("PLC_NAME");
// 检查该监测点是否已有报警记录
if (!alarmStatusMap.containsKey(key)) {
// 新报警,创建告警信息
PageData warnInfo = new PageData();
warnInfo.put("WARN_ID", UuidUtil.get32UUID());
warnInfo.put("WARN_STATUS", "0"); // 0表示未消警
warnInfo.put("WARN_ORG", "山西新泰钢铁有限公司"); // 0表示未消警
if (alarm.get("OVERVIEW_OF_ALERTS")=="低低报警" || alarm.get("OVERVIEW_OF_ALERTS")=="低报警"){
warnInfo.put("WARN_RANK", "3");
}else if (alarm.get("OVERVIEW_OF_ALERTS")=="高报警"){
warnInfo.put("WARN_RANK", "2");
}else if (alarm.get("OVERVIEW_OF_ALERTS")=="高高报警"){
warnInfo.put("WARN_RANK", "1");
}
warnInfo.put("MESSAGE", "设备名称:"+ alarm.get("DEVICE_ID")+",监测节点:"+ alarm.get("PLC_NAME")+",报警内容:"+ alarm.get("OVERVIEW_OF_ALERTS"));
warnInfo.put("START_TIME", currentTime); // 预警开始时间
warnInfo.put("CORPINFO_ID", alarm.get("CORPINFO_ID"));
warnInfo.put("CREATTIME", currentTime);
warnInfo.put("OPERATTIME", currentTime);
warnInfo.put("ISDELETE", "0");
warnInfo.put("FEED_BACK", "1");
// 保存到数据库
tbIronWarnInfoDao.saveWarnInfo(warnInfo);
// 保存到alarmStatusMap中用于跟踪状态
alarmStatusMap.put(key, warnInfo);
XxlJobHelper.log("创建新的告警信息: 设备ID={}, PLC_ID={}, 报警内容={}",
alarm.get("EQUIPMENT_ID"), alarm.get("PLC_ID"), alarm.get("OVERVIEW_OF_ALERTS"));
} else {
// 已存在报警,更新当前值和时间
PageData existingWarn = alarmStatusMap.get(key);
existingWarn.put("MESSAGE", "设备名称:"+ alarm.get("DEVICE_ID")+",监测节点:"+ alarm.get("PLC_NAME")+",报警内容:"+ alarm.get("OVERVIEW_OF_ALERTS"));
existingWarn.put("OPERATTIME", currentTime);
alarmStatusMap.put(key, existingWarn);
}
}
// 检查是否有报警恢复的节点
Set<String> activeAlarmKeys = new HashSet<>();
for (PageData alarm : activeAlarms) {
String key = alarm.getString("EQUIPMENT_ID") + "_" + alarm.getString("PLC_ID") + "_" + alarm.getString("PLC_NAME");
activeAlarmKeys.add(key);
}
// 检查之前报警但现在不报警的节点
Iterator<Map.Entry<String, PageData>> iterator = alarmStatusMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, PageData> entry = iterator.next();
String key = entry.getKey();
PageData warnInfo = entry.getValue();
if (!activeAlarmKeys.contains(key)) {
// 该节点之前报警,但现在不报警了,需要更新状态为已消警
warnInfo.put("WARN_STATUS", "1"); // 1表示已消警
warnInfo.put("END_TIME", currentTime); // 预警结束时间
warnInfo.put("OPERATTIME", currentTime);
// 更新数据库中的记录
tbIronWarnInfoDao.updateWarnInfo(warnInfo);
XxlJobHelper.log("更新告警信息为已消警: 设备ID={}, PLC_ID={}, 报警内容={}",
warnInfo.get("EQUIPMENT_ID"), warnInfo.get("PLC_ID"), warnInfo.get("OVERVIEW_OF_ALERTS"));
// 从跟踪map中移除
iterator.remove();
}
}
}
}

View File

@ -0,0 +1,14 @@
package com.zcloud.service.deviceMonitoringSrevice;
import com.zcloud.entity.Page;
import com.zcloud.entity.PageData;
import java.util.List;
public interface TbIronWarnInfoService {
List<PageData> listPage(Page page);
PageData getOneFeedBackByWarnId(PageData page);
}

View File

@ -0,0 +1,27 @@
package com.zcloud.service.deviceMonitoringSrevice.impl;
import com.zcloud.entity.Page;
import com.zcloud.entity.PageData;
import com.zcloud.mapper.datasource.tbIron.TbIronWarnInfoDao;
import com.zcloud.service.deviceMonitoringSrevice.TbIronWarnInfoService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Service
public class TbIronWarnInfoServiceImpl implements TbIronWarnInfoService {
@Resource
private TbIronWarnInfoDao tbIronWarnInfoDao;
@Override
public List<PageData> listPage(Page page) {
return tbIronWarnInfoDao.listPage(page);
}
@Override
public PageData getOneFeedBackByWarnId(PageData pageData) {
return tbIronWarnInfoDao.getOneFeedBackByWarnId(pageData);
}
}

View File

@ -38,6 +38,7 @@
p.PLC_NAME,
p.IPCDEVICE_ID,
p.EQUIPMENT_ID,
e.DEVICE_ID,
e.DEVICE_TYPE,
e.DISPLAY_AREA,
mt.TARGET_NAME,
@ -104,6 +105,7 @@
p.PLC_NAME,
p.IPCDEVICE_ID,
p.EQUIPMENT_ID,
e.DEVICE_ID,
e.DEVICE_TYPE,
mt.TARGET_NAME,
mt.TARGET_TYPE,

View File

@ -0,0 +1,77 @@
<?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.zcloud.mapper.datasource.tbIron.TbIronWarnInfoDao">
<insert id="feedBack">
INSERT INTO tb_iron_warninfo_feedback
(WARN_FEEDBACK_ID, WARN_ID, PRE_WARMING_LEVEL, WARN_FEEDBACK,
REAL_TIME, RESPON_PERSON, ALARM_MEASURES, FILL_BY, CORPINFO_ID,
CREATOR, CREATTIME, OPERATOR, OPERATTIME)
VALUES (#{WARN_FEEDBACK_ID},
#{WARN_ID},
#{PRE_WARMING_LEVEL},
#{WARN_FEEDBACK},
#{REAL_TIME},
#{RESPON_PERSON},
#{ALARM_MEASURES},
#{FILL_BY},
#{CORPINFO_ID},
#{CREATOR},
#{CREATTIME},
#{OPERATOR},
#{OPERATTIME})
</insert>
<insert id="saveWarnInfo" parameterType="com.zcloud.entity.PageData">
INSERT INTO tb_iron_warninfo
(WARN_ID, WARN_STATUS, WARN_ORG, WARN_RANK, MESSAGE, START_TIME,
END_TIME, CORPINFO_ID, CREATOR, CREATTIME, OPERATOR, OPERATTIME,ISDELETE,FEED_BACK)
VALUES
(#{WARN_ID}, #{WARN_STATUS}, #{WARN_ORG}, #{WARN_RANK}, #{MESSAGE}, #{START_TIME},
#{END_TIME}, #{CORPINFO_ID}, #{CREATOR}, #{CREATTIME}, #{OPERATOR}, #{OPERATTIME},#{ISDELETE},#{FEED_BACK})
</insert>
<update id="updateWarnInfo" parameterType="com.zcloud.entity.PageData">
UPDATE tb_iron_warninfo
SET
WARN_STATUS = #{WARN_STATUS},
END_TIME = #{END_TIME},
OPERATTIME = #{OPERATTIME}
WHERE
WARN_ID = #{WARN_ID} AND WARN_STATUS = '0'
</update>
<insert id="feedbackDataEdit">
update tb_iron_warninfo_feedback
set WARN_FEEDBACK = #{WARN_FEEDBACK},
REAL_TIME = #{REAL_TIME},
RESPON_PERSON = #{RESPON_PERSON},
ALARM_MEASURES = #{ALARM_MEASURES},
FILL_BY = #{FILL_BY},
OPERATOR = #{OPERATOR}
where WARN_FEEDBACK_ID = #{WARN_FEEDBACK_ID}
</insert>
<update id="activationFeedBack">
UPDATE tb_iron_warninfo SET `FEED_BACK` = 0 WHERE `WARN_ID` = #{WARN_ID}
</update>
<select id="listPage" resultType="com.zcloud.entity.PageData">
select * from tb_iron_warninfo p where p.ISDELETE = 0 and CORPINFO_ID = #{pd.CORPINFO_ID}
<if test="pd.KEYWORDS != null and pd.KEYWORDS != ''">
and p.WARN_ORG like CONCAT(CONCAT('%', #{pd.KEYWORDS}),'%')
</if>
<if test="pd.WARN_STATUS != null and pd.WARN_STATUS != ''">
and p.WARN_STATUS = #{pd.WARN_STATUS}
</if>
<if test="pd.WARN_RANK != null and pd.WARN_RANK != ''">
and p.WARN_RANK = #{pd.WARN_RANK}
</if>
order by p.CREATTIME desc
</select>
<select id="getOneFeedBackByWarnId" resultType="com.zcloud.entity.PageData">
select *
from tb_iron_warninfo_feedback
where ISDELETE = 0
and WARN_ID = #{WARN_ID}
</select>
</mapper>