From 8ea3c56abd9555f2ae15a1a4cb0a1339eaea1ebe Mon Sep 17 00:00:00 2001 From: wangyan <405898180@qq.com> Date: Wed, 12 Nov 2025 16:47:29 +0800 Subject: [PATCH] =?UTF-8?q?feat(device):=20=E5=AE=9E=E7=8E=B0=E8=AE=BE?= =?UTF-8?q?=E5=A4=87=E7=9B=91=E6=8E=A7=E6=8A=A5=E8=AD=A6=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加设备监控报警服务和数据访问接口- 实现阈值检查逻辑,支持模拟量和开关量报警 - 新增报警数据处理,包括存储到数据库和Redis缓存 - 实现告警信息表(tb_iron_warninfo)的创建和更新逻辑 - 添加设备节点报警状态跟踪机制 - 完善数据采集时间字段,替换固定值为实际时间 - 增加A枪和B枪工作位状态判断逻辑- 优化设备ID和PLC名称等字段的获取逻辑 -修复除尘器设备不参与报警检查的逻辑 - 添加ConcurrentHashMap用于线程安全的报警状态管理 --- .../controller/AppPosiDeviceController.java | 230 +++++++++++++- .../datasource/tbIron/TbIronWarnInfoDao.java | 28 ++ .../dataDocking/MesDataScheduled.java | 297 +++++++++++++++++- .../TbIronWarnInfoService.java | 14 + .../impl/TbIronWarnInfoServiceImpl.java | 27 ++ .../datasource/tbIron/TbIronPlcMapper.xml | 2 + .../tbIron/TbIronWarningInfoDao.xml | 77 +++++ 7 files changed, 667 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/zcloud/mapper/datasource/tbIron/TbIronWarnInfoDao.java create mode 100644 src/main/java/com/zcloud/service/deviceMonitoringSrevice/TbIronWarnInfoService.java create mode 100644 src/main/java/com/zcloud/service/deviceMonitoringSrevice/impl/TbIronWarnInfoServiceImpl.java create mode 100644 src/main/resources/mybatis/datasource/tbIron/TbIronWarningInfoDao.xml diff --git a/src/main/java/com/zcloud/controller/AppPosiDeviceController.java b/src/main/java/com/zcloud/controller/AppPosiDeviceController.java index 25389be..d39e3c1 100644 --- a/src/main/java/com/zcloud/controller/AppPosiDeviceController.java +++ b/src/main/java/com/zcloud/controller/AppPosiDeviceController.java @@ -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 alarmStatusMap = new ConcurrentHashMap<>(); @PostMapping("/test1") public R test1(@RequestBody HashMap parma) throws Exception { @@ -172,7 +184,10 @@ public class AppPosiDeviceController { String currentValue = parma.get(bitNo); // 添加到数据列表 - dataList.add(saveData(currentValue, equipmentId, targetAllList, processingBatchId, processingTime)); + Map 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 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> mesSaveList) { + ArrayList alarmLogArrayList = new ArrayList<>(); + ArrayList activeAlarms = new ArrayList<>(); + + for (Map 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 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 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> iterator = alarmStatusMap.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry 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" -》 // } -} +} \ No newline at end of file diff --git a/src/main/java/com/zcloud/mapper/datasource/tbIron/TbIronWarnInfoDao.java b/src/main/java/com/zcloud/mapper/datasource/tbIron/TbIronWarnInfoDao.java new file mode 100644 index 0000000..64b9d05 --- /dev/null +++ b/src/main/java/com/zcloud/mapper/datasource/tbIron/TbIronWarnInfoDao.java @@ -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 listPage(Page page); + + PageData getOneFeedBackByWarnId(PageData page); + + /** + * 保存告警信息 + * @param pageData 告警信息 + */ + void saveWarnInfo(PageData pageData); + + /** + * 更新告警信息 + * @param pageData 告警信息 + */ + void updateWarnInfo(PageData pageData); + +} \ No newline at end of file diff --git a/src/main/java/com/zcloud/scheduled/dataDocking/MesDataScheduled.java b/src/main/java/com/zcloud/scheduled/dataDocking/MesDataScheduled.java index cac86c7..616ff37 100644 --- a/src/main/java/com/zcloud/scheduled/dataDocking/MesDataScheduled.java +++ b/src/main/java/com/zcloud/scheduled/dataDocking/MesDataScheduled.java @@ -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 alarmStatusMap = new ConcurrentHashMap<>(); @Override @XxlJob(value = "mesDataJob") @@ -182,6 +194,12 @@ public class MesDataScheduled extends IJobHandler { ArrayList> mesSaveList = new ArrayList<>(); for (Map map : mesDataList) { Set 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 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 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> mesSaveList) { + ArrayList alarmLogArrayList = new ArrayList<>(); + ArrayList activeAlarms = new ArrayList<>(); + + for (Map 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 activeAlarms, ArrayList> 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 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> iterator = alarmStatusMap.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry 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(); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/com/zcloud/service/deviceMonitoringSrevice/TbIronWarnInfoService.java b/src/main/java/com/zcloud/service/deviceMonitoringSrevice/TbIronWarnInfoService.java new file mode 100644 index 0000000..d4e4f0d --- /dev/null +++ b/src/main/java/com/zcloud/service/deviceMonitoringSrevice/TbIronWarnInfoService.java @@ -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 listPage(Page page); + + + PageData getOneFeedBackByWarnId(PageData page); + +} diff --git a/src/main/java/com/zcloud/service/deviceMonitoringSrevice/impl/TbIronWarnInfoServiceImpl.java b/src/main/java/com/zcloud/service/deviceMonitoringSrevice/impl/TbIronWarnInfoServiceImpl.java new file mode 100644 index 0000000..c87b244 --- /dev/null +++ b/src/main/java/com/zcloud/service/deviceMonitoringSrevice/impl/TbIronWarnInfoServiceImpl.java @@ -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 listPage(Page page) { + return tbIronWarnInfoDao.listPage(page); + } + + @Override + public PageData getOneFeedBackByWarnId(PageData pageData) { + return tbIronWarnInfoDao.getOneFeedBackByWarnId(pageData); + } +} diff --git a/src/main/resources/mybatis/datasource/tbIron/TbIronPlcMapper.xml b/src/main/resources/mybatis/datasource/tbIron/TbIronPlcMapper.xml index d06c71f..b19f019 100644 --- a/src/main/resources/mybatis/datasource/tbIron/TbIronPlcMapper.xml +++ b/src/main/resources/mybatis/datasource/tbIron/TbIronPlcMapper.xml @@ -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, diff --git a/src/main/resources/mybatis/datasource/tbIron/TbIronWarningInfoDao.xml b/src/main/resources/mybatis/datasource/tbIron/TbIronWarningInfoDao.xml new file mode 100644 index 0000000..31e0f8d --- /dev/null +++ b/src/main/resources/mybatis/datasource/tbIron/TbIronWarningInfoDao.xml @@ -0,0 +1,77 @@ + + + + + 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 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}) + + + + 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 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} + + + UPDATE tb_iron_warninfo SET `FEED_BACK` = 0 WHERE `WARN_ID` = #{WARN_ID} + + + + + \ No newline at end of file