Browse Source

杂七杂八的优化

wangmiaomiao 10 months ago
parent
commit
1ce27bed1a

+ 80 - 0
slibra-common/src/main/java/com/slibra/common/config/MyThreadPoolConfig.java

@@ -0,0 +1,80 @@
+package com.slibra.common.config;
+
+import com.alibaba.fastjson2.JSON;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.AsyncConfigurer;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.lang.reflect.Method;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ThreadPoolExecutor;
+
+@Configuration
+@EnableAsync
+//@EnableScheduling
+@Slf4j
+public class MyThreadPoolConfig implements AsyncConfigurer {
+
+    /**
+     * cpu 核心数量
+     */
+    public static final int cpuNum = Runtime.getRuntime().availableProcessors();
+
+    /**
+     * 线程池配置
+     *
+     * @return
+     */
+    @Bean("customizeExecutor")
+    @Override
+    public Executor getAsyncExecutor() {
+        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
+        // 配置核心线程池数量
+        taskExecutor.setCorePoolSize(cpuNum);
+        // 配置最大线程池数量
+        taskExecutor.setMaxPoolSize(cpuNum * 2);
+        /// 线程池所使用的缓冲队列
+        taskExecutor.setQueueCapacity(64);
+        // 等待时间 (默认为0,此时立即停止),并没等待xx秒后强制停止
+        taskExecutor.setAwaitTerminationSeconds(60);
+        // 空闲线程存活时间
+        taskExecutor.setKeepAliveSeconds(60);
+        // 等待任务在关机时完成--表明等待所有线程执行完
+        taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
+        // 线程池名称前缀
+        taskExecutor.setThreadNamePrefix("###slibra-thread-pool-");
+        // 线程池拒绝策略
+        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+        // 线程池初始化
+        taskExecutor.initialize();
+        log.info("自定义线程池初始化..............................");
+        return taskExecutor;
+    }
+
+
+    @Override
+    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
+        return new MyAsyncUncaughtExceptionHandler();
+    }
+
+    /**
+     * 自定义异常处理类
+     */
+    static class MyAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler{
+
+        @Override
+        public void handleUncaughtException(Throwable throwable, Method method, Object... objects) {
+            log.info("Exception message - {}", throwable.getMessage());
+            log.info("Method name - {}", method.getName());
+            for (Object param : objects) {
+                log.info("Paramerter value - {}", JSON.toJSON(param));
+            }
+            throw new RuntimeException( throwable.getMessage());
+        }
+    }
+    
+}

+ 7 - 7
slibra-common/src/main/java/com/slibra/common/constant/MyConstants.java

@@ -29,7 +29,7 @@ public class MyConstants {
     public static final String JIAN_BAO_END = "简报";
 
     //简报的prompt
-    public static final String JIAN_BAO_PROMPT = "作为一个工艺分析师,请生成一份#{0}日分析报告,根据我提供的详细数据,输出一份详细的分析报告。报告需数据准确、分析深入,建议具体可行,以便为水务管理和决策提供支持。整体文字在500字内,报告分为三部分:\n" +
+    public static final String JIAN_BAO_PROMPT = "作为一个工艺分析师,请生成一份#{0}日分析报告,根据我提供的详细数据,输出一份详细的分析报告。报告需数据准确、分析深入,所有小数均保留两位小数,建议具体可行,以便为水务管理和决策提供支持。整体文字在500字内,报告分为三部分:\n" +
             "\n" +
             "\n" +
             "\n" +
@@ -81,9 +81,9 @@ public class MyConstants {
     /**
      * 工单的prompt
      */
-    public static final String GONGDAN_PROMPT = "作为一个工艺分析师,请生成一份#{0}日分析报告,根据水务日报系统中提供的详细数据,按照以下要求,输出一份详细的分析报告。报告需数据准确、分析深入,建议具体可行,以便为水务管理和决策提供支持。\n" +
+    public static final String GONGDAN_PROMPT = "作为一个工艺分析师,请生成一份#{0}日分析报告,根据水务日报系统中提供的详细数据,按照以下要求,输出一份详细的分析报告。报告需数据准确、分析深入,所有小数均保留两位小数,建议具体可行,以便为水务管理和决策提供支持。\n" +
             "\n" +
-            "1、水质数据、生化数据:,以下是#{0}日详细数据,要使用表格形式展现\n" +
+            "1、水质数据、生化数据:,以下是#{0}日详细数据,必须要使用表格形式展现\n" +
             "\n" +
             "水质指标:\n" +
             "\n" +
@@ -93,18 +93,18 @@ public class MyConstants {
             "\n" +
             "二、生化指标:\n" +
             "\n" +
-            "1#好氧池\n" +
+            "#1好氧池\n" +
             "\n" +
             "pH:#{14}、  SV:#{15}、SVI:#{16}mg/L、MLSS:#{17}mg/L、MLVSS:#{18}mg/L、DO:#{19}mg/L\n" +
             "\n" +
-            "2#好氧池\n" +
+            "#2好氧池\n" +
             "\n" +
             "pH:#{20}、  SV:#{21}、SVI:#{22}mg/L、MLSS:#{23}mg/L、MLVSS:#{24}mg/L、DO:#{25}mg/L\n" +
-            "1#厌氧池\n" +
+            "#1厌氧池\n" +
             "\n" +
             "DO:#{26}mg/L\n" +
             "\n" +
-            "2#厌氧池\n" +
+            "#2厌氧池\n" +
             "\n" +
             "DO:#{27}mg/L\n" +
             "\n" +

+ 815 - 0
slibra-quartz/src/main/java/com/slibra/quartz/task/AsyncTask.java

@@ -0,0 +1,815 @@
+package com.slibra.quartz.task;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.alibaba.fastjson2.JSONWriter;
+import com.google.protobuf.ByteString;
+import com.slibra.business.domain.TXinyiDaily;
+import com.slibra.business.domain.TXinyiIndustry;
+import com.slibra.business.domain.TXinyiNormConfig;
+import com.slibra.business.domain.TXinyiWarningRecord;
+import com.slibra.business.mapper.*;
+import com.slibra.business.req.ChatReq;
+import com.slibra.business.req.DecisionReq;
+import com.slibra.common.constant.MyConstants;
+import com.slibra.common.enums.BusinessEnum;
+import com.slibra.common.utils.DateUtils;
+import com.slibra.common.utils.StringUtils;
+import com.slibra.common.utils.uuid.IdUtils;
+import inference.InferenceAPIsServiceGrpc;
+import inference.PredictionResponse;
+import inference.PredictionsRequest;
+import io.grpc.ManagedChannel;
+import io.grpc.ManagedChannelBuilder;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.*;
+
+import static com.slibra.common.constant.MyConstants.*;
+
+@Component
+@Slf4j
+public class AsyncTask {
+
+
+    @Autowired
+    private TXinyiIndustryMapper xinyiIndustryMapper;
+
+    @Autowired
+    private TXinyiNormConfigMapper xinyiNormConfigMapper;
+
+    @Autowired
+    private TXinyiWarningRecordMapper xinyiWarningRecordMapper;
+
+    @Autowired
+    private TXinyiChatRecordMapper xinyiChatRecordMapper;
+
+    @Autowired
+    private TXinyiDailyMapper xinyiDailyMapper;
+
+
+    /**
+     *
+     * 异步处理告警任务
+     * @param tXinyiIndustry
+     */
+    @Async("customizeExecutor")
+    public void handleWarning(TXinyiIndustry tXinyiIndustry){
+        log.info("进入了定时任务保存工业库数据并触发报警操作");
+        //todo 临时改一下出水总氮 模拟异常  2024年5月30日19:15:09 改在了插入数据库的时刻
+//        tXinyiIndustry.setCsTn(new BigDecimal(17));
+        //获取配置表
+        List<TXinyiNormConfig> tXinyiNormConfigs = this.xinyiNormConfigMapper.selectTXinyiNormConfigList(null);
+        if(CollectionUtils.isEmpty(tXinyiNormConfigs))
+            throw new RuntimeException("未查询到配置信息");
+        TXinyiNormConfig normConfig = tXinyiNormConfigs.get(0);
+
+        //水质报警
+        this.handleSZWarning(tXinyiIndustry, normConfig);
+
+        //2024年5月28日14:14:26  下面是新增的 生化报警处理
+        this.handleSHWarning(tXinyiIndustry, normConfig);
+    }
+
+    private void handleSHWarning(TXinyiIndustry tXinyiIndustry, TXinyiNormConfig normConfig) {
+        //判断对应指标是否报警  然后调研大模型获取决策信息
+        BigDecimal jsSlq = tXinyiIndustry.getJsSlq();
+        //内回流比报警
+        BigDecimal nhlbSjz = normConfig.getNhlbSjz();//400
+        BigDecimal nhlbnkSxz = normConfig.getNhlbnkSxz();//360
+        BigDecimal nhlbqdsl = normConfig.getNHLBQDSL();
+        BigDecimal nhlbdsjll = normConfig.getNHLBDSJLL();
+        BigDecimal nhlbgzxl = normConfig.getNHLBGZXL();
+        if(!Objects.isNull(jsSlq) && !Objects.isNull(nhlbnkSxz) && !Objects.isNull(nhlbqdsl)
+                && !Objects.isNull(nhlbdsjll) && !Objects.isNull(nhlbgzxl)){
+            BigDecimal divide = nhlbqdsl.multiply(nhlbdsjll).multiply(nhlbgzxl).divide(jsSlq, 4, RoundingMode.HALF_UP);
+            if(!Objects.isNull(nhlbSjz)){
+                handleXinYiWarningsSH(nhlbSjz, divide, nhlbnkSxz, BusinessEnum.WarningCategoryEnum.NHLB.getCode(), tXinyiIndustry, normConfig);
+            }
+        }
+
+        //外回流比报警
+        BigDecimal whlbqdsl = normConfig.getWHLBQDSL();
+        BigDecimal whlbdsjll = normConfig.getWHLBDSJLL();
+        BigDecimal whlbgzxl = normConfig.getWHLBGZXL();
+        BigDecimal whlbnkXxz = normConfig.getWhlbnkXxz();
+        BigDecimal whlbSjz = normConfig.getWhlbSjz();
+        if(!Objects.isNull(whlbqdsl) && !Objects.isNull(whlbdsjll) && !Objects.isNull(whlbgzxl)){
+            BigDecimal divide = whlbqdsl.multiply(whlbdsjll).multiply(whlbgzxl).divide(jsSlq, 4, RoundingMode.HALF_UP);
+            if(!Objects.isNull(whlbSjz)){
+                handleXinYiWarningsSH(whlbSjz, divide, whlbnkXxz, BusinessEnum.WarningCategoryEnum.WHLB.getCode(), tXinyiIndustry, normConfig);
+            }
+        }
+
+
+        //最新的一条日报数据
+        List<TXinyiDaily> tXinyiDailies = this.xinyiDailyMapper.selectTXinyiDailyList(null);
+        if(CollectionUtils.isEmpty(tXinyiDailies))
+            return;//肯定不会出现这种情况 因为有很多历史数据了
+        TXinyiDaily tXinyiDaily = tXinyiDailies.get(0);
+        log.info("生化报警获取日报的最新的一条数据为{}", JSON.toJSONString(tXinyiDaily));
+        BigDecimal jsBod5 = tXinyiDaily.getJsBod5();
+
+        //污泥负荷(需要从日报获取数据) 计算 + 部分数据从日报获取
+        //污泥负荷=[Ls]=24*([BOD_in]-[BOD_off])*[Q_in]/[MLSS]/([V_hao]+[V_que]+[V_yan])/2 kgBOD/(kgMLSS·d)
+        //todo  后面再加 计算太复杂
+
+        //碳氮比(需要从日报获取数据)
+        //进水碳氮比=[b]=[BOD_in]/[TN_in]
+        BigDecimal jsTn = tXinyiIndustry.getJsTn();
+        if(!Objects.isNull(jsBod5) && !Objects.isNull(jsTn)){
+            BigDecimal divide = jsBod5.divide(jsTn, 4, RoundingMode.HALF_UP);
+            BigDecimal jstdbnkzSxz = normConfig.getJstdbnkzSxz();
+            BigDecimal cstdbSjz = normConfig.getCstdbSjz();
+            if(!Objects.isNull(whlbSjz)){
+                handleXinYiWarningsSH(cstdbSjz, divide, jstdbnkzSxz, BusinessEnum.WarningCategoryEnum.TDB.getCode(), tXinyiIndustry, normConfig);
+            }
+        }
+
+        //碳磷比(需要从日报获取数据)
+        //进水碳磷比=[c]=[BOD_in]/[TP_in]
+        BigDecimal jsTp = tXinyiIndustry.getJsTp();
+        BigDecimal jstlbSjz = normConfig.getJstlbSjz();
+        if(!Objects.isNull(jsBod5) && !Objects.isNull(jsTp)){
+            BigDecimal divide = jsBod5.divide(jsTp, 4, RoundingMode.HALF_UP);
+            BigDecimal jstlbNkz = normConfig.getJstlbNkz();
+            if(!Objects.isNull(jstlbSjz)){
+                handleXinYiWarningsSH(jstlbSjz, divide, jstlbNkz, BusinessEnum.WarningCategoryEnum.TLB.getCode(), tXinyiIndustry, normConfig);
+            }
+        }
+
+        //BOD比COD(需要从日报获取数据)
+        //进水BOD与COD比值数据=[d]=[BOD_in]/[COD_in]
+        BigDecimal jsCod = tXinyiIndustry.getJsCod();
+        if(!Objects.isNull(jsBod5) && !Objects.isNull(jsCod)){
+            BigDecimal jsbodycodbzSzj = normConfig.getJsbodycodbzSzj();
+            String jsbodycodbzGkz = normConfig.getJsbodycodbzGkz();
+            if(StringUtils.isNotBlank(jsbodycodbzGkz) && jsbodycodbzGkz.contains("-")){
+                String[] split = jsbodycodbzGkz.split("-");
+                BigDecimal gkz = new BigDecimal(split[1]);
+                BigDecimal divide = jsBod5.divide(jsCod, 4, RoundingMode.HALF_UP);
+                handleXinYiWarningsSH(gkz, divide, jsbodycodbzSzj, BusinessEnum.WarningCategoryEnum.BODCODB.getCode(), tXinyiIndustry, normConfig);
+            }
+
+        }
+
+        //好氧区DO(一池)
+        BigDecimal shcHyOneDo = tXinyiIndustry.getOneHymdDo();
+        BigDecimal hycrjysjzSxz = normConfig.getHycrjysjzSxz();
+        BigDecimal hycrjyNkz = normConfig.getHycrjyNkz();
+        if(!Objects.isNull(shcHyOneDo) && !Objects.isNull(hycrjysjzSxz)){
+            handleXinYiWarningsSH(hycrjysjzSxz, shcHyOneDo, hycrjyNkz, BusinessEnum.WarningCategoryEnum.HYQDO_ONE.getCode(), tXinyiIndustry, normConfig);
+        }
+        //好氧区DO(二池)
+        BigDecimal shcHyTwoDo = tXinyiIndustry.getTwoHymdDo();
+        if(!Objects.isNull(shcHyTwoDo) && !Objects.isNull(hycrjysjzSxz)){
+            handleXinYiWarningsSH(hycrjysjzSxz, shcHyTwoDo, hycrjyNkz, BusinessEnum.WarningCategoryEnum.HYQDO_TWO.getCode(), tXinyiIndustry, normConfig);
+        }
+
+        //气水比(需要从日报获取数据)
+        BigDecimal gfjgzts = normConfig.getGFJGZTS();
+        BigDecimal gfjckll = normConfig.getGFJCKLL();
+        BigDecimal shcqbSjz = normConfig.getShcqbSjz();
+        if(!Objects.isNull(gfjgzts) && !Objects.isNull(gfjckll) && !Objects.isNull(shcqbSjz) && !Objects.isNull(jsSlq)){
+            BigDecimal qsb = gfjgzts.multiply(gfjckll).divide(jsSlq, 4, RoundingMode.HALF_UP);
+            BigDecimal shcqbNkz = normConfig.getShcqbNkz();
+            handleXinYiWarningsSH(shcqbSjz, qsb, shcqbNkz, BusinessEnum.WarningCategoryEnum.WHLB.getCode(), tXinyiIndustry, normConfig);
+        }
+    }
+
+
+    /**
+     * 处理信义生化报警的逻辑 统一处理
+     * @param bzz
+     * @param currentVal
+     * @param gkz
+     * @param category
+     * @param tXinyiIndustry
+     * @param normConfig
+     */
+    private void handleXinYiWarningsSH(BigDecimal bzz, BigDecimal currentVal, BigDecimal gkz, String category, TXinyiIndustry tXinyiIndustry, TXinyiNormConfig normConfig) {
+        BigDecimal multiply = bzz.multiply(new BigDecimal(MyConstants.SCALE_VALUE));
+        TXinyiWarningRecord tXinyiWarningRecord = new TXinyiWarningRecord();
+        /*String category = BusinessEnum.WarningCategoryEnum.CS_AD.getCode();*/
+        tXinyiWarningRecord.setStatus(0);
+        tXinyiWarningRecord.setType(1);
+        tXinyiWarningRecord.setCategory(category);
+        tXinyiWarningRecord.setTime(DateUtils.getNowDate());
+        tXinyiWarningRecord.setWarningVal(currentVal);
+        tXinyiWarningRecord.setDesignVal(bzz);
+        tXinyiWarningRecord.setControlVal(gkz);
+        tXinyiWarningRecord.setCreateBy(WARNING_DEFAULT_CREATE);
+        tXinyiWarningRecord.setCreateTime(DateUtils.getNowDate());
+
+        //2024年5月25日17:52:33  如果工业库获取不到数据,也触发报警,但是不调用决策接口
+        if (Objects.isNull(currentVal)) {
+            tXinyiWarningRecord.setReason(category + EXCEPTION_WARNING);
+            tXinyiWarningRecord.setLevel(WARNING_LEVEL_NO_DATE);
+        } else if (currentVal.compareTo(multiply) > 0) {//一级
+            tXinyiWarningRecord.setReason(category + CHAOBIAO_WARNING);
+            tXinyiWarningRecord.setLevel(WARNING_LEVEL_ONE);
+        } else if (currentVal.compareTo(bzz) >= 0 && currentVal.compareTo(multiply) <= 0) {//二级
+            tXinyiWarningRecord.setReason(category + CHAOBIAO_WARNING);
+            tXinyiWarningRecord.setLevel(WARNING_LEVEL_TWO);
+        } else if (!Objects.isNull(gkz) && currentVal.compareTo(gkz) > 0) {
+            tXinyiWarningRecord.setReason(category + CHAOGUANKONG_WARNING);
+            tXinyiWarningRecord.setLevel(WARNING_LEVEL_THREE);
+        } else {
+            tXinyiWarningRecord = null;//这种的无需处理
+        }
+
+        //当前状态正常 需要查询历史有无正在报警的数据,如果有,将报警状态改完2(系统自动关闭)
+        List<TXinyiWarningRecord> tXinyiWarningRecords = this.xinyiWarningRecordMapper.selectTXinyiWarningRecordList(TXinyiWarningRecord.builder().delFlag(0).type(1).category(category).status(0).build());
+        if(Objects.isNull(tXinyiWarningRecord)){//数据正常,无告警信息
+            if(!CollectionUtils.isEmpty(tXinyiWarningRecords)){
+                log.info( "{}:现在恢复正常,历史报警数据为{}", category,JSON.toJSONString(tXinyiWarningRecords));
+                for (TXinyiWarningRecord xinyiWarningRecord : tXinyiWarningRecords) {
+                    xinyiWarningRecord.setStatus(2);
+                    Date nowDate = DateUtils.getNowDate();
+                    xinyiWarningRecord.setOffTime(nowDate);
+                    xinyiWarningRecord.setUpdateTime(nowDate);
+                    xinyiWarningRecord.setUpdateBy(WARNING_DEFAULT_CREATE);
+                    this.xinyiWarningRecordMapper.updateTXinyiWarningRecord(xinyiWarningRecord);
+                }
+            }
+        }else{//有新的告警信息
+            if(CollectionUtils.isEmpty(tXinyiWarningRecords)){//之前没有告警记录
+                //保存到数据库中
+                this.xinyiWarningRecordMapper.insertTXinyiWarningRecord(tXinyiWarningRecord);
+                if(WARNING_LEVEL_NO_DATE.equals(tXinyiWarningRecord.getLevel())){
+                    //只保存一个普通的问答记录 不需要调用决策信息,但是实时数据还是要记录的
+                    this.addChatRecordByWarning(tXinyiWarningRecord, tXinyiIndustry, normConfig);
+                }else {
+                    //继续调用决策(普通问答)
+                    this.askBigModelForSHWarning(tXinyiWarningRecord, tXinyiIndustry, normConfig);
+                }
+            }else{
+                log.info("{}:之前已经有过告警记录了,且还是继续报警,无需重复添加报警,但是决策仍然要调用", category);
+                for (TXinyiWarningRecord xinyiWarningRecord : tXinyiWarningRecords) {//理论上只有一个的
+                    if(WARNING_LEVEL_NO_DATE.equals(tXinyiWarningRecord.getLevel())){
+                        //只保存一个普通的问答记录 不需要调用决策信息,但是实时数据还是要记录的
+                        this.addChatRecordByWarning(tXinyiWarningRecord, tXinyiIndustry, normConfig);
+                    }else {
+                        //继续调用决策(普通问答)
+                        this.askBigModelForSHWarning(xinyiWarningRecord, tXinyiIndustry, normConfig);
+                    }
+                }
+            }
+        }
+    }
+
+
+    private void handleSZWarning(TXinyiIndustry tXinyiIndustry, TXinyiNormConfig normConfig) {
+        //出水相关
+        //出水COD报警
+        BigDecimal csCod = tXinyiIndustry.getCsCod();
+        BigDecimal cscodBzz = normConfig.getCscodBzz();
+        BigDecimal cscodGkz = normConfig.getCscodGkz();
+        if(!Objects.isNull(cscodBzz)){
+            handleXinYiWarningsCs(cscodBzz, csCod, cscodGkz, BusinessEnum.WarningCategoryEnum.CS_COD.getCode(), tXinyiIndustry, normConfig);
+        }
+
+        //出水总磷超标报警
+        BigDecimal csTp = tXinyiIndustry.getCsTp();
+        BigDecimal cszlBzz = normConfig.getCszlBzz();
+        BigDecimal cszlGkz = normConfig.getCszlGkz();
+        if(!Objects.isNull(cszlBzz)){
+            handleXinYiWarningsCs(cszlBzz, csTp, cszlGkz, BusinessEnum.WarningCategoryEnum.CS_ZL.getCode(), tXinyiIndustry, normConfig);
+        }
+
+
+        //出水总氮超标报警
+        BigDecimal csTn = tXinyiIndustry.getCsTn();
+        BigDecimal cszzBzz = normConfig.getCszzBzz();
+        BigDecimal cszzGkz = normConfig.getCszzGkz();
+        if(!Objects.isNull(cszzBzz)){
+            handleXinYiWarningsCs(cszzBzz, csTn, cszzGkz, BusinessEnum.WarningCategoryEnum.CS_ZD.getCode(), tXinyiIndustry, normConfig);
+        }
+
+        //出水氨氮超标报警
+        BigDecimal csNh3 = tXinyiIndustry.getCsNh3();
+        BigDecimal csadBzz = normConfig.getCsadBzz();
+        BigDecimal csadGkz = normConfig.getCsadGkz();
+        if(!Objects.isNull(csadBzz)){
+            handleXinYiWarningsCs(csadBzz, csNh3, csadGkz, BusinessEnum.WarningCategoryEnum.CS_AD.getCode(), tXinyiIndustry, normConfig);
+        }
+
+        //出水SS超标报警
+        BigDecimal csSS = tXinyiIndustry.getCsSs();
+        BigDecimal csSSBzz = normConfig.getCsssBzz();
+        BigDecimal csssGkz = normConfig.getCsssGkz();
+        if(!Objects.isNull(csSSBzz)){
+            handleXinYiWarningsCs(csSSBzz, csSS, csssGkz, BusinessEnum.WarningCategoryEnum.CS_SS.getCode(), tXinyiIndustry, normConfig);
+        }
+
+        //进水相关报警
+        //进水总磷超标报警
+        BigDecimal jsTp = tXinyiIndustry.getJsTp();
+        BigDecimal jszlSjz = normConfig.getJszlSjz();
+        if(!Objects.isNull(jszlSjz)){
+            handleXinYiWarningRecordJS(jszlSjz, jsTp, BusinessEnum.WarningCategoryEnum.JS_ZL.getCode(), tXinyiIndustry, normConfig);
+        }
+
+        //进水COD超标报警
+        BigDecimal jsCod = tXinyiIndustry.getJsCod();
+        BigDecimal jscodSjz = normConfig.getJscodSjz();
+        if(!Objects.isNull(jscodSjz)){
+            handleXinYiWarningRecordJS(jscodSjz, jsCod, BusinessEnum.WarningCategoryEnum.JS_COD.getCode(), tXinyiIndustry, normConfig);
+        }
+
+        //进水总氮超标报警
+        BigDecimal jsTn = tXinyiIndustry.getJsTn();
+        BigDecimal jszdSjz = normConfig.getJszdSjz();
+        if(!Objects.isNull(jszdSjz)){
+            handleXinYiWarningRecordJS(jszdSjz, jsTn, BusinessEnum.WarningCategoryEnum.JS_ZD.getCode(), tXinyiIndustry, normConfig);
+        }
+
+        //进水氨氮超标报警
+        BigDecimal jsNh3 = tXinyiIndustry.getJsNh3();
+        BigDecimal jsadSjz = normConfig.getJsadSjz();
+        if(!Objects.isNull(jsadSjz)){
+            handleXinYiWarningRecordJS(jsadSjz, jsNh3, BusinessEnum.WarningCategoryEnum.JS_AD.getCode(), tXinyiIndustry, normConfig);
+        }
+
+        //进水SS超标报警
+        BigDecimal jsSS = tXinyiIndustry.getJsSs();
+        BigDecimal jsSSSjz = normConfig.getJsssSjz();
+        if(!Objects.isNull(jsSSSjz)){
+            handleXinYiWarningRecordJS(jsSSSjz, jsSS, BusinessEnum.WarningCategoryEnum.JS_SS.getCode(), tXinyiIndustry, normConfig);
+        }
+    }
+
+
+
+    private void askBigModelForSHWarning(TXinyiWarningRecord xinyiWarningRecord, TXinyiIndustry tXinyiIndustry, TXinyiNormConfig normConfig) {
+        log.info("进入了后台接口调⽤⼤模型获取问答结果处理");
+        StringBuilder sb = new StringBuilder();
+        String sessionId = IdUtils.simpleUUID();
+        ChatReq chatReq = new ChatReq();
+//        String ipAddr = IpUtils.getIpAddr();//获取用户的ip地址 传给大模型
+        String ipAddr = "";//获取用户的ip地址 传给大模型  定时任务获取不到ip地址
+        int counts = 1;//默认是第一次
+        //这种问答 没有历史问答的概念 直接把问题扔进去就行 无需查询历史记录
+        List<String> historyDates = new ArrayList<>();
+        //构建问题(替换提示词中的占位符)
+        String shWarningPrompt = SH_WARNING_PROMPT;
+        shWarningPrompt =shWarningPrompt.replace("#{0}", xinyiWarningRecord.getReason());
+        shWarningPrompt =shWarningPrompt.replace("#{1}", String.valueOf(xinyiWarningRecord.getDesignVal()));
+        shWarningPrompt =shWarningPrompt.replace("#{2}", String.valueOf(xinyiWarningRecord.getControlVal()));
+        shWarningPrompt =shWarningPrompt.replace("#{3}", String.valueOf(xinyiWarningRecord.getWarningVal()));
+        historyDates.add(shWarningPrompt);
+        // 获取输出流
+        ManagedChannel channel = null;
+        try {
+            channel = ManagedChannelBuilder.forAddress("10.0.0.24", 17070)
+                    .usePlaintext()
+                    .build();
+            InferenceAPIsServiceGrpc.InferenceAPIsServiceBlockingStub stub = InferenceAPIsServiceGrpc.newBlockingStub(channel);
+            String dataJson = "{\"bot_id\":\"721\",\"exp_id\":\"721\",\"session_id\":\"" + sessionId + "\",\"use_rag\":\"true\",\"prompt\":\"你是⼀个资深⽔务领域专家,能回答各种⽔务相关问题\",\"history_dia\":" + JSON.toJSONString(historyDates) + ",\"generate_args\":{\"max_new_tokens\":2048,\"max_length\":4096,\"num_beams\":1,\"do_sample\":true,\"top_p\":0.7,\"temperature\":0.95},\"extra\":{ \"ip_address\": \"" + ipAddr  + "\" },\"strengthen\":" + (true) + "}";
+            log.info("请求大模型的问答参数为{}", dataJson);
+            PredictionsRequest request = PredictionsRequest.newBuilder()
+                    .setModelName("slibra_bot")
+                    .putInput("method", ByteString.copyFrom("infer_stream", "utf-8"))//推理
+                    .putInput("data", ByteString.copyFrom(dataJson, "utf-8"))
+                    .buildPartial();
+            Iterator<PredictionResponse> predictions = stub.streamPredictions(request);
+            //将结果记录到问答表
+            while (predictions.hasNext()) {
+                String responseStr = predictions.next().getPrediction().toStringUtf8();
+                log.info("大模型问答返回的原始结果为{}", responseStr);
+                responseStr = JSON.parseObject(responseStr).getString("message");
+                if("complete".equals(responseStr)){
+                    log.info("结尾语句并且是非JSON,无需处理");
+                }else{
+                    sb.append(responseStr);
+                }
+            }
+            //将问答更新到数据库中
+            chatReq.setSessionId(sessionId);
+            chatReq.setType(1);//0问答 1决策 2本地 3仿真预测
+            chatReq.setModule(3);//0专家问答 1智能工单 2智能体助手 3告警 4简报
+            String showVal = this.buildShowValue(xinyiWarningRecord, tXinyiIndustry, normConfig);
+            chatReq.setShowVal(showVal);
+            chatReq.setQuestion(shWarningPrompt);
+            chatReq.setAnswer(sb.toString());
+            chatReq.setWarningId(String.valueOf(xinyiWarningRecord.getId()));
+            chatReq.setCounts(counts);//问答次数
+            chatReq.setUserId(WARNING_DEFAULT_CREATE);
+            chatReq.setCreateBy(WARNING_DEFAULT_CREATE);
+            chatReq.setCreateTime(DateUtils.getNowDate());
+            this.xinyiChatRecordMapper.insertTXinyiChatRecord(chatReq);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        } finally {
+            // 关闭输出流
+            channel.shutdown();
+        }
+    }
+
+    /**
+     * 调用大模型获取决策结果 并同时记录对应信息到聊天记录表中
+     *
+     * @param tXinyiWarningRecord
+     * @param tXinyiIndustry
+     * @param normConfig
+     */
+    private void handleDecision(TXinyiWarningRecord tXinyiWarningRecord, TXinyiIndustry tXinyiIndustry, TXinyiNormConfig normConfig) {
+        log.info("进入了调⽤大模型决策接口");
+        ChatReq chatReq = new ChatReq();
+//        StringBuilder sb = new StringBuilder();
+        //大模型结果 放入一个结合中
+        List<String> resultData = new ArrayList<>();
+        //决策和问答不一样 没有历史的概念 所以sessionId都是新的  次数都是1
+        String sessionId = IdUtils.simpleUUID();
+        String feedback = chatReq.getFeedback();
+        //决策请求的业务参数
+//        List<HashMap<String, Object>> list = this.xinyiIndustryMapper.selectLast10RecordsForDecision();
+        //2024年5月21日15:23:07 这里不能用关联查询处理,日报要获取最新的一条而不是今日的数据。
+        List<DecisionReq> decisionReqs = this.xinyiIndustryMapper.selectLast10RecordsForDecisionOnlyIndustry();
+        if(!CollectionUtils.isEmpty(decisionReqs)){
+            for (DecisionReq decisionReq : decisionReqs) {
+                //处理日报数据
+                TXinyiDaily daily = this.xinyiDailyMapper.selectNewestData();
+                if(!Objects.isNull(daily)){
+                    decisionReq.setT(daily.getJsSw());
+                    decisionReq.setSVI(daily.getWntjzsAll());
+                    decisionReq.setSV(daily.getWncjbAll());
+                    decisionReq.setMlvss(daily.getHfxwnndAll());
+                    decisionReq.setDoAna(daily.getYycRjyAll());
+                    decisionReq.setDoQue(daily.getQycRjyAll());
+                    //2024年5月26日11:59:02 干污泥量数据做了同步
+                    decisionReq.setGwnl(daily.getGWNL());
+                    BigDecimal jsBod5 = daily.getJsBod5();
+                    decisionReq.setBodIn(jsBod5);
+                    BigDecimal tpIn = decisionReq.getTpIn();
+                    BigDecimal tnIn = decisionReq.getTnIn();
+                    if(!Objects.isNull(jsBod5)){
+                        if(!Objects.isNull(tpIn) && tpIn.compareTo(new BigDecimal("0")) >0){
+                            decisionReq.setC(jsBod5.divide(tpIn, 4, RoundingMode.HALF_UP));
+                        }
+                        if(!Objects.isNull(tnIn) && tnIn.compareTo(new BigDecimal("0")) >0){
+                            decisionReq.setB(jsBod5.divide(tnIn, 4, RoundingMode.HALF_UP));
+                        }
+                    }
+                }
+            }
+        }
+        String rows = JSON.toJSONString(decisionReqs, JSONWriter.Feature.WriteNulls);
+        // 获取输出流
+        ManagedChannel channel = null;
+        String dataJson = "";
+        try {
+            channel = ManagedChannelBuilder.forAddress("10.0.0.24", 17070)
+                    .usePlaintext()
+                    .build();
+            InferenceAPIsServiceGrpc.InferenceAPIsServiceBlockingStub stub = InferenceAPIsServiceGrpc.newBlockingStub(channel);
+            dataJson = "{\"bot_id\":\"b00001\",\"exp_id\":\"721\",\"norm\":\"" + tXinyiWarningRecord.getCategory() + "\",\"feedback\":" + feedback + ",\"session_id\":" + "\"" + sessionId + "\"" + ",\"generate_args\":{\"max_new_tokens\":1024,\"max_length\":4096,\"num_beams\":1,\"do_sample\":true,\"top_p\":0.7,\"temperature\":0.95},\"extra\":{\"rows\":" +  rows + "}}";
+            log.info("请求大模型的决策的参数为{}", dataJson);
+            PredictionsRequest request = PredictionsRequest.newBuilder()
+                    .setModelName("slibra_bot")
+                    .putInput("method", ByteString.copyFrom("decision_stream", "utf-8"))//推理
+                    .putInput("data", ByteString.copyFrom(dataJson, "utf-8"))
+                    .buildPartial();
+            Iterator<PredictionResponse> predictions = stub.streamPredictions(request);
+            while (predictions.hasNext()) {
+                String responseStr = predictions.next().getPrediction().toStringUtf8();
+                log.info("决策流式返回的结果是{}", responseStr);
+
+                //2024年5月25日16:37:16  按照大模型返回的类型解析数据
+                String biz = JSON.parseObject(responseStr).getString("biz");
+                if(BusinessEnum.BigModelBizEnum.OK.getCode().equals(biz)){
+                    log.info("结尾语句并且是非JSON,无需处理");
+                    //结束语句也流式输出,但是并不记录下来  2024年5月24日11:15:23 也不返回前端
+                    /*outputStream.write(responseStr.getBytes());
+                    outputStream.flush();*/
+                }else if(BusinessEnum.BigModelBizEnum.DECISION_DEBUGGER.getCode().equals(biz)){
+                    log.info("中间过程,目前只打印日志,不记录数据,也不返回给前端,返回数据为{}", responseStr);
+                    //结束语句也流式输出,但是并不记录下来  2024年5月24日11:15:23 也不返回前端
+                    /*outputStream.write(responseStr.getBytes());
+                    outputStream.flush();*/
+                }else{//其他 要么错误 要么alert 要么出的报告
+//                    sb.append(responseStr);
+                    resultData.add(responseStr);
+                }
+            }
+        } catch (Exception e) {
+//            throw new RuntimeException(e);
+            log.error("定时任务处理告警调用决策异常,异常信息为{}", JSON.toJSONString(e));
+            resultData.add("{\"biz\":\"ERROR\",\"message\":\"大模型分析数据异常,请稍后再试\"}");
+        } finally {
+            log.info("决策最终要保存的数据是{}", JSON.toJSONString(resultData));
+            //保存聊天记录
+            //将问答更新到数据库中
+            chatReq.setSessionId(sessionId);
+            chatReq.setType(1);//0问答 1决策
+            chatReq.setModule(3);
+            /*String userId = SecurityUtils.getUserId().toString();
+            String username = SecurityUtils.getUsername();*/
+            chatReq.setUserId(WARNING_DEFAULT_CREATE);
+            String showVal = this.buildShowValue(tXinyiWarningRecord, tXinyiIndustry, normConfig);
+            chatReq.setShowVal(showVal);//前端展示的数据和提问的数据不一致
+            chatReq.setQuestion(dataJson);
+            chatReq.setAnswer(JSON.toJSONString(resultData));
+            chatReq.setWarningId(String.valueOf(tXinyiWarningRecord.getId()));
+            chatReq.setCounts(1);//问答次数
+
+            chatReq.setCreateBy(WARNING_DEFAULT_CREATE);
+            chatReq.setCreateTime(DateUtils.getNowDate());
+            this.xinyiChatRecordMapper.insertTXinyiChatRecord(chatReq);
+            // 关闭输出流
+            if(!Objects.isNull(channel))
+                channel.shutdown();
+        }
+    }
+
+    private String buildShowValue(TXinyiWarningRecord tXinyiWarningRecord, TXinyiIndustry tXinyiIndustry, TXinyiNormConfig normConfig) {
+        JSONObject result = new JSONObject();
+        JSONObject basic = new JSONObject();
+        Integer status = tXinyiWarningRecord.getStatus();
+        Date warningTime = tXinyiWarningRecord.getTime();
+        int count = DateUtils.differentHoursByMillisecond(warningTime, DateUtils.getNowDate()) + 1;
+        basic.put("title", tXinyiWarningRecord.getReason());
+        basic.put("报警时间", DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM ,warningTime));
+        basic.put("报警值", tXinyiWarningRecord.getWarningVal());
+        basic.put("标准值", tXinyiWarningRecord.getDesignVal());
+        basic.put("管控值", tXinyiWarningRecord.getControlVal());
+        basic.put("报警次数", Math.min(count, MAX_COUNT));
+        if(tXinyiWarningRecord.getType() != 2)
+            basic.put("状态", status == 0 ? "报警中" : status == 1 ? "用户关闭" : status == 2 ? "系统关闭" : "应急处理中");
+        else
+            basic.put("状态", status == 0 ? "预警中" : "已完成");
+        //2024年5月27日14:04:22  额外返回2个字段 [管控值 和 告警级别]  返回的json没有数据是因为value没有值
+//        basic.put("管控值", tXinyiWarningRecord.getControlVal());
+        basic.put("告警级别", tXinyiWarningRecord.getLevel());
+        result.put("basic", basic);
+        JSONObject jsData = getJsonObject(tXinyiIndustry, normConfig);//进水数据
+        result.put("jsData", jsData);
+        JSONObject csData = getCsonObject(tXinyiIndustry, normConfig);//出水数据
+        result.put("csData", csData);
+        return JSON.toJSONString(result, JSONWriter.Feature.WriteNulls);
+    }
+
+    private static JSONObject getJsonObject(TXinyiIndustry tXinyiIndustry, TXinyiNormConfig normConfig) {
+        JSONObject jsData = new JSONObject();
+        HashMap<Object, Object> temp1 = new HashMap<>();
+        BigDecimal jsSlq = tXinyiIndustry.getJsSlq();
+        temp1.put("value", jsSlq);
+        temp1.put("exceed", jsSlq.compareTo(normConfig.getJsslSjz()) >0);
+        jsData.put("流量", temp1);
+        HashMap<Object, Object> temp2 = new HashMap<>();
+        BigDecimal jsCod = tXinyiIndustry.getJsCod();
+        temp2.put("value", jsCod);
+        temp2.put("exceed", jsCod.compareTo(normConfig.getJscodSjz()) > 0);
+        jsData.put("COD", temp2);
+        HashMap<Object, Object> temp3 = new HashMap<>();
+        BigDecimal jsNh3 = tXinyiIndustry.getJsNh3();
+        temp3.put("value", jsNh3);
+        temp3.put("exceed", jsNh3.compareTo(normConfig.getJsadSjz()) > 0);
+        jsData.put("NH3-N", temp3);
+        HashMap<Object, Object> temp4 = new HashMap<>();
+        BigDecimal jsTp = tXinyiIndustry.getJsTp();
+        temp4.put("value", jsTp);
+        temp4.put("exceed", jsTp.compareTo(normConfig.getJszlSjz()) > 0);
+        jsData.put("TP", temp4);
+        HashMap<Object, Object> temp5 = new HashMap<>();
+        BigDecimal jsSs = tXinyiIndustry.getJsSs();
+        temp5.put("value", jsSs);
+        temp5.put("exceed", jsSs.compareTo(normConfig.getJsssSjz()) > 0);
+        jsData.put("SS", temp5);
+        HashMap<Object, Object> temp6 = new HashMap<>();
+        BigDecimal jsTn = tXinyiIndustry.getJsTn();
+        temp6.put("value", jsTn);
+        temp6.put("exceed", jsTn.compareTo(normConfig.getJszdSjz()) > 0);
+        jsData.put("TN", temp6);
+        return jsData;
+    }
+
+
+    private static JSONObject getCsonObject(TXinyiIndustry tXinyiIndustry, TXinyiNormConfig normConfig) {
+        JSONObject csData = new JSONObject();
+        HashMap<Object, Object> temp1 = new HashMap<>();
+        BigDecimal csSlq = tXinyiIndustry.getCsSlqc();
+        temp1.put("value", csSlq);
+        temp1.put("exceed", false);//出水水量没有管控值
+        csData.put("流量", temp1);
+        HashMap<Object, Object> temp2 = new HashMap<>();
+        BigDecimal csCod = tXinyiIndustry.getCsCod();
+        temp2.put("value", csCod);
+        temp2.put("exceed", csCod.compareTo(normConfig.getCscodGkz()) > 0);
+        csData.put("COD", temp2);
+        HashMap<Object, Object> temp3 = new HashMap<>();
+        BigDecimal csNh3 = tXinyiIndustry.getCsNh3();
+        temp3.put("value", csNh3);
+        temp3.put("exceed", csNh3.compareTo(normConfig.getCsadGkz()) > 0);
+        csData.put("NH3-N", temp3);
+        HashMap<Object, Object> temp4 = new HashMap<>();
+        BigDecimal csTp = tXinyiIndustry.getCsTp();
+        temp4.put("value", csTp);
+        temp4.put("exceed", csTp.compareTo(normConfig.getCszlGkz()) > 0);
+        csData.put("TP", temp4);
+        HashMap<Object, Object> temp5 = new HashMap<>();
+        BigDecimal csSs = tXinyiIndustry.getCsSs();
+        temp5.put("value", csSs);
+        temp5.put("exceed", csSs.compareTo(normConfig.getCsssGkz()) > 0);
+        csData.put("SS", temp5);
+        HashMap<Object, Object> temp6 = new HashMap<>();
+        BigDecimal csTn = tXinyiIndustry.getCsTn();
+        temp6.put("value", csTn);
+        temp6.put("exceed", csTn.compareTo(normConfig.getCszzGkz()) > 0);
+        csData.put("TN", temp6);
+        return csData;
+    }
+
+    /**
+     * 通过输入的值 生成对应类型的报警对象(出水)
+     *
+     * @param csBzz
+     * @param currentVal
+     * @param csGkz
+     * @param category
+     * @param tXinyiIndustry
+     * @param normConfig
+     * @return
+     */
+    private void handleXinYiWarningsCs(BigDecimal csBzz, BigDecimal currentVal, BigDecimal csGkz, String category, TXinyiIndustry tXinyiIndustry, TXinyiNormConfig normConfig) {
+        BigDecimal multiply = csBzz.multiply(new BigDecimal(MyConstants.SCALE_VALUE));
+        TXinyiWarningRecord tXinyiWarningRecord = new TXinyiWarningRecord();
+        /*String category = BusinessEnum.WarningCategoryEnum.CS_AD.getCode();*/
+        tXinyiWarningRecord.setStatus(0);
+        tXinyiWarningRecord.setType(0);
+        tXinyiWarningRecord.setCategory(category);
+        tXinyiWarningRecord.setTime(DateUtils.getNowDate());
+        tXinyiWarningRecord.setWarningVal(currentVal);
+        tXinyiWarningRecord.setDesignVal(csBzz);
+        tXinyiWarningRecord.setControlVal(csGkz);
+        tXinyiWarningRecord.setCreateBy(WARNING_DEFAULT_CREATE);
+        tXinyiWarningRecord.setCreateTime(DateUtils.getNowDate());
+
+        //2024年5月25日17:52:33  如果工业库获取不到数据,也触发报警,但是不调用决策接口
+        if(Objects.isNull(currentVal)){
+            tXinyiWarningRecord.setReason(category + EXCEPTION_WARNING);
+            tXinyiWarningRecord.setLevel(WARNING_LEVEL_NO_DATE);
+        }else if(currentVal.compareTo(multiply) > 0){//一级
+            tXinyiWarningRecord.setReason(category + CHAOBIAO_WARNING);
+            tXinyiWarningRecord.setLevel(WARNING_LEVEL_ONE);
+        }else if(currentVal.compareTo(csBzz) >= 0 && currentVal.compareTo(multiply) <= 0){//二级
+            tXinyiWarningRecord.setReason(category + CHAOBIAO_WARNING);
+            tXinyiWarningRecord.setLevel(WARNING_LEVEL_TWO);
+        }else if(!Objects.isNull(csGkz) && currentVal.compareTo(csGkz) > 0){
+            tXinyiWarningRecord.setReason(category + CHAOGUANKONG_WARNING);
+            tXinyiWarningRecord.setLevel(WARNING_LEVEL_THREE);
+        }else{
+            tXinyiWarningRecord = null;//这种的无需处理
+        }
+        //当前状态正常 需要查询历史有无正在报警的数据,如果有,将报警状态改完2(系统自动关闭)
+        List<TXinyiWarningRecord> tXinyiWarningRecords = this.xinyiWarningRecordMapper.selectTXinyiWarningRecordList(TXinyiWarningRecord.builder().delFlag(0).type(0).category(category).warningStatus(0).build());
+        if(Objects.isNull(tXinyiWarningRecord)){//数据正常,无告警信息
+            if(!CollectionUtils.isEmpty(tXinyiWarningRecords)){
+                log.info( "{}:现在恢复正常,历史报警数据为{}", category,JSON.toJSONString(tXinyiWarningRecords));
+                for (TXinyiWarningRecord xinyiWarningRecord : tXinyiWarningRecords) {
+                    xinyiWarningRecord.setStatus(2);
+                    Date nowDate = DateUtils.getNowDate();
+                    xinyiWarningRecord.setOffTime(nowDate);
+                    xinyiWarningRecord.setUpdateTime(nowDate);
+                    xinyiWarningRecord.setUpdateBy(WARNING_DEFAULT_CREATE);
+                    this.xinyiWarningRecordMapper.updateTXinyiWarningRecord(xinyiWarningRecord);
+                }
+            }
+        }else{//有告警信息
+            if(CollectionUtils.isEmpty(tXinyiWarningRecords)){//之前没有告警记录
+                //保存到数据库中
+                this.xinyiWarningRecordMapper.insertTXinyiWarningRecord(tXinyiWarningRecord);
+                if(WARNING_LEVEL_NO_DATE.equals(tXinyiWarningRecord.getLevel())){
+                    //只保存一个普通的问答记录 不需要调用决策信息,但是实时数据还是要记录的
+                    this.addChatRecordByWarning(tXinyiWarningRecord, tXinyiIndustry, normConfig);
+                }else {
+                    //继续调用决策
+                    this.handleDecision(tXinyiWarningRecord, tXinyiIndustry, normConfig);
+                }
+            }else{
+                log.info("{}:之前已经有过告警记录了,且还是继续报警,无需重复添加报警,但是决策仍然要调用", category);
+                for (TXinyiWarningRecord xinyiWarningRecord : tXinyiWarningRecords) {//理论上只有一个的
+                    if(WARNING_LEVEL_NO_DATE.equals(tXinyiWarningRecord.getLevel())){
+                        //只保存一个普通的问答记录 不需要调用决策信息,但是实时数据还是要记录的
+                        this.addChatRecordByWarning(tXinyiWarningRecord, tXinyiIndustry, normConfig);
+                    }else {
+                        //继续调用决策
+                        this.handleDecision(xinyiWarningRecord, tXinyiIndustry, normConfig);
+                    }
+                }
+            }
+        }
+
+    }
+
+
+    /**
+     * 通过输入的值 生成对应类型的报警对象(进水)
+     *
+     * @param jsBzz
+     * @param currentVal
+     * @param category
+     * @param tXinyiIndustry
+     * @param normConfig
+     * @return
+     */
+    private void handleXinYiWarningRecordJS(BigDecimal jsBzz, BigDecimal currentVal, String category, TXinyiIndustry tXinyiIndustry, TXinyiNormConfig normConfig) {
+        BigDecimal multiply = jsBzz.multiply(new BigDecimal(MyConstants.SCALE_VALUE));
+        TXinyiWarningRecord tXinyiWarningRecord = new TXinyiWarningRecord();
+        /*String category = BusinessEnum.WarningCategoryEnum.CS_AD.getCode();*/
+        tXinyiWarningRecord.setStatus(0);
+        tXinyiWarningRecord.setType(0);
+        tXinyiWarningRecord.setCategory(category);
+        tXinyiWarningRecord.setTime(DateUtils.getNowDate());
+        tXinyiWarningRecord.setWarningVal(currentVal);
+        tXinyiWarningRecord.setDesignVal(jsBzz);
+//        tXinyiWarningRecord.setControlVal(csGkz);
+        tXinyiWarningRecord.setCreateBy(WARNING_DEFAULT_CREATE);
+        tXinyiWarningRecord.setCreateTime(DateUtils.getNowDate());
+
+        //2024年5月25日17:52:33  如果工业库获取不到数据,也触发报警,但是不调用决策接口
+        if(Objects.isNull(currentVal)){
+            tXinyiWarningRecord.setReason(category + EXCEPTION_WARNING);
+            tXinyiWarningRecord.setLevel(WARNING_LEVEL_NO_DATE);
+        }else if(currentVal.compareTo(multiply) > 0){//一级
+            tXinyiWarningRecord.setReason(category + CHAOBIAO_WARNING);
+            tXinyiWarningRecord.setLevel(WARNING_LEVEL_ONE);
+        }else if(currentVal.compareTo(jsBzz) >= 0 && currentVal.compareTo(multiply) <= 0){//二级
+            tXinyiWarningRecord.setReason(category + CHAOBIAO_WARNING);
+            tXinyiWarningRecord.setLevel(WARNING_LEVEL_TWO);
+        }else{
+            tXinyiWarningRecord = null;//这种的无需处理
+        }
+        /*else if(!Objects.isNull(csGkz) && currentVal.compareTo(csGkz) > 0){
+            tXinyiWarningRecord.setReason(category + CHAOGUANKONG_WARNING);
+            tXinyiWarningRecord.setLevel(WARNING_LEVEL_THREE);
+        }*/
+        //当前状态正常 需要查询历史有无正在报警的数据,如果有,将报警状态改完2(系统自动关闭)
+        List<TXinyiWarningRecord> tXinyiWarningRecords = this.xinyiWarningRecordMapper.selectTXinyiWarningRecordList(TXinyiWarningRecord.builder().delFlag(0).type(0).category(category).status(0).build());
+        if(Objects.isNull(tXinyiWarningRecord)){//数据正常,无告警信息
+            if(!CollectionUtils.isEmpty(tXinyiWarningRecords)){
+                log.info( "{}:现在恢复正常,历史报警数据为{}", category,JSON.toJSONString(tXinyiWarningRecords));
+                for (TXinyiWarningRecord xinyiWarningRecord : tXinyiWarningRecords) {
+                    xinyiWarningRecord.setStatus(2);
+                    Date nowDate = DateUtils.getNowDate();
+                    xinyiWarningRecord.setOffTime(nowDate);
+                    xinyiWarningRecord.setUpdateTime(nowDate);
+                    xinyiWarningRecord.setUpdateBy(WARNING_DEFAULT_CREATE);
+                    this.xinyiWarningRecordMapper.updateTXinyiWarningRecord(xinyiWarningRecord);
+                }
+            }
+        }else{//有告警信息
+            if(CollectionUtils.isEmpty(tXinyiWarningRecords)){//之前没有告警记录
+                //保存到数据库中
+                this.xinyiWarningRecordMapper.insertTXinyiWarningRecord(tXinyiWarningRecord);
+                if(WARNING_LEVEL_NO_DATE.equals(tXinyiWarningRecord.getLevel())){
+                    //只保存一个普通的问答记录 不需要调用决策信息,但是实时数据还是要记录的
+                    this.addChatRecordByWarning(tXinyiWarningRecord, tXinyiIndustry, normConfig);
+                }else {
+                    //继续调用决策
+                    this.handleDecision(tXinyiWarningRecord, tXinyiIndustry, normConfig);
+                }
+            }else{
+                log.info("{}:之前已经有过告警记录了,且还是继续报警,无需重复添加报警,但是决策仍然要调用", category);
+                for (TXinyiWarningRecord xinyiWarningRecord : tXinyiWarningRecords) {//理论上只有一个的
+                    if(WARNING_LEVEL_NO_DATE.equals(tXinyiWarningRecord.getLevel())){
+                        //只保存一个普通的问答记录 不需要调用决策信息,但是实时数据还是要记录的
+                        this.addChatRecordByWarning(tXinyiWarningRecord, tXinyiIndustry, normConfig);
+                    }else {
+                        //继续调用决策
+                        this.handleDecision(xinyiWarningRecord, tXinyiIndustry, normConfig);
+                    }
+                }
+            }
+        }
+    }
+
+    private void addChatRecordByWarning(TXinyiWarningRecord tXinyiWarningRecord, TXinyiIndustry tXinyiIndustry, TXinyiNormConfig normConfig) {
+        ChatReq chatReq = new ChatReq();
+        //保存聊天记录
+        //将问答更新到数据库中
+        chatReq.setSessionId(IdUtils.simpleUUID());
+        chatReq.setType(1);//0问答 1决策 2本地 3仿真预测
+        chatReq.setModule(3);
+            /*String userId = SecurityUtils.getUserId().toString();
+            String username = SecurityUtils.getUsername();*/
+        chatReq.setUserId(WARNING_DEFAULT_CREATE);
+        String showVal = this.buildShowValue(tXinyiWarningRecord, tXinyiIndustry, normConfig);
+        chatReq.setShowVal(showVal);//前端展示的数据和提问的数据不一致
+        chatReq.setQuestion(WARNING_DEFAULT_QUESTION);//本地问题
+        chatReq.setAnswer(tXinyiWarningRecord.getReason() + ",请检查设备是否正常运行");
+        chatReq.setWarningId(String.valueOf(tXinyiWarningRecord.getId()));
+        chatReq.setCounts(1);//问答次数
+
+        chatReq.setCreateBy(WARNING_DEFAULT_CREATE);
+        chatReq.setCreateTime(DateUtils.getNowDate());
+        this.xinyiChatRecordMapper.insertTXinyiChatRecord(chatReq);
+    }
+}

+ 16 - 4
slibra-quartz/src/main/java/com/slibra/quartz/task/RyTask.java

@@ -35,6 +35,7 @@ import java.math.RoundingMode;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
+import java.util.concurrent.TimeUnit;
 
 import static com.slibra.common.constant.MyConstants.*;
 
@@ -82,6 +83,9 @@ public class RyTask
     @Autowired
     private TXinyiDailyMapper xinyiDailyMapper;
 
+    @Autowired
+    private AsyncTask asyncTask;
+
 
 //    public final static StopWatch watch = new StopWatch("task");
     public static final String[] queryTags = {"信义污水厂JS_COD_Value","信义污水厂JS_PH_Value","信义污水厂JS_SS_Value","信义污水厂JS_ZL_Value","信义污水厂JS_ZA_Value","信义污水厂JS_AD_Value","信义污水厂JS_T_Value","信义污水厂进水泵房液位","信义污水厂出水瞬时流量","信义污水厂升级出水COD","信义污水厂升级出水PH","信义污水厂升级出水SS","信义污水厂升级出水TN","信义污水厂升级出水TP","信义污水厂升级出水氨氮","信义污水厂AIT202_Value","信义污水厂AIT203_Value","信义污水厂AIT207_Value","信义污水厂AIT206_Value","信义污水厂AIT209_Value","信义污水厂AIT210_Value","信义污水厂进水TDS","信义污水厂FT101_Value","信义污水厂SWCHHYHLB1_R_Value","信义污水厂SWCHHYHLB2_R_Value","信义污水厂SWCHHYHLB3_R_Value","信义污水厂SWCHHYHLB4_R_Value","信义污水厂SWCHHYHLB5_R_Value","信义污水厂SWCHHYHLB6_R_Value","信义污水厂SWCWNHLB1_R_Value","信义污水厂SWCWNHLB2_R_Value","信义污水厂SWCWNHLB3_R_Value","信义污水厂SWCWNHLB4_R_Value","信义污水厂SWCWNHLB5_R_Value","信义污水厂GFJ1_R_Value","信义污水厂GFJ2_R_Value","信义污水厂GFJ3_R_Value","信义污水厂GFJ4_R_Value","信义污水厂GFJ5_R_Value","信义污水厂GFJ6_R_Value","信义污水厂GFJ1_KQLL_Value","信义污水厂GFJ2_KQLL_Value","信义污水厂GFJ3_KQLL_Value","信义污水厂GFJ4_KQLL_Value","信义污水厂GFJ5_KQLL_Value","信义污水厂GFJ6_KQLL_Value","信义污水厂实际碳源加药量","信义污水厂除磷加药瞬时流量", "信义污水厂_除磷P04预测值_"};
@@ -225,7 +229,8 @@ public class RyTask
                         industry.setCsSs(value);
                     } else if ("信义污水厂升级出水TN".equals(type)) {
                         log.info("************----------真实的出水总氮的值为{}\n时间为{}", value, k);
-                        industry.setCsTn(value);
+                        //todo 后面演示完要去掉
+                        industry.setCsTn(new BigDecimal(17));
                     } else if ("信义污水厂升级出水TP".equals(type)) {
                         industry.setCsTp(value);
                     } else if ("信义污水厂升级出水氨氮".equals(type)) {
@@ -324,7 +329,14 @@ public class RyTask
             //插入数据库
             xinyiIndustryMapper.insertTXinyiIndustry(industry);
             //判断是否触发告警、接触告警、保存决策等等
-            this.handleWarning(industry);
+//            this.handleWarning(industry);
+            //2024年5月30日18:29:20  改为异步处理
+            try {
+                TimeUnit.SECONDS.sleep(5);
+            } catch (InterruptedException e) {
+                throw new RuntimeException(e);
+            }
+            asyncTask.handleWarning(industry);
         });
 
         //执行完成 测试执行时间
@@ -335,8 +347,8 @@ public class RyTask
 
     private void handleWarning(TXinyiIndustry tXinyiIndustry) {
         log.info("进入了定时任务保存工业库数据并触发报警操作");
-        //todo 临时改一下出水总氮 模拟异常
-        tXinyiIndustry.setCsTn(new BigDecimal(17));
+        //todo 临时改一下出水总氮 模拟异常  2024年5月30日19:15:09 改在了插入数据库的时刻
+//        tXinyiIndustry.setCsTn(new BigDecimal(17));
         //获取配置表
         List<TXinyiNormConfig> tXinyiNormConfigs = this.xinyiNormConfigMapper.selectTXinyiNormConfigList(null);
         if(CollectionUtils.isEmpty(tXinyiNormConfigs))