|
@@ -2272,14 +2272,520 @@ public class HandleDataController extends BaseController
|
|
BigDecimal jsslSjz = normConfig.getJsslSjz();
|
|
BigDecimal jsslSjz = normConfig.getJsslSjz();
|
|
BigDecimal jszdSjz = normConfig.getJszdSjz();
|
|
BigDecimal jszdSjz = normConfig.getJszdSjz();
|
|
BigDecimal jsadSjz = normConfig.getJsadSjz();
|
|
BigDecimal jsadSjz = normConfig.getJsadSjz();
|
|
|
|
+ BigDecimal cscodBzz = normConfig.getCscodBzz();
|
|
|
|
+ BigDecimal cscodGkz = normConfig.getCscodGkz();
|
|
|
|
+ BigDecimal jscodSjz = normConfig.getJscodSjz();
|
|
//进水总氮超标报警
|
|
//进水总氮超标报警
|
|
BigDecimal jsTn = tXinyiIndustry.getJsTn();
|
|
BigDecimal jsTn = tXinyiIndustry.getJsTn();
|
|
//进水氨氮超标报警
|
|
//进水氨氮超标报警
|
|
BigDecimal jsNh3 = tXinyiIndustry.getJsNh3();
|
|
BigDecimal jsNh3 = tXinyiIndustry.getJsNh3();
|
|
|
|
+ //进水Cod报警
|
|
|
|
+ BigDecimal jsCod = tXinyiIndustry.getJsCod();
|
|
|
|
+ //出水Cod报警
|
|
|
|
+ BigDecimal csCod = tXinyiIndustry.getCsCod();
|
|
|
|
+
|
|
if(!Objects.isNull(jszdSjz) && jszdSjz.compareTo(BigDecimal.ZERO) > 0)
|
|
if(!Objects.isNull(jszdSjz) && jszdSjz.compareTo(BigDecimal.ZERO) > 0)
|
|
handleXinYiWarningRecordJSOriginZD(jszdSjz, jsTn, BusinessEnum.WarningCategoryEnum.JS_ZD.getCode(), tXinyiIndustry, normConfig, getCwrwfhzByDetail(jsSlq, tXinyiIndustry.getJsTn(), jsslSjz, normConfig.getJszdSjz()));
|
|
handleXinYiWarningRecordJSOriginZD(jszdSjz, jsTn, BusinessEnum.WarningCategoryEnum.JS_ZD.getCode(), tXinyiIndustry, normConfig, getCwrwfhzByDetail(jsSlq, tXinyiIndustry.getJsTn(), jsslSjz, normConfig.getJszdSjz()));
|
|
if(!Objects.isNull(jsadSjz) && jsadSjz.compareTo(BigDecimal.ZERO) > 0)
|
|
if(!Objects.isNull(jsadSjz) && jsadSjz.compareTo(BigDecimal.ZERO) > 0)
|
|
handleXinYiWarningRecordJSOriginNh3(jsadSjz, jsNh3, BusinessEnum.WarningCategoryEnum.JS_AD.getCode(), tXinyiIndustry, normConfig, getCwrwfhzByDetail(jsSlq, tXinyiIndustry.getJsNh3(), jsslSjz, normConfig.getJsadSjz()));
|
|
handleXinYiWarningRecordJSOriginNh3(jsadSjz, jsNh3, BusinessEnum.WarningCategoryEnum.JS_AD.getCode(), tXinyiIndustry, normConfig, getCwrwfhzByDetail(jsSlq, tXinyiIndustry.getJsNh3(), jsslSjz, normConfig.getJsadSjz()));
|
|
|
|
+ if(!Objects.isNull(cscodBzz) && cscodBzz.compareTo(BigDecimal.ZERO) > 0 && !Objects.isNull(cscodGkz) && cscodGkz.compareTo(BigDecimal.ZERO) > 0)
|
|
|
|
+ handleXinYiWarningsCsOriginCod(cscodBzz, csCod, cscodGkz, CS_COD.getCode(), tXinyiIndustry, normConfig, getCwrwfhzByDetail(jsSlq, tXinyiIndustry.getJsCod(), jsslSjz, normConfig.getJscodSjz()));
|
|
|
|
+ if(!Objects.isNull(jscodSjz) && jscodSjz.compareTo(BigDecimal.ZERO) > 0)
|
|
|
|
+ handleXinYiWarningRecordJSOriginCod(jscodSjz, jsCod, JS_COD.getCode(), tXinyiIndustry, normConfig, getCwrwfhzByDetail(jsSlq, tXinyiIndustry.getJsCod(), jsslSjz, normConfig.getJscodSjz()));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 不同指标报警规则不一样,全部区分开来处理,此方法为:进水cod
|
|
|
|
+ * 通过输入的值 生成对应类型的报警对象(进水)- cod
|
|
|
|
+ *
|
|
|
|
+ * @param jsBzz
|
|
|
|
+ * @param currentVal
|
|
|
|
+ * @param category
|
|
|
|
+ * @param tXinyiIndustry
|
|
|
|
+ * @param normConfig
|
|
|
|
+ * @param cwrwfhz
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ private void handleXinYiWarningRecordJSOriginCod(BigDecimal jsBzz, BigDecimal currentVal, String category, TXinyiIndustry tXinyiIndustry, TXinyiNormConfig normConfig, BigDecimal cwrwfhz) {
|
|
|
|
+
|
|
|
|
+ Date nowDate = DateUtils.getNowDate();
|
|
|
|
+
|
|
|
|
+ List<TXinyiIndustry> tXinyiIndustries = this.xinyiIndustryMapper.selectNIndustry(INT_8);
|
|
|
|
+ if(CollectionUtils.isEmpty(tXinyiIndustries) || tXinyiIndustries.size() < INT_8){
|
|
|
|
+ log.error("处理生化报警时,获取最近的8条工业库数据失败~~~~~~~");
|
|
|
|
+ return ;
|
|
|
|
+ }
|
|
|
|
+ //拼接决策的最近8小时的值
|
|
|
|
+ String last8Str = this.getJsCodStrByList(tXinyiIndustries);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ //最开始的工艺报警 (超标准工艺报警) 2025年04月16日15:40:23 改成只有超标准才会报警,并且具体逻辑做拆分
|
|
|
|
+ normalIndustryWarningJsCod(jsBzz, currentVal, category, tXinyiIndustry, normConfig, cwrwfhz, nowDate, tXinyiIndustries);
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 最开始的工艺报警 (超标准工艺报警) -- 进水cod
|
|
|
|
+ * @param jsBzz
|
|
|
|
+ * @param currentVal
|
|
|
|
+ * @param category
|
|
|
|
+ * @param tXinyiIndustry
|
|
|
|
+ * @param normConfig
|
|
|
|
+ * @param cwrwfhz
|
|
|
|
+ * @param nowDate
|
|
|
|
+ * @param tXinyiIndustries
|
|
|
|
+ */
|
|
|
|
+ private void normalIndustryWarningJsCod(BigDecimal jsBzz, BigDecimal currentVal, String category, TXinyiIndustry tXinyiIndustry, TXinyiNormConfig normConfig, BigDecimal cwrwfhz, Date nowDate, List<TXinyiIndustry> tXinyiIndustries) {
|
|
|
|
+ //新的判断进水氨氮是否超标
|
|
|
|
+ TXinyiWarningRecord tXinyiWarningRecord = existsNormalJsCod(jsBzz, currentVal, category, cwrwfhz, tXinyiIndustries, normConfig);
|
|
|
|
+
|
|
|
|
+ //最近3条输出 连续升高趋势 和 新增的报警都需要
|
|
|
|
+ //当前状态正常 需要查询历史有无正在报警的数据,如果有,将报警状态改完2(系统自动关闭)
|
|
|
|
+ List<TXinyiWarningRecord> tXinyiWarningRecords = this.xinyiWarningRecordMapper.selectTXinyiWarningRecordList(TXinyiWarningRecord.builder().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) {
|
|
|
|
+ closeWarning(xinyiWarningRecord);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }else{//有告警信息
|
|
|
|
+ if(CollectionUtils.isEmpty(tXinyiWarningRecords)){//之前没有告警记录
|
|
|
|
+ //保存到数据库中
|
|
|
|
+ //2024年7月15日11:06:16 因为只有一个告警记录,但是如果一直报警,现在报警时间取的是更新时间,兼容第一次报警处理
|
|
|
|
+ tXinyiWarningRecord.setUpdateTime(nowDate);
|
|
|
|
+ this.xinyiWarningRecordMapper.insertTXinyiWarningRecord(tXinyiWarningRecord);
|
|
|
|
+ //继续调用决策
|
|
|
|
+ this.handleDecision(tXinyiWarningRecord, tXinyiIndustry, normConfig, false, nowDate);
|
|
|
|
+ }else{
|
|
|
|
+ log.info("{}:之前已经有过告警记录了,且还是继续报警,无需重复添加报警,但是决策仍然要调用", category);
|
|
|
|
+ for (TXinyiWarningRecord xinyiWarningRecord : tXinyiWarningRecords) {//理论上只有一个的
|
|
|
|
+ //2024年7月5日10:45:24 逻辑调整:更新一直报警的那条记录的显示值
|
|
|
|
+ xinyiWarningRecord.setWarningVal(tXinyiWarningRecord.getWarningVal());
|
|
|
|
+// xinyiWarningRecord.setDesignVal(tXinyiWarningRecord.getDesignVal());
|
|
|
|
+// tXinyiWarningRecord.setControlVal(tXinyiWarningRecord.getControlVal());
|
|
|
|
+ xinyiWarningRecord.setTime(tXinyiWarningRecord.getTime());
|
|
|
|
+ xinyiWarningRecord.setUpdateTime(nowDate);
|
|
|
|
+ xinyiWarningRecord.setUpdateBy(WARNING_DEFAULT_CREATE);
|
|
|
|
+ //2024年7月15日11:07:33 报警的级别也要重新计算并更新
|
|
|
|
+ xinyiWarningRecord.setLevel(tXinyiWarningRecord.getLevel());
|
|
|
|
+ //2024年7月31日09:20:47 报警的原因(超标还是超管控也需要更新)
|
|
|
|
+ xinyiWarningRecord.setReason(tXinyiWarningRecord.getReason());
|
|
|
|
+ //更新数据库
|
|
|
|
+ this.xinyiWarningRecordMapper.updateTXinyiWarningRecord(xinyiWarningRecord);
|
|
|
|
+ //继续调用决策
|
|
|
|
+ this.handleDecision(xinyiWarningRecord, tXinyiIndustry, normConfig, false, nowDate);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 根据新的规则,判断进水氨氮是否超标,超标了则返回报警对象;没有超标,返回空对象 -- 进水cod
|
|
|
|
+ *
|
|
|
|
+ * @param jsBzz
|
|
|
|
+ * @param currentVal
|
|
|
|
+ * @param category
|
|
|
|
+ * @param cwrwfhz
|
|
|
|
+ * @param tXinyiIndustries
|
|
|
|
+ * @param normConfig
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ private TXinyiWarningRecord existsNormalJsCod(BigDecimal jsBzz, BigDecimal currentVal, String category, BigDecimal cwrwfhz, List<TXinyiIndustry> tXinyiIndustries, TXinyiNormConfig normConfig) {
|
|
|
|
+ boolean flag = false;
|
|
|
|
+ TXinyiIndustry tXinyiIndustry = tXinyiIndustries.get(INDEX_0);
|
|
|
|
+ BigDecimal jsCod0 = tXinyiIndustry.getJsCod();
|
|
|
|
+ BigDecimal jsCod1 = tXinyiIndustries.get(INDEX_1).getJsCod();
|
|
|
|
+ /*BigDecimal jsCod2 = tXinyiIndustries.get(INDEX_2).getJsCod();
|
|
|
|
+ BigDecimal jsCod3 = tXinyiIndustries.get(INDEX_3).getJsCod();*/
|
|
|
|
+ if(!Objects.isNull(jsCod0) && jsCod0.compareTo(jsBzz) > 0 && !Objects.isNull(jsCod1) && jsCod1.compareTo(jsBzz) > 0)
|
|
|
|
+ flag = true;//在线仪表,连续两个不同的进水COD数据 > 630
|
|
|
|
+ if(!Objects.isNull(jsCod0) && jsCod0.compareTo(jsBzz) > 0 && !Objects.isNull(jsCod1) && jsCod0.compareTo(jsCod1) > 0)
|
|
|
|
+ flag = true;//在线仪表,一个进水COD数据 > 630,与前一个数据呈上升趋势
|
|
|
|
+ BigDecimal jsTn = tXinyiIndustry.getJsTn();
|
|
|
|
+ BigDecimal jsNh3 = tXinyiIndustry.getJsNh3();
|
|
|
|
+ BigDecimal jsTp = tXinyiIndustry.getJsTp();
|
|
|
|
+ if(!Objects.isNull(jsCod0) && jsCod0.compareTo(jsBzz) > 0 && (!Objects.isNull(jsTn) && jsTn.compareTo(BigDecimal.valueOf(65)) > 0
|
|
|
|
+ || !Objects.isNull(jsNh3) && jsNh3.compareTo(BigDecimal.valueOf(58)) > 0 || !Objects.isNull(jsTp) && jsTp.compareTo(BigDecimal.valueOf(7.1)) > 0))
|
|
|
|
+ flag = true;
|
|
|
|
+ if(!flag)
|
|
|
|
+ return null;
|
|
|
|
+ //存在符合的报警情况,生成报警对象
|
|
|
|
+ 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());
|
|
|
|
+ tXinyiWarningRecord.setRemark(ZERO_SZ_WARNING.getCode());
|
|
|
|
+ //2025年02月10日14:45:08 下面是新增加的字段
|
|
|
|
+ tXinyiWarningRecord.setWaterType(BusinessEnum.WaterTypeEnum.JS.getCode());
|
|
|
|
+ //超污染物限制:计算公式为:当前氨氮/氨氮设计值 或者 当前氨氮/氨氮管控值(智能工单使用) 这里是出水的 【需要根据超标还是超管控,具体计算】
|
|
|
|
+ //超污染物负荷值:计算公式为:当前水量与氨氮乘积 / 设计水量与设计进水氨氮的乘积(智能工单使用)
|
|
|
|
+ tXinyiWarningRecord.setCwrwfhz(cwrwfhz);//2025年02月14日10:48:32 具体的值由上游传过来
|
|
|
|
+ tXinyiWarningRecord.setReason(category + CHAOBIAO_WARNING);
|
|
|
|
+ tXinyiWarningRecord.setLevel(WARNING_LEVEL_ONE);
|
|
|
|
+ tXinyiWarningRecord.setSymbol(BusinessEnum.WarningSymbolEnum.CBZZ.getCode());
|
|
|
|
+ tXinyiWarningRecord.setCwrwxz(getCwrwxzByDetail(currentVal, normConfig, category, true));//根据当前值和类型以及是否超标处理
|
|
|
|
+
|
|
|
|
+ return tXinyiWarningRecord;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ private String getJsCodStrByList(List<TXinyiIndustry> tXinyiIndustries) {
|
|
|
|
+ int size = tXinyiIndustries.size();
|
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
|
+ for (int i = 0; i < size; i++) {
|
|
|
|
+ TXinyiIndustry tXinyiIndustry = tXinyiIndustries.get(i);
|
|
|
|
+ //2025年05月08日14:07:50 bug修复:传过来几条数据,都需要拼接
|
|
|
|
+ if(i < size - 1)
|
|
|
|
+ sb.append(DecimalUtils.getAbsAndScale(tXinyiIndustry.getJsCod(), INT_2)).append("mg/L、");
|
|
|
|
+ else
|
|
|
|
+ sb.append(DecimalUtils.getAbsAndScale(tXinyiIndustry.getJsCod(), INT_2)).append("mg/L。");
|
|
|
|
+ }
|
|
|
|
+ return sb.toString();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 通过输入的值 生成对应类型的报警对象(出水)- 新的 按照不同的类型区分了,因为每个报警都不一样了
|
|
|
|
+ *
|
|
|
|
+ * @param csBzz
|
|
|
|
+ * @param currentVal
|
|
|
|
+ * @param csGkz
|
|
|
|
+ * @param category
|
|
|
|
+ * @param tXinyiIndustry
|
|
|
|
+ * @param normConfig
|
|
|
|
+ * @param cwrwfhz
|
|
|
|
+ * 2025年05月14日15:15:48 cod报警比较特殊:没有异常升高、异常偏低、高低值报警;并且把断点和连续不变合成了一个叫 【设备故障的报警】
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ private void handleXinYiWarningsCsOriginCod(BigDecimal csBzz, BigDecimal currentVal, BigDecimal csGkz, String category, TXinyiIndustry tXinyiIndustry, TXinyiNormConfig normConfig, BigDecimal cwrwfhz) {
|
|
|
|
+
|
|
|
|
+ Date nowDate = DateUtils.getNowDate();
|
|
|
|
+ List<TXinyiIndustry> tXinyiIndustries = this.xinyiIndustryMapper.selectNIndustry(INT_4);
|
|
|
|
+ if(CollectionUtils.isEmpty(tXinyiIndustries) || tXinyiIndustries.size() < INT_4){
|
|
|
|
+ log.error("处理生化报警时,获取最近的4条工业库数据失败~~~~~~~");
|
|
|
|
+ return ;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+// //拼接决策的最近4小时的值
|
|
|
|
+// String last4Str = this.getJsNh3StrByList(tXinyiIndustries);
|
|
|
|
+//
|
|
|
|
+// //报警设备故障
|
|
|
|
+// if (existsCsCodDeviceErr(csBzz, currentVal, category, tXinyiIndustry, normConfig, cwrwfhz, tXinyiIndustries, nowDate, last4Str, csGkz))
|
|
|
|
+// return;
|
|
|
|
+
|
|
|
|
+ //工艺报警
|
|
|
|
+ //最开始的工艺报警 (超标准工艺报警)
|
|
|
|
+ normalIndustryWarningCsCod(csBzz, currentVal, category, tXinyiIndustry, normConfig, cwrwfhz, nowDate, tXinyiIndustries, csGkz);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 最开始的工艺报警 (超标准工艺报警) -- 出水cod
|
|
|
|
+ * @param csBzz
|
|
|
|
+ * @param currentVal
|
|
|
|
+ * @param category
|
|
|
|
+ * @param tXinyiIndustry
|
|
|
|
+ * @param normConfig
|
|
|
|
+ * @param cwrwfhz
|
|
|
|
+ * @param nowDate
|
|
|
|
+ * @param tXinyiIndustries
|
|
|
|
+ */
|
|
|
|
+ private void normalIndustryWarningCsCod(BigDecimal csBzz, BigDecimal currentVal, String category, TXinyiIndustry tXinyiIndustry, TXinyiNormConfig normConfig, BigDecimal cwrwfhz, Date nowDate, List<TXinyiIndustry> tXinyiIndustries, BigDecimal csGkz) {
|
|
|
|
+ //新的判断进水氨氮是否超标
|
|
|
|
+ TXinyiWarningRecord tXinyiWarningRecord = existsNormalCsCod(csBzz, currentVal, category, cwrwfhz, tXinyiIndustries, normConfig, csGkz);
|
|
|
|
+
|
|
|
|
+ //最近3条输出 连续升高趋势 和 新增的报警都需要
|
|
|
|
+ //当前状态正常 需要查询历史有无正在报警的数据,如果有,将报警状态改完2(系统自动关闭)
|
|
|
|
+ List<TXinyiWarningRecord> tXinyiWarningRecords = this.xinyiWarningRecordMapper.selectTXinyiWarningRecordList(TXinyiWarningRecord.builder().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) {
|
|
|
|
+ closeWarning(xinyiWarningRecord);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }else{//有告警信息
|
|
|
|
+ if(CollectionUtils.isEmpty(tXinyiWarningRecords)){//之前没有告警记录
|
|
|
|
+ //保存到数据库中
|
|
|
|
+ //2024年7月15日11:06:16 因为只有一个告警记录,但是如果一直报警,现在报警时间取的是更新时间,兼容第一次报警处理
|
|
|
|
+ tXinyiWarningRecord.setUpdateTime(nowDate);
|
|
|
|
+ this.xinyiWarningRecordMapper.insertTXinyiWarningRecord(tXinyiWarningRecord);
|
|
|
|
+ //继续调用决策
|
|
|
|
+ this.handleDecision(tXinyiWarningRecord, tXinyiIndustry, normConfig, false, nowDate);
|
|
|
|
+ }else{
|
|
|
|
+ log.info("{}:之前已经有过告警记录了,且还是继续报警,无需重复添加报警,但是决策仍然要调用", category);
|
|
|
|
+ for (TXinyiWarningRecord xinyiWarningRecord : tXinyiWarningRecords) {//理论上只有一个的
|
|
|
|
+ //2024年7月5日10:45:24 逻辑调整:更新一直报警的那条记录的显示值
|
|
|
|
+ xinyiWarningRecord.setWarningVal(tXinyiWarningRecord.getWarningVal());
|
|
|
|
+// xinyiWarningRecord.setDesignVal(tXinyiWarningRecord.getDesignVal());
|
|
|
|
+// tXinyiWarningRecord.setControlVal(tXinyiWarningRecord.getControlVal());
|
|
|
|
+ xinyiWarningRecord.setTime(tXinyiWarningRecord.getTime());
|
|
|
|
+ xinyiWarningRecord.setUpdateTime(nowDate);
|
|
|
|
+ xinyiWarningRecord.setUpdateBy(WARNING_DEFAULT_CREATE);
|
|
|
|
+ //2024年7月15日11:07:33 报警的级别也要重新计算并更新
|
|
|
|
+ xinyiWarningRecord.setLevel(tXinyiWarningRecord.getLevel());
|
|
|
|
+ //2024年7月31日09:20:47 报警的原因(超标还是超管控也需要更新)
|
|
|
|
+ xinyiWarningRecord.setReason(tXinyiWarningRecord.getReason());
|
|
|
|
+ //更新数据库
|
|
|
|
+ this.xinyiWarningRecordMapper.updateTXinyiWarningRecord(xinyiWarningRecord);
|
|
|
|
+ //继续调用决策
|
|
|
|
+ this.handleDecision(xinyiWarningRecord, tXinyiIndustry, normConfig, false, nowDate);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 根据新的规则,判断出水cod是否超标,超标了则返回报警对象;没有超标,返回空对象 -- 出水cod
|
|
|
|
+ *
|
|
|
|
+ * @param csBzz
|
|
|
|
+ * @param currentVal
|
|
|
|
+ * @param category
|
|
|
|
+ * @param cwrwfhz
|
|
|
|
+ * @param tXinyiIndustries
|
|
|
|
+ * @param normConfig
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ private TXinyiWarningRecord existsNormalCsCod(BigDecimal csBzz, BigDecimal currentVal, String category, BigDecimal cwrwfhz, List<TXinyiIndustry> tXinyiIndustries, TXinyiNormConfig normConfig, BigDecimal csGkz) {
|
|
|
|
+ boolean flag = false;
|
|
|
|
+ TXinyiIndustry tXinyiIndustry = tXinyiIndustries.get(INDEX_0);
|
|
|
|
+ BigDecimal csCod0 = tXinyiIndustry.getCsCod();
|
|
|
|
+ BigDecimal csCod1 = tXinyiIndustries.get(INDEX_1).getCsCod();
|
|
|
|
+ BigDecimal csCod2 = tXinyiIndustries.get(INDEX_2).getCsCod();
|
|
|
|
+ BigDecimal csCod3 = tXinyiIndustries.get(INDEX_3).getCsCod();
|
|
|
|
+ if(!Objects.isNull(csCod0) && !Objects.isNull(csCod1) && !Objects.isNull(csCod2) && !Objects.isNull(csCod3)){
|
|
|
|
+ //出水COD在线仪表 > 40 and 连续4小时
|
|
|
|
+ if(csCod0.compareTo(csBzz) > 0 && csCod1.compareTo(csBzz) > 0 && csCod2.compareTo(csBzz) > 0 && csCod3.compareTo(csBzz) > 0)
|
|
|
|
+ flag = true;
|
|
|
|
+ //出水COD在线仪表 > 40 and 连续三小时数据呈现大于等于上一小时的情况
|
|
|
|
+ if(csCod0.compareTo(csBzz) > 0 && csCod0.compareTo(csCod1) >= 0 && csCod1.compareTo(csCod2) >= 0 && csCod2.compareTo(csCod3) >= 0)
|
|
|
|
+ flag = true;
|
|
|
|
+ }
|
|
|
|
+ //出水COD在线仪表 > 40 and 出水氨氮连续检测数据 > 4
|
|
|
|
+ //查询同时刻的化验数据,计算出水氨氮
|
|
|
|
+ List<TXinyiRobot> tXinyiRobots = this.xinyiRobotMapper.selectTXinyiRobotList(TXinyiRobot.builder().testHour(tXinyiIndustry.getTestHour()).build());
|
|
|
|
+ if(!CollectionUtils.isEmpty(tXinyiRobots)){
|
|
|
|
+ TXinyiRobot xinyiRobot = tXinyiRobots.get(0);
|
|
|
|
+ BigDecimal no3Hlj1JqrTemp = xinyiRobot.getNo3Hlj1Jqr();
|
|
|
|
+ //#2好氧硝酸盐
|
|
|
|
+ BigDecimal no3Hlj2JqrTemp = xinyiRobot.getNo3Hlj2Jqr();
|
|
|
|
+ //1#缺氧出-硝酸盐
|
|
|
|
+ BigDecimal no3Qyc1JqrTemp = xinyiRobot.getNo3Qyc1Jqr();
|
|
|
|
+ BigDecimal nh31JqrTemp = xinyiRobot.getNh31Jqr();
|
|
|
|
+ //2#缺氧出-硝酸盐
|
|
|
|
+ BigDecimal no3Qyc2JqrTemp = xinyiRobot.getNo3Qyc2Jqr();
|
|
|
|
+ BigDecimal nh32JqrTemp = xinyiRobot.getNh32Jqr();
|
|
|
|
+ if (Objects.isNull(no3Qyc1JqrTemp))
|
|
|
|
+ no3Qyc1JqrTemp = BigDecimal.ZERO;
|
|
|
|
+ if (Objects.isNull(nh31JqrTemp))
|
|
|
|
+ nh31JqrTemp = BigDecimal.ZERO;
|
|
|
|
+ if (Objects.isNull(no3Hlj1JqrTemp))
|
|
|
|
+ no3Hlj1JqrTemp = BigDecimal.ZERO;
|
|
|
|
+ BigDecimal anDan1 = no3Qyc1JqrTemp.add(nh31JqrTemp).subtract(no3Hlj1JqrTemp);
|
|
|
|
+
|
|
|
|
+ //判断 增加容错
|
|
|
|
+ if (Objects.isNull(no3Qyc2JqrTemp))
|
|
|
|
+ no3Qyc2JqrTemp = BigDecimal.ZERO;
|
|
|
|
+ if (Objects.isNull(nh32JqrTemp))
|
|
|
|
+ nh32JqrTemp = BigDecimal.ZERO;
|
|
|
|
+ if (Objects.isNull(no3Hlj2JqrTemp))
|
|
|
|
+ no3Hlj2JqrTemp = BigDecimal.ZERO;
|
|
|
|
+ BigDecimal anDan2 = no3Qyc2JqrTemp.add(nh32JqrTemp).subtract(no3Hlj2JqrTemp);
|
|
|
|
+ BigDecimal divide = anDan1.add(anDan2).divide(DECIMAL_2, INT_2, RoundingMode.HALF_UP);
|
|
|
|
+ //出水COD在线仪表 > 40 and 出水氨氮连续检测数据 > 4
|
|
|
|
+ if(!Objects.isNull(csCod0) && csCod0.compareTo(csBzz) > 0 && divide.compareTo(BigDecimal.valueOf(4)) > 0)
|
|
|
|
+ flag = true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ if(!flag)
|
|
|
|
+ return null;
|
|
|
|
+ //存在符合的报警情况,生成报警对象
|
|
|
|
+ TXinyiWarningRecord tXinyiWarningRecord = new TXinyiWarningRecord();
|
|
|
|
+ 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());
|
|
|
|
+ tXinyiWarningRecord.setRemark(ZERO_SZ_WARNING.getCode());
|
|
|
|
+ //2025年02月10日14:45:08 下面是新增加的字段
|
|
|
|
+ tXinyiWarningRecord.setWaterType(BusinessEnum.WaterTypeEnum.CS.getCode());
|
|
|
|
+ //超污染物限制:计算公式为:当前氨氮/氨氮设计值 或者 当前氨氮/氨氮管控值(智能工单使用) 这里是出水的 【需要根据超标还是超管控,具体计算】
|
|
|
|
+ //超污染物负荷值:计算公式为:当前水量与氨氮乘积 / 设计水量与设计进水氨氮的乘积(智能工单使用)
|
|
|
|
+ tXinyiWarningRecord.setCwrwfhz(cwrwfhz);//2025年02月14日10:48:32 具体的值由上游传过来
|
|
|
|
+ tXinyiWarningRecord.setReason(category + CHAOBIAO_WARNING);
|
|
|
|
+ tXinyiWarningRecord.setLevel(WARNING_LEVEL_ONE);
|
|
|
|
+ tXinyiWarningRecord.setSymbol(BusinessEnum.WarningSymbolEnum.CBZZ.getCode());
|
|
|
|
+ tXinyiWarningRecord.setCwrwxz(getCwrwxzByDetail(currentVal, normConfig, category, true));//根据当前值和类型以及是否超标处理
|
|
|
|
+
|
|
|
|
+ return tXinyiWarningRecord;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 查看出水cod是否存在 设备故障 的报警判断,如果存在处理数据,并报警。
|
|
|
|
+ *
|
|
|
|
+ * @param csBzz
|
|
|
|
+ * @param currentVal
|
|
|
|
+ * @param category
|
|
|
|
+ * @param tXinyiIndustry
|
|
|
|
+ * @param normConfig
|
|
|
|
+ * @param cwrwfhz
|
|
|
|
+ * @param tXinyiIndustries
|
|
|
|
+ * @param nowDate
|
|
|
|
+ * @param last4Str
|
|
|
|
+ * @param csGkz
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ private boolean existsCsCodDeviceErr(BigDecimal csBzz, BigDecimal currentVal, String category, TXinyiIndustry tXinyiIndustry, TXinyiNormConfig normConfig, BigDecimal cwrwfhz, List<TXinyiIndustry> tXinyiIndustries, Date nowDate, String last4Str, BigDecimal csGkz) {
|
|
|
|
+ if(!CollectionUtils.isEmpty(tXinyiIndustries) && tXinyiIndustries.size() == INT_4){
|
|
|
|
+ //查询同类型的历史报警
|
|
|
|
+ TXinyiWarningRecord csCodDeviceErrWarning = TXinyiWarningRecord.builder().type(0).category(category).symbol(BusinessEnum.WarningSymbolEnum.DEVICE_ERR_CS_COD.getCode()).status(0).build();
|
|
|
|
+ List<TXinyiWarningRecord> csCodDeviceErrList = this.xinyiWarningRecordMapper.selectTXinyiWarningRecordList(csCodDeviceErrWarning);
|
|
|
|
+ //2025年02月21日14:33:37 这里要改成当前值和上个小时比较 上个小时和上上个小时比较
|
|
|
|
+ if(existsCsCodDeviceErr(tXinyiIndustries)){//这里不能只返回一个布尔类型的结果,因为还要获取百分比的值
|
|
|
|
+ //关闭同类型的其他报警
|
|
|
|
+ closeOtherWarningsByCategory(category, BusinessEnum.WarningSymbolEnum.DEVICE_ERR_CS_COD.getCode());
|
|
|
|
+ //触发报警 并且模拟大模型返回决策问答数据
|
|
|
|
+ if(CollectionUtils.isEmpty(csCodDeviceErrList)){
|
|
|
|
+ //插入该类型报警
|
|
|
|
+ csCodDeviceErrWarning.setTime(nowDate);
|
|
|
|
+ csCodDeviceErrWarning.setReason(category + BusinessEnum.WarningSymbolEnum.DEVICE_ERR_CS_COD.getMsg());
|
|
|
|
+ csCodDeviceErrWarning.setWaterType(BusinessEnum.WaterTypeEnum.CS.getCode());
|
|
|
|
+ csCodDeviceErrWarning.setSymbol(BusinessEnum.WarningSymbolEnum.DEVICE_ERR_CS_COD.getCode());
|
|
|
|
+ csCodDeviceErrWarning.setCreateBy(WARNING_DEFAULT_CREATE);
|
|
|
|
+ csCodDeviceErrWarning.setCreateTime(nowDate);
|
|
|
|
+ csCodDeviceErrWarning.setWarningVal(currentVal);
|
|
|
|
+ csCodDeviceErrWarning.setDesignVal(csBzz);
|
|
|
|
+ csCodDeviceErrWarning.setControlVal(csGkz);
|
|
|
|
+ csCodDeviceErrWarning.setRemark(ZERO_SZ_WARNING.getCode());
|
|
|
|
+ csCodDeviceErrWarning.setCwrwfhz(cwrwfhz);
|
|
|
|
+ csCodDeviceErrWarning.setCwrwxz(getCwrwxzByDetail(currentVal, normConfig, category, true));//根据当前值和类型以及是否超标处理
|
|
|
|
+ this.xinyiWarningRecordMapper.insertTXinyiWarningRecord(csCodDeviceErrWarning);
|
|
|
|
+ //同时处理决策 不用调用大模型,本地处理问答
|
|
|
|
+ addChatRecordByCsCodDeviceErr(csCodDeviceErrWarning, tXinyiIndustry, normConfig, category, last4Str);
|
|
|
|
+ }else{
|
|
|
|
+ //2025年04月16日15:56:47 这种的继续报警,所以决策还需要再次调用一次
|
|
|
|
+ //2025年05月08日13:34:23bug修改 这里不能用new的对象 要获取历史报警的值
|
|
|
|
+// addChatRecordByGDZ(warningRecordGDZ, tXinyiIndustry, normConfig, category, exceedVal, resultMap.get(LASTVAL), last8Str);
|
|
|
|
+ addChatRecordByCsCodDeviceErr(csCodDeviceErrList.get(0), tXinyiIndustry, normConfig, category, last4Str);
|
|
|
|
+ }
|
|
|
|
+ //后续的报警不再进行
|
|
|
|
+ return true;
|
|
|
|
+ }else{//不存在 查看历史是否有报警,有的话关闭
|
|
|
|
+ if(!CollectionUtils.isEmpty(csCodDeviceErrList)){
|
|
|
|
+ closeWarning(csCodDeviceErrList.get(0));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ *
|
|
|
|
+ * 出水cod - 设备故障 本地决策处理
|
|
|
|
+ * @param warningRecord
|
|
|
|
+ * @param tXinyiIndustry
|
|
|
|
+ * @param normConfig
|
|
|
|
+ * @param category
|
|
|
|
+ * @param last4Str
|
|
|
|
+ */
|
|
|
|
+ private void addChatRecordByCsCodDeviceErr(TXinyiWarningRecord warningRecord, TXinyiIndustry tXinyiIndustry, TXinyiNormConfig normConfig, String category,String last4Str) {
|
|
|
|
+ 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(warningRecord, tXinyiIndustry, normConfig, DateUtils.getNowDate());
|
|
|
|
+ chatReq.setShowVal(showVal);//前端展示的数据和提问的数据不一致
|
|
|
|
+ chatReq.setQuestion(BusinessEnum.WarningSymbolEnum.DEVICE_ERR_CS_COD.getMsg());//本地问题
|
|
|
|
+// chatReq.setAnswer(category + YCSG_ANSWER_ONE + exceedVal.multiply(BigDecimal_100) + "%" + YCSG_ANSWER_TWO + warningRecord.getWarningVal() + YCSG_ANSWER_THREE);
|
|
|
|
+ chatReq.setAnswer(CS_COD_DEVICE_ERR_ANSWER_REPLACE.replaceAll("@@@0", category).replaceAll("@@@1", last4Str));//只替换最近8小时的值 和 类型
|
|
|
|
+ chatReq.setWarningId(String.valueOf(warningRecord.getId()));
|
|
|
|
+ chatReq.setCounts(1);//问答次数
|
|
|
|
+
|
|
|
|
+ chatReq.setCreateBy(WARNING_DEFAULT_CREATE);
|
|
|
|
+ chatReq.setCreateTime(DateUtils.getNowDate());
|
|
|
|
+ this.xinyiChatRecordMapper.insertTXinyiChatRecord(chatReq);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 将此化验类型的其他的报警全部关闭
|
|
|
|
+ * @param category
|
|
|
|
+ */
|
|
|
|
+ private void closeOtherWarningsByCategory(String category, Integer symbol) {
|
|
|
|
+ List<TXinyiWarningRecord> tXinyiWarningRecords = this.xinyiWarningRecordMapper.getOtherWarningsByCategory(category, symbol);
|
|
|
|
+ if(!CollectionUtils.isEmpty(tXinyiWarningRecords)){
|
|
|
|
+ for (TXinyiWarningRecord tXinyiWarningRecord : tXinyiWarningRecords) {
|
|
|
|
+ this.closeWarning(tXinyiWarningRecord);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ private String getJsNh3StrByList(List<TXinyiIndustry> tXinyiIndustries) {
|
|
|
|
+// return StringUtil.join(tXinyiIndustries.stream().map(TXinyiIndustry::getJsNh3).collect(Collectors.toList()) , "mg/L、");
|
|
|
|
+ int size = tXinyiIndustries.size();
|
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
|
+ for (int i = 0; i < size; i++) {
|
|
|
|
+ TXinyiIndustry tXinyiIndustry = tXinyiIndustries.get(i);
|
|
|
|
+ if(i < size - 1)
|
|
|
|
+ sb.append(DecimalUtils.getAbsAndScale(tXinyiIndustry.getJsNh3(), INT_2)).append("mg/L、");
|
|
|
|
+ else
|
|
|
|
+ sb.append(DecimalUtils.getAbsAndScale(tXinyiIndustry.getJsNh3(), INT_2)).append("mg/L。");
|
|
|
|
+ }
|
|
|
|
+ return sb.toString();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 出水cod是否存在设备故障报警
|
|
|
|
+ * @param industryList
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ private boolean existsCsCodDeviceErr(List<TXinyiIndustry> industryList) {
|
|
|
|
+ boolean result = false;
|
|
|
|
+ BigDecimal csCod0 = industryList.get(0).getCsCod();
|
|
|
|
+ BigDecimal csCod1 = industryList.get(1).getCsCod();
|
|
|
|
+ BigDecimal csCod2 = industryList.get(2).getCsCod();
|
|
|
|
+ BigDecimal csCod3 = industryList.get(3).getCsCod();
|
|
|
|
+ //全部为空
|
|
|
|
+ if(Objects.isNull(csCod0) && Objects.isNull(csCod1) && Objects.isNull(csCod2) && Objects.isNull(csCod3))
|
|
|
|
+ return true;
|
|
|
|
+ //数据为0、 数据相同 and 出水COD>40
|
|
|
|
+ if(!Objects.isNull(csCod0) && !Objects.isNull(csCod1) && !Objects.isNull(csCod2) && !Objects.isNull(csCod3)){
|
|
|
|
+ if(BigDecimal.ZERO.compareTo(csCod0) == 0 && BigDecimal.ZERO.compareTo(csCod1) == 0 && BigDecimal.ZERO.compareTo(csCod2) == 0 && BigDecimal.ZERO.compareTo(csCod3) == 0)
|
|
|
|
+ return true;
|
|
|
|
+ if(csCod0.compareTo(BigDecimal.valueOf(40)) > 0 && csCod0.compareTo(csCod1) == 0 && csCod0.compareTo(csCod2) == 0 && csCod0.compareTo(csCod3) == 0)
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return result;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|