|
@@ -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);
|
|
|
+ }
|
|
|
+}
|