wangxiaofei 1 týždeň pred
rodič
commit
4aef550121

+ 235 - 241
taphole-iron/src/main/java/com/sckj/iron/socketio/DeviceEventListener.java

@@ -62,7 +62,6 @@ import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentSkipListMap;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -233,7 +232,7 @@ public class DeviceEventListener extends AbstractEventListener { //
     // 分别记录两个鱼雷罐车的最大值和当前递增值
     private BigDecimal ironWeight1Pre = BigDecimal.ZERO;//上一个数据
     private BigDecimal ironWeight2Pre = BigDecimal.ZERO;//上一个数据
-    private Map<String,Double> ironTempMap = new ConcurrentHashMap<>();
+    private Map<String, Double> ironSpeedMap = new ConcurrentHashMap<>();
 
     //出铁耗时(单位:秒)
     private AtomicInteger mSecondsElapsed = new AtomicInteger(0);
@@ -246,17 +245,17 @@ public class DeviceEventListener extends AbstractEventListener { //
     private TIronData mTIronData;
 
     //连续计数
-    private Map<String, Integer> mWarnCountMap = new ConcurrentSkipListMap<>();
+    private Map<String, List<Object>> mWarnCountMap = Collections.synchronizedMap(new LinkedHashMap<>());
 
 
     // 定时任务统一管理
-    private Map<String, TIronSchedule> scheduleMap = new ConcurrentHashMap<>();
+    private Map<String, TIronSchedule> mScheduleMap = new ConcurrentHashMap<>();
 
     // 模型统一管理
-    private Map<String, TIronModel> modelMap = new ConcurrentHashMap<>();
+    private Map<String, TIronModel> mModelMap = new ConcurrentHashMap<>();
 
     // 音频统一管理
-    private Map<String, TAudioDTO> audioMap = new ConcurrentHashMap<>();
+    private Map<String, TAudioDTO> mAudioMap = new ConcurrentHashMap<>();
 
     //建议打泥量
     private String mCalcHitMud;
@@ -307,12 +306,12 @@ public class DeviceEventListener extends AbstractEventListener { //
         taskExecutor.submit(() -> {
             getSchedules();
 
-            TIronSchedule opcdasubscribe = scheduleMap.get(TaskNameConstants.TASKNAME_OPCDASUBSCRIBE);
+            TIronSchedule opcdasubscribe = mScheduleMap.get(TaskNameConstants.TASKNAME_OPCDASUBSCRIBE);
             if (opcdasubscribe != null && "1".equals(opcdasubscribe.getStatus())) {
                 scheduledTaskManager.addTask(opcdasubscribe.getName(), opcdasubscribe.getDelay(), opcdasubscribe.getPeriod(), TimeUnit.SECONDS, () -> {
                     if ("prod".equals(activeProfiles)) {
                         log.info("HDC subscribe available");
-                       // hdService.subscribeAvailable();
+                        // hdService.subscribeAvailable();
                     } else if ("test".equals(activeProfiles)) {
                         log.info("DA subscribe available");
                         opcuaService.subscribeAvailable();
@@ -331,7 +330,7 @@ public class DeviceEventListener extends AbstractEventListener { //
      * 出铁模型
      */
     private void getModels() {
-        modelMap = ironModelService.lambdaQuery().eq(TIronModel::getStatus, "1").list().stream().collect(Collectors.toMap(
+        mModelMap = ironModelService.lambdaQuery().eq(TIronModel::getStatus, "1").list().stream().collect(Collectors.toMap(
                 TIronModel::getModelName, // 键映射函数
                 model -> model, // 值映射函数
                 (existing, replacement) -> existing // 合并函数
@@ -342,7 +341,7 @@ public class DeviceEventListener extends AbstractEventListener { //
      * 预警音频
      */
     private void getAudios() {
-        audioMap = audioService.lambdaQuery().eq(TAudio::getDelFlag, "1").list().stream().collect(Collectors.toMap(
+        mAudioMap = audioService.lambdaQuery().eq(TAudio::getDelFlag, "1").list().stream().collect(Collectors.toMap(
                 TAudio::getExceptionType, // 键映射函数
                 audio -> {
                     TAudioDTO tAudioDTO = new TAudioDTO();
@@ -558,7 +557,7 @@ public class DeviceEventListener extends AbstractEventListener { //
      * 定时任务
      */
     private void getSchedules() {
-        scheduleMap = iTIronScheduleService.lambdaQuery().list().stream().collect(Collectors.toMap(
+        mScheduleMap = iTIronScheduleService.lambdaQuery().list().stream().collect(Collectors.toMap(
                 TIronSchedule::getName, // 键映射函数
                 schedule -> schedule, // 值映射函数
                 (existing, replacement) -> existing // 合并函数
@@ -848,8 +847,8 @@ public class DeviceEventListener extends AbstractEventListener { //
         //平均流速
         BigDecimal avgSpeed = totalWeight.divide(BigDecimal.valueOf(ironElapsedMinute), 2, RoundingMode.HALF_UP);
 
-        if(avgSpeed.doubleValue() < stdIronSpeedMin || avgSpeed.doubleValue() > stdIronSpeedMax){
-            log.warn("平均流速{}不在速度阈值范围内({}-{}), 不计算剩余时间", avgSpeed,stdIronSpeedMin,stdIronSpeedMax);
+        if (avgSpeed.doubleValue() < stdIronSpeedMin || avgSpeed.doubleValue() > stdIronSpeedMax) {
+            log.warn("平均流速{}不在速度阈值范围内({}-{}), 不计算剩余时间", avgSpeed, stdIronSpeedMin, stdIronSpeedMax);
             return;
         }
 
@@ -865,7 +864,7 @@ public class DeviceEventListener extends AbstractEventListener { //
         log.info("剩余出铁时间计算完成: {}分钟", diffCloseTime);
 
         int stdIronTimeMax = Integer.parseInt(mContext.lookupVariable(ExpressionConstants.stdIronTimeMax).toString()) + 50;
-        log.info("标准最大出铁时间: {}分钟,是否超过最大时间:{},为true则设置为标准最大出铁时间", stdIronTimeMax,diffCloseTime > stdIronTimeMax);
+        log.info("标准最大出铁时间: {}分钟,是否超过最大时间:{},为true则设置为标准最大出铁时间", stdIronTimeMax, diffCloseTime > stdIronTimeMax);
 
         diffCloseTime = Math.min(diffCloseTime, stdIronTimeMax);
 
@@ -886,7 +885,7 @@ public class DeviceEventListener extends AbstractEventListener { //
             isClosureTime.set(true);
 
             // 打泥量选择模型
-            TIronSchedule scheduleHitMud = scheduleMap.get(TaskNameConstants.TASKNAME_HIT_MUD);
+            TIronSchedule scheduleHitMud = mScheduleMap.get(TaskNameConstants.TASKNAME_HIT_MUD);
             if (scheduleHitMud != null && "1".equals(scheduleHitMud.getStatus())) {
                 scheduledTaskManager.addTask(scheduleHitMud.getName(), scheduleHitMud.getDelay(), scheduleHitMud.getPeriod(), TimeUnit.SECONDS, runnableHitmud());
             }
@@ -978,7 +977,7 @@ public class DeviceEventListener extends AbstractEventListener { //
             ironWeight1Pre = BigDecimal.ZERO;
             ironWeight2Pre = BigDecimal.ZERO;
 
-            ironTempMap.clear();
+            ironSpeedMap.clear();
 
             log.info("   ├─ 重置出铁计时: 原计时={}秒 → 重置为0秒", mSecondsElapsed.get());
             mSecondsElapsed.set(0);
@@ -1003,7 +1002,7 @@ public class DeviceEventListener extends AbstractEventListener { //
             log.info("   └─ 已关闭所有出铁相关定时任务");
 
             // 出铁计时
-            TIronSchedule tappingConsttime = scheduleMap.get(TaskNameConstants.TASKNAME_TAPPING_CONSTTIME);
+            TIronSchedule tappingConsttime = mScheduleMap.get(TaskNameConstants.TASKNAME_TAPPING_CONSTTIME);
             if (tappingConsttime != null && "1".equals(tappingConsttime.getStatus())) {
                 log.info("   ⏱️ 【启动出铁计时任务】");
                 log.info("      ├─ 任务名称: {}", tappingConsttime.getName());
@@ -1018,19 +1017,19 @@ public class DeviceEventListener extends AbstractEventListener { //
             }
 
             // 堵口模型
-            TIronSchedule closureWarn = scheduleMap.get(TaskNameConstants.TASKNAME_CLOSURE_WARN);
+            TIronSchedule closureWarn = mScheduleMap.get(TaskNameConstants.TASKNAME_CLOSURE_WARN);
             if (closureWarn != null && "1".equals(closureWarn.getStatus())) {
                 log.info("   🔒 【启动堵口预警任务】");
                 log.info("      ├─ 任务名称: {}", closureWarn.getName());
                 log.info("      ├─ 延迟时间: {}秒", closureWarn.getDelay());
                 log.info("      └─ 执行周期: {}秒", closureWarn.getPeriod());
-                scheduledTaskManager.addTask(closureWarn.getName(), closureWarn.getDelay(), closureWarn.getPeriod(), TimeUnit.SECONDS, runnableClosureWarn());
+                //scheduledTaskManager.addTask(closureWarn.getName(), closureWarn.getDelay(), closureWarn.getPeriod(), TimeUnit.SECONDS, runnableClosureWarn());
             } else {
                 log.info("   🔒 【堵口预警任务】未启动 (配置为null或status!=1)");
             }
 
             // 出铁超时报警
-            TIronSchedule tappingTimeoutWarn = scheduleMap.get(TaskNameConstants.TASKNAME_TAPPING_TIMEOUT_WARN);
+            TIronSchedule tappingTimeoutWarn = mScheduleMap.get(TaskNameConstants.TASKNAME_TAPPING_TIMEOUT_WARN);
             if (tappingTimeoutWarn != null && "1".equals(tappingTimeoutWarn.getStatus())) {
                 log.info("   ⚠️ 【启动出铁超时报警任务】");
                 log.info("      ├─ 任务名称: {}", tappingTimeoutWarn.getName());
@@ -1042,7 +1041,7 @@ public class DeviceEventListener extends AbstractEventListener { //
             }
 
             // 出铁超重报警
-            TIronSchedule tappingWeightoutWarn = scheduleMap.get(TaskNameConstants.TAPPING_WEIGHTOUT_WARN);
+            TIronSchedule tappingWeightoutWarn = mScheduleMap.get(TaskNameConstants.TAPPING_WEIGHTOUT_WARN);
             if (tappingWeightoutWarn != null && "1".equals(tappingWeightoutWarn.getStatus())) {
                 log.info("   ⚖️ 【启动出铁超重报警任务】");
                 log.info("      ├─ 任务名称: {}", tappingWeightoutWarn.getName());
@@ -1154,7 +1153,7 @@ public class DeviceEventListener extends AbstractEventListener { //
                 log.warn("⚠️ 出铁时间偏短: 实际{}分钟 < 标准{}分钟", actualTime, stdIronTimeMin);
                 taskExecutor.submit(() -> {
                     log.info("📝 记录出铁时间偏短异常...");
-                    PushData.send2Warn(audioMap.get(ExceptionTypeEnum.IRON_TIME_SHORT.getCode()));
+                    PushData.send2Warn(mAudioMap.get(ExceptionTypeEnum.IRON_TIME_SHORT.getCode()));
                     saveException(ExceptionTypeEnum.IRON_TIME_SHORT,
                             String.format("出铁时间%s分钟", actualTime));
                     getExceptionList();
@@ -1173,7 +1172,7 @@ public class DeviceEventListener extends AbstractEventListener { //
                 log.warn("⚠️ 出铁量偏少: 实际{}吨 < 标准{}吨", actualWeight, stdIronWeightMin);
                 taskExecutor.submit(() -> {
                     log.info("📝 记录出铁量偏少异常...");
-                    PushData.send2Warn(audioMap.get(ExceptionTypeEnum.IRON_WEIGHT_FEW.getCode()));
+                    PushData.send2Warn(mAudioMap.get(ExceptionTypeEnum.IRON_WEIGHT_FEW.getCode()));
                     saveException(ExceptionTypeEnum.IRON_WEIGHT_FEW,
                             String.format("出铁量%s吨", actualWeight));
                     getExceptionList();
@@ -1188,7 +1187,7 @@ public class DeviceEventListener extends AbstractEventListener { //
             }
 
             // 7. 启动出铁诊断模型
-            TIronSchedule tappingTest = scheduleMap.get(TaskNameConstants.TASKNAME_TAPPING_TEST);
+            TIronSchedule tappingTest = mScheduleMap.get(TaskNameConstants.TASKNAME_TAPPING_TEST);
             if (tappingTest != null && "1".equals(tappingTest.getStatus())) {
                 log.info("🔬 启动出铁诊断模型...");
                 scheduledTaskManager.addTask(tappingTest.getName(),
@@ -1205,131 +1204,6 @@ public class DeviceEventListener extends AbstractEventListener { //
         }
     }
 
-    //堵口预警
-    @NotNull
-    private Runnable runnableClosureWarn() {
-        return () -> {
-            log.info("=== 堵口预警检查开始 ===");
-
-            TIronModel modelClosureWarn1 = modelMap.get(ModelConstants.closure_warn1);
-            TIronModel modelClosureWarn2 = modelMap.get(ModelConstants.closure_warn2);
-            TIronModel modelClosureWarn3 = modelMap.get(ModelConstants.closure_warn3);
-
-            log.info("模型状态: closure_warn1={}, closure_warn2={}, closure_warn3={}",
-                    modelClosureWarn1 != null ? modelClosureWarn1.getStatus() : "null",
-                    modelClosureWarn2 != null ? modelClosureWarn2.getStatus() : "null",
-                    modelClosureWarn3 != null ? modelClosureWarn3.getStatus() : "null");
-
-            try {
-
-                if ("1".equals(modelClosureWarn1.getStatus())
-                        && "1".equals(modelClosureWarn2.getStatus())
-                        && "1".equals(modelClosureWarn3.getStatus())
-                ) {
-                    log.info("使用模型预警模式");
-
-                    //堵口预警
-                    String modelExpression1 = modelClosureWarn1.getModelExpression();
-                    log.info("模型1表达式: {}", modelExpression1);
-                    Expression expression1 = mParser.parseExpression(modelExpression1);
-                    boolean result1 = expression1.getValue(mContext, Boolean.class);
-                    String modelKey1 = modelClosureWarn1.getModelName();
-                    int triggerCount1 = modelClosureWarn1.getTriggerCondCount() != null ? modelClosureWarn1.getTriggerCondCount() : 1;
-
-                    log.info("模型1评估: result1={}, triggerCount1={}", result1, triggerCount1);
-
-                    if (result1) {
-                        int count = mWarnCountMap.getOrDefault(modelKey1, 0) + 1;
-
-                        log.info("模型1触发计数: {}/{}", count, triggerCount1);
-
-                        mWarnCountMap.put(modelKey1, count);
-                        if (count >= triggerCount1) {
-                            log.warn("模型1触发堵口告警1");
-
-                            taskExecutor.submit(() -> {
-                                PushData.send2Warn(audioMap.get(ExceptionTypeEnum.CLOSURE1.getCode()));
-                                saveException(ExceptionTypeEnum.NEED_CLOSURE, String.format("流速偏大,建议将当前铁口堵口"));
-                                //推送预警列表
-                                getExceptionList();
-                            });
-                            mWarnCountMap.put(modelKey1, 0);
-                            return;
-                        }
-                    } else {
-                        mWarnCountMap.put(modelKey1, 0);
-                        PushData.send2CancelWarn(new TAudioDTO());
-                    }
-
-                    String modelExpression2 = modelClosureWarn2.getModelExpression();
-                    log.info("模型2表达式: {}", modelExpression2);
-                    Expression expression2 = mParser.parseExpression(modelExpression2);
-                    boolean result2 = expression2.getValue(mContext, Boolean.class);
-                    String modelKey2 = modelClosureWarn2.getModelName();
-                    int triggerCount2 = modelClosureWarn2.getTriggerCondCount() != null ? modelClosureWarn2.getTriggerCondCount() : 1;
-                    log.info("模型2评估: result2={}, triggerCount2={}", result2, triggerCount2);
-
-                    if (result2) {
-                        int count = mWarnCountMap.getOrDefault(modelKey2, 0) + 1;
-                        log.info("模型2触发计数: {}/{}", count, triggerCount2);
-                        mWarnCountMap.put(modelKey2, count);
-                        if (count >= triggerCount2) {
-                            log.warn("模型1触发堵口告警2");
-
-                            taskExecutor.submit(() -> {
-                                PushData.send2Warn(audioMap.get(ExceptionTypeEnum.CLOSURE2.getCode()));
-                                saveException(ExceptionTypeEnum.NEED_CLOSURE, String.format("流速偏小,但其它铁口正在出铁,请将当前铁口堵口"));
-                                //推送预警列表
-                                getExceptionList();
-                            });
-                            mWarnCountMap.put(modelKey2, 0);
-                            return;
-                        }
-                    } else {
-                        mWarnCountMap.put(modelKey2, 0);
-                        PushData.send2CancelWarn(new TAudioDTO());
-                    }
-
-                    String modelExpression3 = modelClosureWarn3.getModelExpression();
-                    log.info("模型3表达式: {}", modelExpression3);
-
-                    Expression expression3 = mParser.parseExpression(modelExpression3);
-                    boolean result3 = expression3.getValue(mContext, Boolean.class);
-                    String modelKey3 = modelClosureWarn3.getModelName();
-                    int triggerCount3 = modelClosureWarn3.getTriggerCondCount() != null ? modelClosureWarn3.getTriggerCondCount() : 1;
-                    log.info("模型3评估: result3={}, triggerCount3={}", result3, triggerCount3);
-
-                    if (result3) {
-                        int count = mWarnCountMap.getOrDefault(modelKey3, 0) + 1;
-                        log.info("模型3触发计数: {}/{}", count, triggerCount3);
-                        mWarnCountMap.put(modelKey3, count);
-                        if (count >= triggerCount3) {
-                            log.warn("模型3触发堵口告警3");
-                            taskExecutor.submit(() -> {
-                                PushData.send2Warn(audioMap.get(ExceptionTypeEnum.CLOSURE3.getCode()));
-                                saveException(ExceptionTypeEnum.NEED_CLOSURE, String.format("流速偏小且其他铁口均未出铁,请先将其它铁口打开,再进行堵口"));
-                                //推送预警列表
-                                getExceptionList();
-                            });
-                            mWarnCountMap.put(modelKey3, 0);
-                        }
-                    } else {
-                        mWarnCountMap.put(modelKey3, 0);
-                        PushData.send2CancelWarn(new TAudioDTO());
-                    }
-                } else {
-                    log.info("使用实时速度预警模式");
-
-                }
-                log.info("=== 堵口预警检查结束 ===");
-            } catch (Exception e) {
-                log.error("堵口预警检查异常", e);
-                e.printStackTrace();
-            }
-
-        };
-    }
-
 
     //出铁超时
 
@@ -1365,7 +1239,7 @@ public class DeviceEventListener extends AbstractEventListener { //
 
                         try {
                             try {
-                                PushData.send2Warn(audioMap.get(ExceptionTypeEnum.IRON_TIME_LONG.getCode()));
+                                PushData.send2Warn(mAudioMap.get(ExceptionTypeEnum.IRON_TIME_LONG.getCode()));
                                 // 记录异常信息
                                 String exceptionMessage = String.format("出铁时间:%s分钟", currentIronTime);
                                 saveException(ExceptionTypeEnum.IRON_TIME_LONG, exceptionMessage);
@@ -1377,7 +1251,7 @@ public class DeviceEventListener extends AbstractEventListener { //
                             } catch (Exception e) {
 
                             }
-                            scheduledTaskManager.cancelTask(scheduleMap.get(TaskNameConstants.TASKNAME_TAPPING_TIMEOUT_WARN).getName());
+                            scheduledTaskManager.cancelTask(mScheduleMap.get(TaskNameConstants.TASKNAME_TAPPING_TIMEOUT_WARN).getName());
                         } catch (Exception e) {
                             log.error("处理出铁超时异常时发生错误", e);
                         }
@@ -1417,14 +1291,14 @@ public class DeviceEventListener extends AbstractEventListener { //
 
                     taskExecutor.submit(() -> {
                         try {
-                            PushData.send2Warn(audioMap.get(ExceptionTypeEnum.IRON_WEIGHT_MANY.getCode()));
+                            PushData.send2Warn(mAudioMap.get(ExceptionTypeEnum.IRON_WEIGHT_MANY.getCode()));
                             saveException(ExceptionTypeEnum.IRON_WEIGHT_MANY, String.format("出铁量%s吨", mTotalWeight));
                             //推送预警列表
                             getExceptionList();
                         } catch (Exception e) {
 
                         }
-                        scheduledTaskManager.cancelTask(scheduleMap.get(TaskNameConstants.TAPPING_WEIGHTOUT_WARN).getName());
+                        scheduledTaskManager.cancelTask(mScheduleMap.get(TaskNameConstants.TAPPING_WEIGHTOUT_WARN).getName());
                     });
 
                     log.info("出铁重量异常处理任务已提交");
@@ -1469,7 +1343,7 @@ public class DeviceEventListener extends AbstractEventListener { //
             log.info("开始执行打泥量计算任务 - 任务名称: {}", ModelConstants.hit_mud);
 
             // 获取打泥量计算模型配置
-            TIronModel modelHitMud = modelMap.get(ModelConstants.hit_mud);
+            TIronModel modelHitMud = mModelMap.get(ModelConstants.hit_mud);
             log.info("获取打泥量模型配置: {}", modelHitMud != null ? modelHitMud.getModelName() : "null");
 
             // 获取最新的出铁数据
@@ -1479,14 +1353,14 @@ public class DeviceEventListener extends AbstractEventListener { //
             // 数据有效性检查
             if (ObjectUtils.isEmpty(tappingData)) {
                 log.warn("出铁数据为空,无法计算打泥量");
-                scheduledTaskManager.cancelTask(scheduleMap.get(ModelConstants.hit_mud).getName());
+                scheduledTaskManager.cancelTask(mScheduleMap.get(ModelConstants.hit_mud).getName());
                 log.info("取消打泥量计算任务");
                 return;
             }
 
             if (ObjectUtils.isEmpty(modelHitMud)) {
                 log.warn("未找到打泥量模型配置: {}", ModelConstants.hit_mud);
-                scheduledTaskManager.cancelTask(scheduleMap.get(ModelConstants.hit_mud).getName());
+                scheduledTaskManager.cancelTask(mScheduleMap.get(ModelConstants.hit_mud).getName());
                 log.info("取消打泥量计算任务");
                 return;
             }
@@ -1595,7 +1469,7 @@ public class DeviceEventListener extends AbstractEventListener { //
                 log.error("打泥量计算异常: {}", e.getMessage(), e);
             } finally {
                 // 确保任务被取消
-                scheduledTaskManager.cancelTask(scheduleMap.get(ModelConstants.hit_mud).getName());
+                scheduledTaskManager.cancelTask(mScheduleMap.get(ModelConstants.hit_mud).getName());
                 log.info("打泥量计算任务已完成并取消");
             }
         };
@@ -1612,7 +1486,7 @@ public class DeviceEventListener extends AbstractEventListener { //
                 return;
             }
 
-            TIronModel modelTappingWarn = modelMap.get(ModelConstants.tapping_warn);
+            TIronModel modelTappingWarn = mModelMap.get(ModelConstants.tapping_warn);
             if (modelTappingWarn == null) {
                 log.warn("未找到急需出铁预警模型配置: {}", ModelConstants.tapping_warn);
                 return;
@@ -1628,29 +1502,48 @@ public class DeviceEventListener extends AbstractEventListener { //
                     Expression expression = mParser.parseExpression(modelExpression);
                     Boolean result = expression.getValue(mContext, Boolean.class);
 
-                    log.info("预警表达式执行结果: {}", result);
+                    log.info("急需出铁预警表达式执行结果: {}", result);
 
                     String modelKey = modelTappingWarn.getModelName();
                     int triggerCount = modelTappingWarn.getTriggerCondCount() != null ? modelTappingWarn.getTriggerCondCount() : 1;
 
-                    log.info("触发阈值: {}, 当前计数: {}", triggerCount, mWarnCountMap.getOrDefault(modelKey, 0));
+                    List<Object> warnData = mWarnCountMap.getOrDefault(modelKey, new ArrayList<>());
+                    int count = warnData.isEmpty() ? 0 : ((Number) warnData.get(0)).intValue();
+
+                    log.info("触发阈值: {}, 当前计数: {}", triggerCount, count);
 
                     if (Boolean.TRUE.equals(result)) {
-                        int count = mWarnCountMap.getOrDefault(modelKey, 0) + 1;
-                        mWarnCountMap.put(modelKey, count);
+                        // 增加计数并保存当前数据
+                        count++;
+                        warnData.clear();
+                        warnData.add(count);
+                        // 保存当前压差数据
+                        warnData.add(mContext.lookupVariable(ExpressionConstants.stdPressureDiff));
+                        mWarnCountMap.put(modelKey, warnData);
 
                         log.info("预警条件满足,当前计数: {}/{}", count, triggerCount);
 
                         if (count >= triggerCount) {
                             log.warn("触发急需出铁告警,压差超过阈值: {}", mContext.lookupVariable(ExpressionConstants.stdPressureDiff));
 
+                            StringBuilder tempValues = new StringBuilder();
+                            for (int i = 1; i < warnData.size(); i++) {
+                                if (i > 1) tempValues.append("、");
+                                tempValues.append(warnData.get(i)).append("kPa");
+                            }
+
+                            // 构建异常消息,包含所有记录的数据
+                            StringBuilder msgBuilder = new StringBuilder("压差:");
+                            msgBuilder.append(tempValues.toString());
+                            msgBuilder.append("连续超过阈值" + StandardConstans.STANDARD_PRESSURE_DIFF + "kPa");
+                            // 这里可以添加具体的异常数据
+
                             //触发次数超过配置的次数后发出预警
-                            PushData.send2Warn(audioMap.get(ExceptionTypeEnum.NEED_TAPHOLE.getCode()));
-                            saveException(ExceptionTypeEnum.NEED_TAPHOLE,
-                                    String.format("压差超过%skPa,请降低送风流量,并操作出铁",
-                                            String.valueOf(mContext.lookupVariable(ExpressionConstants.stdPressureDiff))));
+                            PushData.send2Warn(mAudioMap.get(ExceptionTypeEnum.NEED_TAPHOLE.getCode()));
+                            saveException(ExceptionTypeEnum.NEED_TAPHOLE, String.format("%s,请降低送风流量,并操作出铁", msgBuilder));
 
-                            mWarnCountMap.put(modelKey, 0);
+                            // 重置计数
+                            mWarnCountMap.put(modelKey, new ArrayList<>());
 
                             //推送预警列表
                             getExceptionList();
@@ -1658,11 +1551,10 @@ public class DeviceEventListener extends AbstractEventListener { //
                             log.info("急需出铁告警已发送,计数器已重置");
                         }
                     } else {
-                        int oldCount = mWarnCountMap.getOrDefault(modelKey, 0);
-                        if (oldCount > 0) {
-                            log.info("预警条件不满足,重置计数器,原计数: {}", oldCount);
+                        if (count > 0) {
+                            log.info("预警条件不满足,重置计数器,原计数: {}", count);
                         }
-                        mWarnCountMap.put(modelKey, 0);
+                        mWarnCountMap.put(modelKey, new ArrayList<>());
                         PushData.send2CancelWarn(new TAudioDTO());
                     }
                 } catch (Exception e) {
@@ -1851,7 +1743,7 @@ public class DeviceEventListener extends AbstractEventListener { //
                 log.error("❌ 出铁诊断分析异常", e);
                 e.printStackTrace();
             } finally {
-                scheduledTaskManager.cancelTask(scheduleMap.get(TaskNameConstants.TASKNAME_TAPPING_TEST).getName());
+                scheduledTaskManager.cancelTask(mScheduleMap.get(TaskNameConstants.TASKNAME_TAPPING_TEST).getName());
                 log.info("⏹️ 出铁诊断定时任务已取消");
             }
         };
@@ -2105,7 +1997,7 @@ public class DeviceEventListener extends AbstractEventListener { //
                     taphole1End();
 
                     // 启动预警模型
-                    TIronSchedule tappingWarn = scheduleMap.get(TaskNameConstants.TASKNAME_TAPPING_WARN);
+                    TIronSchedule tappingWarn = mScheduleMap.get(TaskNameConstants.TASKNAME_TAPPING_WARN);
                     log.info("   🔍 【预警检查】");
                     log.info("      ├─ 预警配置: {}", tappingWarn != null ? "存在" : "null");
                     if (tappingWarn != null && "1".equals(tappingWarn.getStatus())) {
@@ -2202,70 +2094,110 @@ public class DeviceEventListener extends AbstractEventListener { //
 
                 // 温度异常检测
                 if (tempNow < stdTempMin) {
-                    int count = mWarnCountMap.getOrDefault("tempMinWarn", 0) + 1;
-                    mWarnCountMap.put("tempMinWarn", count);
+                    List<Object> warnData = mWarnCountMap.getOrDefault("tempMinWarn", new ArrayList<>());
+                    int count = warnData.isEmpty() ? 0 : ((Number) warnData.get(0)).intValue();
+                    count++;
+
+                    // 保留最新的不超过触发次数的数据
+                    if (warnData.size() > 1) {
+                        warnData = warnData.subList(0, 1); // 保留计数位置
+                    }
+                    warnData.set(0, count);
+                    warnData.add(tempNow); // 添加当前温度数据
+
+                    mWarnCountMap.put("tempMinWarn", warnData);
                     log.warn("检测到温度偏低 - 当前: {}℃, 标准最低: {}℃, 连续异常次数: {}", tempNow, stdTempMin, count);
 
                     if (count >= StandardConstans.WARN_COUNT) {
-                        log.error("温度偏低预警触发 - 连续3次异常,当前温度: {}℃", tempNow);
-                        taskExecutor.submit(() -> {
-                            try {
-                                String exceptionMsg = String.format("温度%s℃", tempNow);
-                                PushData.send2Warn(audioMap.get(ExceptionTypeEnum.IRON_TEMP_HIGH.getCode()));
-                                saveException(ExceptionTypeEnum.IRON_TEMP_HIGH, exceptionMsg);
-                                log.warn("已记录温度偏低异常: {}", exceptionMsg);
+                        log.error("温度偏低预警触发 - 连续{}次异常", StandardConstans.WARN_COUNT);
+                        try {
+                            // 构建包含所有异常数据的消息
+                            StringBuilder tempValues = new StringBuilder();
+                            for (int i = 1; i < warnData.size(); i++) {
+                                if (i > 1) tempValues.append("、");
+                                tempValues.append(warnData.get(i)).append("℃");
+                            }
+                            String exceptionMsg = String.format("温度连续%d次偏低:%s,低于%d℃",
+                                    StandardConstans.WARN_COUNT, tempValues.toString(), stdTempMin);
 
-                                getExceptionList();
-                                log.info("已推送温度预警列表更新");
+                            PushData.send2Warn(mAudioMap.get(ExceptionTypeEnum.IRON_TEMP_HIGH.getCode()));
+                            saveException(ExceptionTypeEnum.IRON_TEMP_HIGH, exceptionMsg);
+                            log.warn("已记录温度偏低异常: {}", exceptionMsg);
 
-                            } catch (Exception e) {
-                                log.error("处理温度偏低异常时发生错误", e);
-                            }
-                        });
-                        mWarnCountMap.put("tempMinWarn", 0);
+                            getExceptionList();
+                            log.info("已推送温度预警列表更新");
+
+                        } catch (Exception e) {
+                            log.error("处理温度偏低异常时发生错误", e);
+                        }
+                        mWarnCountMap.put("tempMinWarn", new ArrayList<>());
                         mIronTempLowCount.incrementAndGet();
                         log.info("重置温度偏低计数器,低温异常次数+1");
-                        return;
                     }
-
                 } else if (tempNow > stdTempMax) {
-                    int count = mWarnCountMap.getOrDefault("tempMaxWarn", 0) + 1;
-                    mWarnCountMap.put("tempMaxWarn", count);
+                    List<Object> warnData = mWarnCountMap.getOrDefault("tempMaxWarn", new ArrayList<>());
+                    int count = warnData.isEmpty() ? 0 : ((Number) warnData.get(0)).intValue();
+                    count++;
+
+                    // 保留最新的不超过触发次数的数据
+                    if (warnData.size() > 1) {
+                        warnData = warnData.subList(0, 1); // 保留计数位置
+                    }
+                    warnData.set(0, count);
+                    warnData.add(tempNow); // 添加当前温度数据
+
+                    mWarnCountMap.put("tempMaxWarn", warnData);
                     log.warn("检测到温度偏高 - 当前: {}℃, 标准最高: {}℃, 连续异常次数: {}", tempNow, stdTempMax, count);
 
                     if (count >= StandardConstans.WARN_COUNT) {
-                        log.error("温度偏高预警触发 - 连续3次异常,当前温度: {}℃", tempNow);
-                        taskExecutor.submit(() -> {
-                            try {
-                                String exceptionMsg = String.format("温度%s℃", tempNow);
-                                PushData.send2Warn(audioMap.get(ExceptionTypeEnum.IRON_TEMP_LOW.getCode()));
-                                saveException(ExceptionTypeEnum.IRON_TEMP_LOW, exceptionMsg);
-                                log.warn("已记录温度偏高异常: {}", exceptionMsg);
+                        log.error("温度偏高预警触发 - 连续{}次异常", StandardConstans.WARN_COUNT);
+                        try {
+                            // 构建包含所有异常数据的消息
+                            StringBuilder tempValues = new StringBuilder();
+                            for (int i = 1; i < warnData.size(); i++) {
+                                if (i > 1) tempValues.append("、");
+                                tempValues.append(warnData.get(i)).append("℃");
+                            }
+                            String exceptionMsg = String.format("温度连续%d次偏高:%s,高于%d℃",
+                                    StandardConstans.WARN_COUNT, tempValues.toString(), stdTempMax);
 
-                                getExceptionList();
-                                log.info("已推送温度预警列表更新");
+                            PushData.send2Warn(mAudioMap.get(ExceptionTypeEnum.IRON_TEMP_LOW.getCode()));
+                            saveException(ExceptionTypeEnum.IRON_TEMP_LOW, exceptionMsg);
+                            log.warn("已记录温度偏高异常: {}", exceptionMsg);
 
-                            } catch (Exception e) {
-                                log.error("处理温度偏高异常时发生错误", e);
-                            }
-                        });
-                        mWarnCountMap.put("tempMaxWarn", 0);
+                            getExceptionList();
+                            log.info("已推送温度预警列表更新");
+
+                        } catch (Exception e) {
+                            log.error("处理温度偏高异常时发生错误", e);
+                        }
+                        mWarnCountMap.put("tempMaxWarn", new ArrayList<>());
                         mIronTempHighCount.incrementAndGet();
                         log.info("重置温度偏高计数器,高温异常次数+1");
                         return;
                     }
 
                 } else {
-                    // 温度正常,重置异常计数
-                    int oldMinCount = mWarnCountMap.getOrDefault("tempMinWarn", 0);
-                    int oldMaxCount = mWarnCountMap.getOrDefault("tempMaxWarn", 0);
+                    // 温度或流速正常,重置异常计数
+                    int oldMinCount = 0;
+                    int oldMaxCount = 0;
+
+                    List<Object> minWarnData = mWarnCountMap.getOrDefault("tempMinWarn", new ArrayList<>());
+                    if (!minWarnData.isEmpty()) {
+                        oldMinCount = ((Number) minWarnData.get(0)).intValue();
+                    }
+
+                    List<Object> maxWarnData = mWarnCountMap.getOrDefault("tempMaxWarn", new ArrayList<>());
+                    if (!maxWarnData.isEmpty()) {
+                        oldMaxCount = ((Number) maxWarnData.get(0)).intValue();
+                    }
 
                     if (oldMinCount > 0 || oldMaxCount > 0) {
                         log.info("温度恢复正常 - 当前: {}℃,重置异常计数器", tempNow);
                     }
 
-                    mWarnCountMap.put("tempMinWarn", 0);
-                    mWarnCountMap.put("tempMaxWarn", 0);
+                    mWarnCountMap.put("tempMinWarn", new ArrayList<>());
+                    mWarnCountMap.put("tempMaxWarn", new ArrayList<>());
                 }
 
                 // 温度数据收集
@@ -2286,15 +2218,15 @@ public class DeviceEventListener extends AbstractEventListener { //
 
                 String serverTime = LocalDateUtils.formatDate(opcData.getServerTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:00"));
 
-                if(ironTempMap.containsKey(serverTime)){
-                    Double oldValue = ironTempMap.getOrDefault(serverTime, 0D);
-                    if(oldValue < speed){
-                        ironTempMap.put(serverTime,speed);
-                    }else{
+                if (ironSpeedMap.containsKey(serverTime)) {
+                    Double oldValue = ironSpeedMap.getOrDefault(serverTime, 0D);
+                    if (oldValue < speed) {
+                        ironSpeedMap.put(serverTime, speed);
+                    } else {
                         speed = oldValue;
                     }
-                }else{
-                    ironTempMap.put(serverTime,speed);
+                } else {
+                    ironSpeedMap.put(serverTime, speed);
                 }
 
                 mMaxSpeed.set(speed);
@@ -2318,42 +2250,104 @@ public class DeviceEventListener extends AbstractEventListener { //
                     if (rtIronSpeed < stdSpeedMin) {
                         log.warn("流速偏低: {} < {}", rtIronSpeed, stdSpeedMin);
                         //铁水流速低
-                        int count = mWarnCountMap.getOrDefault("speedMinWarn", 0) + 1;
-                        mWarnCountMap.put("speedMinWarn", count);
+                        List<Object> warnData = mWarnCountMap.getOrDefault("speedMinWarn", new ArrayList<>());
+                        int count = warnData.isEmpty() ? 0 : ((Number) warnData.get(0)).intValue();
+                        count++;
+
+                        // 保留最新的不超过触发次数的数据
+                        if (warnData.size() > 1) {
+                            warnData = warnData.subList(0, 1); // 保留计数位置
+                        }
+                        warnData.set(0, count);
+                        warnData.add(rtIronSpeed); // 添加当前流速数据
+
+                        mWarnCountMap.put("speedMinWarn", warnData);
                         log.info("流速偏低计数: {}/3", count);
 
                         if (count >= StandardConstans.WARN_COUNT) {
-                            PushData.send2Warn(audioMap.get(ExceptionTypeEnum.IRON_SPEED_SLOW.getCode()));
+                            // 构建包含所有异常数据的消息
+                            StringBuilder speedValues = new StringBuilder();
+                            for (int i = 1; i < warnData.size(); i++) {
+                                if (i > 1) speedValues.append("、");
+                                speedValues.append(String.format("%st/min", warnData.get(i)));
+                            }
+
+                            PushData.send2Warn(mAudioMap.get(ExceptionTypeEnum.NEED_CLOSURE.getCode()));
                             log.info("触发流速偏低预警");
-                            saveException(ExceptionTypeEnum.IRON_SPEED_SLOW, String.format("流速%s吨/分钟", mMaxSpeed.get()));
                             //推送预警列表
                             getExceptionList();
-                            mWarnCountMap.put("speedMinWarn", 0);
+                            mWarnCountMap.put("speedMinWarn", new ArrayList<>());
 
+                            if (ironLoading2.get() > 0 || ironLoading3.get() > 0 || ironLoading4.get() > 0) {
+                                //堵口2
+                                saveException(ExceptionTypeEnum.NEED_CLOSURE,
+                                        String.format("铁水流速连续%d次偏低:%st,低于%st/min,但其它铁口正在出铁,请将当前铁口堵口",
+                                                StandardConstans.WARN_COUNT, speedValues.toString(), stdSpeedMin));
+                            } else {
+                                //堵口3
+                                saveException(ExceptionTypeEnum.NEED_CLOSURE,
+                                        String.format("铁水流速连续%d次偏低:%s,低于%st/min,其他铁口均未出铁,请先将其它铁口打开,再进行堵口",
+                                                StandardConstans.WARN_COUNT, speedValues.toString(), stdSpeedMin));
+                            }
                         }
                     } else if (rtIronSpeed > stdSpeedMax) {
                         log.warn("流速偏高: {} > {}", rtIronSpeed, stdSpeedMax);
                         //铁水流速高
-                        int count = mWarnCountMap.getOrDefault("speedMaxWarn", 0) + 1;
-                        mWarnCountMap.put("speedMaxWarn", count);
+                        List<Object> warnData = mWarnCountMap.getOrDefault("speedMaxWarn", new ArrayList<>());
+                        int count = warnData.isEmpty() ? 0 : ((Number) warnData.get(0)).intValue();
+                        count++;
+
+                        // 保留最新的不超过触发次数的数据
+                        if (warnData.size() > 1) {
+                            warnData = warnData.subList(0, 1); // 保留计数位置
+                        }
+                        warnData.set(0, count);
+                        warnData.add(rtIronSpeed); // 添加当前流速数据
+
+                        mWarnCountMap.put("speedMaxWarn", warnData);
                         log.info("流速偏高计数: {}/3", count);
+
                         if (count >= StandardConstans.WARN_COUNT) {
+                            // 构建包含所有异常数据的消息
+                            StringBuilder speedValues = new StringBuilder();
+                            for (int i = 1; i < warnData.size(); i++) {
+                                if (i > 1) speedValues.append("、");
+                                speedValues.append(String.format("%.2f", warnData.get(i)));
+                            }
+
                             log.info("触发流速偏高预警");
-                            PushData.send2Warn(audioMap.get(ExceptionTypeEnum.IRON_SPEED_FAST.getCode()));
-                            saveException(ExceptionTypeEnum.IRON_SPEED_FAST, String.format("连续3次偏小:%st/min、%st/min、%st/min,低于%st/min,流速偏大,建议将当前铁口堵口", mMaxSpeed.get()));
+                            PushData.send2Warn(mAudioMap.get(ExceptionTypeEnum.NEED_CLOSURE.getCode()));
+                            saveException(ExceptionTypeEnum.NEED_CLOSURE,
+                                    String.format("铁水流速连续%d次偏高:%st/min、%st/min、%st/min,高于%st/min,建议将当前铁口堵口",
+                                            StandardConstans.WARN_COUNT, speedValues.toString(), stdSpeedMax));
                             //推送预警列表
                             getExceptionList();
-                            mWarnCountMap.put("speedMaxWarn", 0);
+                            mWarnCountMap.put("speedMaxWarn", new ArrayList<>());
                         }
                     } else {
+                        // 温度或流速正常,重置异常计数
+                        int oldMinCount = 0;
+                        int oldMaxCount = 0;
+
+                        List<Object> minWarnData = mWarnCountMap.getOrDefault("speedMinWarn", new ArrayList<>());
+                        if (!minWarnData.isEmpty()) {
+                            oldMinCount = ((Number) minWarnData.get(0)).intValue();
+                        }
+
+                        List<Object> maxWarnData = mWarnCountMap.getOrDefault("speedMaxWarn", new ArrayList<>());
+                        if (!maxWarnData.isEmpty()) {
+                            oldMaxCount = ((Number) maxWarnData.get(0)).intValue();
+                        }
+
+                        if (oldMinCount > 0 || oldMaxCount > 0) {
+                            log.info("速度恢复正常 - 当前: {}t/min,重置异常计数器", rtIronSpeed);
+                        }
+
                         log.info("流速正常: {} 在 {}-{} 范围内", rtIronSpeed, stdSpeedMin, stdSpeedMax);
-                        mWarnCountMap.put("speedMinWarn", 0);
-                        mWarnCountMap.put("speedMaxWarn", 0);
+                        mWarnCountMap.put("speedMinWarn", new ArrayList<>());
+                        mWarnCountMap.put("speedMaxWarn", new ArrayList<>());
                     }
 
-                    //剩余铁量计算-流速
-                    //getCloseTime();
-
                 }
             } else if (opcData.getPointName().contains(SubscribeTagConstants.TAG_TAPHOLE2_STATUS(opcData.getServerType()))) {
                 ironLoading2.set(Integer.parseInt(opcData.getData().toString()));
@@ -2648,7 +2642,7 @@ public class DeviceEventListener extends AbstractEventListener { //
                                 log.warn("开口机超时告警触发 - 实际耗时:{}分钟 > 标准:{}分钟",
                                         minutesDiff, StandardConstans.STANDARD_OPEN_HOUR);
                                 String warnMsg = String.format("开口耗时:%s分钟", minutesDiff);
-                                PushData.send2Warn(audioMap.get(ExceptionTypeEnum.OPEN_HOUR_LONG.getCode()));
+                                PushData.send2Warn(mAudioMap.get(ExceptionTypeEnum.OPEN_HOUR_LONG.getCode()));
                                 log.warn("已发送开口机超时预警: {}", warnMsg);
                                 saveException(ExceptionTypeEnum.OPEN_HOUR_LONG, warnMsg);
                                 log.warn("已记录开口机超时异常: {}", warnMsg);
@@ -3179,7 +3173,7 @@ public class DeviceEventListener extends AbstractEventListener { //
 
         //异常列表
         //预警列表
-        TIronSchedule getExceptionList = scheduleMap.get(TaskNameConstants.TASKNAME_EXCEPTION_LIST);
+        TIronSchedule getExceptionList = mScheduleMap.get(TaskNameConstants.TASKNAME_EXCEPTION_LIST);
         if (getExceptionList != null && "1".equals(getExceptionList.getStatus())) {
             scheduledTaskManager.addTask(getExceptionList.getName(), getExceptionList.getDelay(), getExceptionList.getPeriod(), TimeUnit.SECONDS, () -> {
                 getExceptionList();
@@ -3187,7 +3181,7 @@ public class DeviceEventListener extends AbstractEventListener { //
         }
 
         //折线图数据
-        TIronSchedule getIronChart = scheduleMap.get(TaskNameConstants.TASKNAME_IRON_CHART);
+        TIronSchedule getIronChart = mScheduleMap.get(TaskNameConstants.TASKNAME_IRON_CHART);
         if (getIronChart != null && "1".equals(getIronChart.getStatus())) {
             scheduledTaskManager.addTask(getIronChart.getName(), getIronChart.getDelay(), getIronChart.getPeriod(), TimeUnit.SECONDS, () -> {
                 Map<String, Object> ironChart = tIronVisualScreenService.getIronChart(new TrendRequest());
@@ -3198,7 +3192,7 @@ public class DeviceEventListener extends AbstractEventListener { //
         }
 
         //L2定时拉取
-        TIronSchedule schedule = scheduleMap.get(TaskNameConstants.TASKNAME_IRON_L2);
+        TIronSchedule schedule = mScheduleMap.get(TaskNameConstants.TASKNAME_IRON_L2);
         if (schedule != null && "1".equals(schedule.getStatus())) {
             scheduledTaskManager.addTask(schedule.getName(), schedule.getDelay(), schedule.getPeriod(), TimeUnit.SECONDS, () -> {
                 getTheoryWeight2();
@@ -3206,7 +3200,7 @@ public class DeviceEventListener extends AbstractEventListener { //
         }
 
         //L2定时诊断列表
-        TIronSchedule ironTest = scheduleMap.get(TaskNameConstants.TASKNAME_IRON_TEST);
+        TIronSchedule ironTest = mScheduleMap.get(TaskNameConstants.TASKNAME_IRON_TEST);
         if (ironTest != null && "1".equals(ironTest.getStatus())) {
             scheduledTaskManager.addTask(ironTest.getName(), ironTest.getDelay(), ironTest.getPeriod(), TimeUnit.SECONDS, () -> {
                 List<TIronTest> latest3 = iTIronTestService.getLatest3();
@@ -3329,7 +3323,7 @@ public class DeviceEventListener extends AbstractEventListener { //
                             case TaskNameConstants.TASKNAME_CLOSURE_WARN:
                                 //堵口预警
                                 if (schedule != null && "1".equals(schedule.getStatus())) {
-                                    scheduledTaskManager.addTask(schedule.getName(), schedule.getDelay(), schedule.getPeriod(), TimeUnit.SECONDS, runnableClosureWarn());
+                                    //  scheduledTaskManager.addTask(schedule.getName(), schedule.getDelay(), schedule.getPeriod(), TimeUnit.SECONDS, runnableClosureWarn());
                                 } else {
                                     System.out.println("[DeviceEventListener] closure_warn 定时任务未添加,配置为null或status!=1");
                                 }
@@ -3393,7 +3387,7 @@ public class DeviceEventListener extends AbstractEventListener { //
                 TaskNameConstants.TASKNAME_CLOSURE_PREDICT
         };
         for (String name : taskNames) {
-            TIronSchedule schedule = scheduleMap.get(name);
+            TIronSchedule schedule = mScheduleMap.get(name);
             if (schedule != null) {
                 scheduledTaskManager.cancelTask(schedule.getName());
             }