|
|
@ -6,6 +6,7 @@ import com.hnac.hzims.baseinfo.entity.ThreeDuty; |
|
|
|
import com.hnac.hzims.baseinfo.feign.IBaseInfoClient; |
|
|
|
import com.hnac.hzims.baseinfo.feign.IBaseInfoClient; |
|
|
|
import com.hnac.hzims.damsafety.entity.TBuilding; |
|
|
|
import com.hnac.hzims.damsafety.entity.TBuilding; |
|
|
|
import com.hnac.hzims.damsafety.feign.IWrpSectionBClient; |
|
|
|
import com.hnac.hzims.damsafety.feign.IWrpSectionBClient; |
|
|
|
|
|
|
|
import com.hnac.hzims.entity.ReportData; |
|
|
|
import com.hnac.hzims.message_alarm.dto.MessageDTO; |
|
|
|
import com.hnac.hzims.message_alarm.dto.MessageDTO; |
|
|
|
import com.hnac.hzims.message_alarm.entity.*; |
|
|
|
import com.hnac.hzims.message_alarm.entity.*; |
|
|
|
import com.hnac.hzims.message_alarm.enums.AlarmLevelEnum; |
|
|
|
import com.hnac.hzims.message_alarm.enums.AlarmLevelEnum; |
|
|
@ -19,8 +20,14 @@ import com.hnac.hzims.message_alarm.service.IMessageStrategyService; |
|
|
|
import com.hnac.hzims.message_alarm.strategy.FactoryRuleStrategy; |
|
|
|
import com.hnac.hzims.message_alarm.strategy.FactoryRuleStrategy; |
|
|
|
import com.hnac.hzims.message_alarm.util.DateUtil; |
|
|
|
import com.hnac.hzims.message_alarm.util.DateUtil; |
|
|
|
import com.hnac.hzims.message_alarm.vo.MessageObjAttrRuleVo; |
|
|
|
import com.hnac.hzims.message_alarm.vo.MessageObjAttrRuleVo; |
|
|
|
|
|
|
|
import com.hnac.hzims.operational.station.entity.StationEntity; |
|
|
|
|
|
|
|
import com.hnac.hzims.util.CommonUtil; |
|
|
|
import com.hnac.hzinfo.datasearch.analyse.domain.FieldsData; |
|
|
|
import com.hnac.hzinfo.datasearch.analyse.domain.FieldsData; |
|
|
|
|
|
|
|
import com.hnac.hzinfo.datasearch.analyse.po.AnalyseCodeByAnalyseDataPO; |
|
|
|
|
|
|
|
import com.hnac.hzinfo.datasearch.analyse.po.AnalyzeDataConditionPO; |
|
|
|
import com.hnac.hzinfo.datasearch.analyse.vo.AnalyseDataTaosVO; |
|
|
|
import com.hnac.hzinfo.datasearch.analyse.vo.AnalyseDataTaosVO; |
|
|
|
|
|
|
|
import com.hnac.hzinfo.datasearch.analyse.vo.AnalyzeDataConditionVO; |
|
|
|
|
|
|
|
import com.hnac.hzinfo.datasearch.analyse.vo.AnalyzeInstanceFieldVO; |
|
|
|
import com.hnac.hzinfo.datasearch.real.po.RealDataSearchPO; |
|
|
|
import com.hnac.hzinfo.datasearch.real.po.RealDataSearchPO; |
|
|
|
import com.hnac.hzinfo.sdk.analyse.AnalyseDataSearchClient; |
|
|
|
import com.hnac.hzinfo.sdk.analyse.AnalyseDataSearchClient; |
|
|
|
import com.hnac.hzinfo.sdk.analyse.po.ComputeBaseStrategyPO; |
|
|
|
import com.hnac.hzinfo.sdk.analyse.po.ComputeBaseStrategyPO; |
|
|
@ -43,11 +50,13 @@ import org.springframework.stereotype.Component; |
|
|
|
|
|
|
|
|
|
|
|
import javax.annotation.Resource; |
|
|
|
import javax.annotation.Resource; |
|
|
|
import java.math.BigDecimal; |
|
|
|
import java.math.BigDecimal; |
|
|
|
|
|
|
|
import java.math.RoundingMode; |
|
|
|
import java.text.ParseException; |
|
|
|
import java.text.ParseException; |
|
|
|
import java.text.SimpleDateFormat; |
|
|
|
import java.text.SimpleDateFormat; |
|
|
|
import java.time.LocalDateTime; |
|
|
|
import java.time.LocalDateTime; |
|
|
|
import java.time.ZoneId; |
|
|
|
import java.time.ZoneId; |
|
|
|
import java.time.format.DateTimeFormatter; |
|
|
|
import java.time.format.DateTimeFormatter; |
|
|
|
|
|
|
|
import java.time.temporal.ChronoUnit; |
|
|
|
import java.util.*; |
|
|
|
import java.util.*; |
|
|
|
import java.util.concurrent.TimeUnit; |
|
|
|
import java.util.concurrent.TimeUnit; |
|
|
|
import java.util.function.Function; |
|
|
|
import java.util.function.Function; |
|
|
@ -102,6 +111,7 @@ public class MessageMonitorObjJob { |
|
|
|
|
|
|
|
|
|
|
|
private final static String NOTIFY_TOPIC = "message_alarm_center/handleNotify"; //通知消息主题
|
|
|
|
private final static String NOTIFY_TOPIC = "message_alarm_center/handleNotify"; //通知消息主题
|
|
|
|
private final static String ALARM_TOPIC = "message_alarm_center/handleAlarm";//告警消息主题
|
|
|
|
private final static String ALARM_TOPIC = "message_alarm_center/handleAlarm";//告警消息主题
|
|
|
|
|
|
|
|
private final static String FLOW_ALARM_TOPIC = "message_alarm_center/handleFlowWarn";//流量告警消息主题
|
|
|
|
|
|
|
|
|
|
|
|
@Value("${hzims.alarm.rzalarm.level3}") |
|
|
|
@Value("${hzims.alarm.rzalarm.level3}") |
|
|
|
private String level3; |
|
|
|
private String level3; |
|
|
@ -442,6 +452,70 @@ public class MessageMonitorObjJob { |
|
|
|
return ReturnT.SUCCESS; |
|
|
|
return ReturnT.SUCCESS; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//流量告警消息
|
|
|
|
|
|
|
|
@XxlJob("flowWarnJob") |
|
|
|
|
|
|
|
public ReturnT<String> flowWarnJob(String param) { |
|
|
|
|
|
|
|
XxlJobParam xxlJobParam = JsonUtil.parse(param, XxlJobParam.class); |
|
|
|
|
|
|
|
if (null == xxlJobParam) { |
|
|
|
|
|
|
|
xxlJobParam = new XxlJobParam(); |
|
|
|
|
|
|
|
xxlJobParam.setCreateSdf("yyyy-MM-dd HH:mm:ss"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
logger.info("告警消息执行定时任务开始:" + new Date()); |
|
|
|
|
|
|
|
// 获取当前时间 8点 15点 根据现在的生态流量建议接下来的时间的流量
|
|
|
|
|
|
|
|
LocalDateTime now = LocalDateTime.now(); |
|
|
|
|
|
|
|
LocalDateTime startTime = now.withHour(0).withMinute(0).withSecond(0).withNano(0); |
|
|
|
|
|
|
|
// 判断是否是8点还是15点
|
|
|
|
|
|
|
|
int hours = (int) ChronoUnit.HOURS.between(startTime, now); |
|
|
|
|
|
|
|
if (hours != 8 && hours != 15) { |
|
|
|
|
|
|
|
return null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
//查询 已启动方案监控的对象 且关联了FLOWALARM模板
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<MessageSchemeObj> schemeObjList = getObjCodes(xxlJobParam.getSchemeId(), TemplateTypeEnum.FLOW_WARN.getCode()); |
|
|
|
|
|
|
|
logger.info("schemeObjList:" + schemeObjList); |
|
|
|
|
|
|
|
if (schemeObjList != null && !schemeObjList.isEmpty()) { |
|
|
|
|
|
|
|
//获取对象+属性+规则数据
|
|
|
|
|
|
|
|
LambdaQueryWrapper<MessageMonitorObjAttr> wrapper = new LambdaQueryWrapper<>(); |
|
|
|
|
|
|
|
List<String> codes = schemeObjList.stream().map(MessageSchemeObj::getObjectCode).distinct().collect(Collectors.toList()); |
|
|
|
|
|
|
|
wrapper.in(MessageMonitorObjAttr::getInstanceCode, codes); |
|
|
|
|
|
|
|
List<MessageObjAttrRuleVo> attrRuleVos = messageMonitorObjAttrService.queryMessageObjAttrRuleVo(wrapper); |
|
|
|
|
|
|
|
if (attrRuleVos == null || attrRuleVos.isEmpty()) { |
|
|
|
|
|
|
|
return ReturnT.FAIL; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//获取对象属性
|
|
|
|
|
|
|
|
List<MessageMonitorObjAttr> attrs = attrRuleVos.stream().map(MessageObjAttrRuleVo::getAttr).distinct().collect(Collectors.toList()); |
|
|
|
|
|
|
|
logger.info("attrs:" + attrs); |
|
|
|
|
|
|
|
for (MessageSchemeObj obj : schemeObjList) { |
|
|
|
|
|
|
|
//获取对象对应的属性的实时数据
|
|
|
|
|
|
|
|
List<Map<String, Object>> fieldsHistoryDate = getFieldsHistoryDate(attrs, obj, hours, startTime, now); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
logger.info("================平均数据res: ===========" + fieldsHistoryDate); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//获取对象属性对应的规则
|
|
|
|
|
|
|
|
List<MessageObjAttrRuleVo> rules = getMessageMonitorObjAttrRule(attrRuleVos, obj); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<Map<String, Object>> jsonList = getFlowAlarmList(obj.getObjectCode(), fieldsHistoryDate, rules, startTime, now); |
|
|
|
|
|
|
|
logger.info("================流量告警数据jsonList: ===========" + jsonList); |
|
|
|
|
|
|
|
//发送mqtt
|
|
|
|
|
|
|
|
if (jsonList != null && !jsonList.isEmpty()) {//如果属性中有告警 就发送
|
|
|
|
|
|
|
|
Map<String, String> dataMap = new HashMap<>(); |
|
|
|
|
|
|
|
dataMap.put("templateType", TemplateTypeEnum.FLOW_WARN.getCode()); |
|
|
|
|
|
|
|
dataMap.put("jsonData", JsonUtil.toJson(jsonList)); |
|
|
|
|
|
|
|
SimpleDateFormat createSdf = new SimpleDateFormat(xxlJobParam.getCreateSdf()); |
|
|
|
|
|
|
|
dataMap.put("createDate", createSdf.format(new Date()));//时间格式
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
logger.info("================dataMap: ===========" + dataMap); |
|
|
|
|
|
|
|
//发送mqtt
|
|
|
|
|
|
|
|
sendMqttMessage(FLOW_ALARM_TOPIC, dataMap, obj); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
logger.info("告警消息执行定时任务结束:" + new Date()); |
|
|
|
|
|
|
|
return ReturnT.SUCCESS; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* 查询出该流域下的所有水库,通知到所有水库的对应责任人号码 |
|
|
|
* 查询出该流域下的所有水库,通知到所有水库的对应责任人号码 |
|
|
|
* @param reservoirInfo |
|
|
|
* @param reservoirInfo |
|
|
@ -857,5 +931,158 @@ public class MessageMonitorObjJob { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private List<Map<String, Object>> getFieldsHistoryDate(List<MessageMonitorObjAttr> attrs, MessageSchemeObj obj, |
|
|
|
|
|
|
|
Integer timeInterval, LocalDateTime startTime, |
|
|
|
|
|
|
|
LocalDateTime endTime) { |
|
|
|
|
|
|
|
//查询对象已配置的属性值
|
|
|
|
|
|
|
|
List<String> signages = attrs.stream().filter(e->e.getInstanceCode().equals(obj.getObjectCode())) |
|
|
|
|
|
|
|
.map(MessageMonitorObjAttr::getAttrCode) |
|
|
|
|
|
|
|
.collect(Collectors.toList()); |
|
|
|
|
|
|
|
List<Map<String, Object>> resultList = new ArrayList<>(); |
|
|
|
|
|
|
|
for (String signage : signages) { |
|
|
|
|
|
|
|
// accessRules 取数规则:0=最早值、1=最大值、2=最小值、3=平均值、4=(累计值/和值)、5=(变化值/差值)6=最新值")
|
|
|
|
|
|
|
|
// SaveTimeType 周期类型: 0-> s(秒) 1->、m(分)、2->h(小时) 3->、d(天) 4->、w(周) 5->、n(自然月)、6->y(自然年)
|
|
|
|
|
|
|
|
String stcd = obj.getObjectCode(); |
|
|
|
|
|
|
|
List<Map<String, Object>> dataList = |
|
|
|
|
|
|
|
getData(stcd, 3, 2, timeInterval, startTime, endTime, signage); |
|
|
|
|
|
|
|
if (!CollectionUtils.isEmpty(dataList)) { |
|
|
|
|
|
|
|
// 为了处理特殊返回情况 多查出一条数据的问题
|
|
|
|
|
|
|
|
if (dataList.size() > 1) { |
|
|
|
|
|
|
|
dataList.remove(0); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
resultList.add(dataList.get(0)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return resultList; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public List<Map<String, Object>> getData(String stcd, Integer accessRules, Integer saveTimeType, Integer timeInterval, |
|
|
|
|
|
|
|
LocalDateTime startTime, LocalDateTime endTime, String signage) { |
|
|
|
|
|
|
|
List<Map<String, Object>> list = new ArrayList<>(); |
|
|
|
|
|
|
|
if (signage == null) { |
|
|
|
|
|
|
|
return null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
int count = 0; |
|
|
|
|
|
|
|
List<ReportData> reportDataList = |
|
|
|
|
|
|
|
getDataByDeviceCode(stcd, accessRules, saveTimeType, timeInterval, startTime, endTime, signage); |
|
|
|
|
|
|
|
count = reportDataList.size(); |
|
|
|
|
|
|
|
for (int i = 0; i < count; i++) { |
|
|
|
|
|
|
|
Map<String, Object> res = new HashMap<>(); |
|
|
|
|
|
|
|
ReportData reportData = reportDataList.get(i); |
|
|
|
|
|
|
|
res.put("tm", reportData.getKeyStr()); |
|
|
|
|
|
|
|
res.put(signage, reportData.getVal()); |
|
|
|
|
|
|
|
res.put("signage", signage); |
|
|
|
|
|
|
|
list.add(res); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return list; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<ReportData> getDataByDeviceCode(String deviceCode, Integer accessRules, Integer saveTimeType, Integer timeInterval, |
|
|
|
|
|
|
|
LocalDateTime start, LocalDateTime end, String col) { |
|
|
|
|
|
|
|
List<ReportData> reportData = new ArrayList<>(); |
|
|
|
|
|
|
|
AnalyseCodeByAnalyseDataPO po = new AnalyseCodeByAnalyseDataPO(); |
|
|
|
|
|
|
|
po.setDeviceCode(deviceCode); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<AnalyzeDataConditionPO> signboardConditions = new ArrayList<>(); |
|
|
|
|
|
|
|
AnalyzeDataConditionPO conditionPO = new AnalyzeDataConditionPO(); |
|
|
|
|
|
|
|
conditionPO.setBeginTime(start); |
|
|
|
|
|
|
|
conditionPO.setEndTime(end); |
|
|
|
|
|
|
|
conditionPO.setSignages(col); |
|
|
|
|
|
|
|
// conditionPO.setKeepFigures(3);
|
|
|
|
|
|
|
|
conditionPO.setAccessRules(accessRules); |
|
|
|
|
|
|
|
conditionPO.setSaveTimeType(saveTimeType); |
|
|
|
|
|
|
|
conditionPO.setTimeInterval(timeInterval); |
|
|
|
|
|
|
|
conditionPO.setFull(1); |
|
|
|
|
|
|
|
signboardConditions.add(conditionPO); |
|
|
|
|
|
|
|
po.setSignboardConditions(signboardConditions); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Result<List<AnalyzeDataConditionVO>> result = analyseDataSearchClient.getAnalyzeDataByAnalyzeCodeAndSignages(po); |
|
|
|
|
|
|
|
if (result == null || !result.isSuccess()) { |
|
|
|
|
|
|
|
return reportData; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
List<AnalyzeDataConditionVO> datas = result.getData(); |
|
|
|
|
|
|
|
if (datas == null || datas.isEmpty()) { |
|
|
|
|
|
|
|
return reportData; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
for (AnalyzeDataConditionVO vo : datas) { |
|
|
|
|
|
|
|
List<AnalyseDataTaosVO> dataTaosVOs = vo.getList(); |
|
|
|
|
|
|
|
for (AnalyseDataTaosVO vv : dataTaosVOs) { |
|
|
|
|
|
|
|
if (vo.getSignage().equals(col)) { |
|
|
|
|
|
|
|
ReportData data = new ReportData(); |
|
|
|
|
|
|
|
data.setKeyStr(CommonUtil.getKeyBySaveTimeType(vv.getTs(), saveTimeType)); |
|
|
|
|
|
|
|
String val = vv.getVal(); |
|
|
|
|
|
|
|
data.setStcd(deviceCode); |
|
|
|
|
|
|
|
data.setVal(val); |
|
|
|
|
|
|
|
if (val != null && !"".equals(val)) { |
|
|
|
|
|
|
|
data.setValue(Double.valueOf(vv.getVal())); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
data.setValue(0.0); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
data.setName(vo.getName()); |
|
|
|
|
|
|
|
reportData.add(data); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return reportData; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private List<Map<String,Object>> getFlowAlarmList(String objCode, |
|
|
|
|
|
|
|
List<Map<String, Object>> dataList, |
|
|
|
|
|
|
|
List<MessageObjAttrRuleVo> ruleVos, |
|
|
|
|
|
|
|
LocalDateTime startTime, |
|
|
|
|
|
|
|
LocalDateTime now){ |
|
|
|
|
|
|
|
List<Map<String,Object>> res=new ArrayList<>(); |
|
|
|
|
|
|
|
int level=0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(ruleVos == null || ruleVos.isEmpty()){ |
|
|
|
|
|
|
|
return null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(dataList == null || dataList.isEmpty()){ |
|
|
|
|
|
|
|
return null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
//判断整个对象中是否有属性告警
|
|
|
|
|
|
|
|
for (Map<String, Object> fieldsData : dataList) { |
|
|
|
|
|
|
|
String attr = fieldsData.get("signage").toString(); |
|
|
|
|
|
|
|
String val = fieldsData.get(attr).toString(); |
|
|
|
|
|
|
|
String ts = fieldsData.get("tm").toString(); |
|
|
|
|
|
|
|
List<MessageObjAttrRuleVo> filterList = ruleVos.stream().filter(e -> e.getAttr().getAttrCode().equals(attr)).collect(Collectors.toList()); |
|
|
|
|
|
|
|
if (filterList != null && !filterList.isEmpty()) { |
|
|
|
|
|
|
|
List<MessageMonitorObjAttrRule> rules = filterList.get(0).getAttrRuleList(); |
|
|
|
|
|
|
|
if (CollectionUtils.isEmpty(rules)) { |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Map<String, String> param = new HashMap<>(); |
|
|
|
|
|
|
|
param.put("objCode", objCode); |
|
|
|
|
|
|
|
param.put("attr", attr); |
|
|
|
|
|
|
|
param.put("val", val); |
|
|
|
|
|
|
|
param.put("ts", ts); |
|
|
|
|
|
|
|
Map<String, Object> messageMap = parseAlarmRule(param, rules); |
|
|
|
|
|
|
|
level = level + Integer.parseInt(messageMap.get("alarmLevel").toString()); |
|
|
|
|
|
|
|
// 查询电站核定流量 并计算剩下的时间需要达到多少平均流量
|
|
|
|
|
|
|
|
if (Integer.parseInt(messageMap.get("alarmLevel").toString()) > 0) { |
|
|
|
|
|
|
|
StationEntity station = dataDeviceMapper.getStationFlowValueByCode(objCode); |
|
|
|
|
|
|
|
messageMap.put("suggest", "0"); |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
// 高板岩一站 电站生态流量预警:核定流量0.02(m³/s),当前日均流量0.017(m³/s),建议生态流量后续9小时的实时流量值不低于0.054(m³/s)
|
|
|
|
|
|
|
|
long seconds = ChronoUnit.SECONDS.between(startTime, now); |
|
|
|
|
|
|
|
long hours = 24 - ChronoUnit.HOURS.between(startTime, now); |
|
|
|
|
|
|
|
BigDecimal sumFlow = station.getDischarge().multiply(new BigDecimal(24 * 60 * 60)); |
|
|
|
|
|
|
|
BigDecimal nowFlow = new BigDecimal(val).multiply(new BigDecimal(seconds)); |
|
|
|
|
|
|
|
BigDecimal divide = sumFlow.subtract(nowFlow).divide(new BigDecimal(24 * 60 * 60 - seconds), 2, RoundingMode.HALF_UP); |
|
|
|
|
|
|
|
messageMap.put("suggest", station.getName() + "电站生态流量预警:核定流量" + station.getDischarge() + |
|
|
|
|
|
|
|
"(m³/s),当前日均流量" + val + "(m³/s),建议生态流量后续" + hours + "小时的实时流量值不低于" + divide + "(m³/s)"); |
|
|
|
|
|
|
|
} catch (Exception e) { |
|
|
|
|
|
|
|
messageMap.put("suggest", "0"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
res.add(messageMap); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if(level == 0){//告警等级相加大于0就是有告警
|
|
|
|
|
|
|
|
return null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return res; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|