Browse Source

修改控返不一致报警逻辑,支持设备类定义

zhangqiankun 3 years ago
parent
commit
edea66b3c8

+ 1 - 2
src/main/java/com/persagy/client/WebSocketClientFactory.java

@@ -16,7 +16,6 @@ import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
 
 import com.persagy.constant.CommonConst;
-import com.persagy.init.InitReturnAlarmConfig;
 import com.persagy.netty.collect.ReturnDifferentAlarm;
 import com.persagy.service.AlarmHandleService;
 import com.persagy.utils.GZIPCompressUtil;
@@ -116,7 +115,7 @@ public class WebSocketClientFactory {
                         }
                     });
                     // 控返不一致报警处理
-                    if (CommonConst.collectEnable && InitReturnAlarmConfig.alarmEnable) {
+                    if (CommonConst.collectEnable) {
                     	executor.execute(() -> returnDifferentAlarm.putMsg(finalMessage));
 					}
                 } catch (Exception e) {

+ 9 - 1
src/main/java/com/persagy/constant/CommonConst.java

@@ -13,7 +13,7 @@ import org.springframework.stereotype.Component;
  */
 @Component
 public class CommonConst {
-
+	
 	/** 系统标识,用于创建人 */
     public static final String IOT_PONINTSET_TYPE = "pointset";
     
@@ -23,6 +23,9 @@ public class CommonConst {
 	/** 项目根路径*/
 	public static final String SERVER_ROOT_PATH = System.getProperty("user.dir");
 
+    /** persagy-zkt-dmp 服务地址 */
+    public static String zktDMP;
+	
     /** 系统标识,用于创建人 */
     public static String systemId;
     
@@ -59,6 +62,11 @@ public class CommonConst {
     /** iot-project服务的webSocket地址 */
     public static String websocket;
 
+    @Value("${persagy.zkt.dmp}")
+    public void setZktDMP(String value) {
+        CommonConst.zktDMP = value;
+    }
+    
     @Value("${system.id}")
     public void setSystemId(String value) {
         CommonConst.systemId = value;

+ 176 - 0
src/main/java/com/persagy/constant/ExtraCommonConstant.java

@@ -0,0 +1,176 @@
+package com.persagy.constant;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.persagy.entity.PonitData;
+import com.persagy.entity.ReturnAlarmDefine;
+import com.persagy.init.InitReturnAlarmConfig;
+
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.HttpUtil;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 
+ * @version 1.0.0
+ * @company persagy 
+ * @author zhangqiankun
+ * @date 2021年12月14日 下午2:04:41
+ */
+@Slf4j
+public class ExtraCommonConstant {
+
+	public static final Object sync = new Object();
+	
+	public static final String SUCCESS = "success";
+	public static final String CRITERIA = "criteria";
+    public static final String IBMS_SCENE_CODE = "ibmsSceneCode";
+    public static final String IBMS_CLASS_CODE = "ibmsClassCode";
+	public static final String RWD_INSTANCE_OBJECT_QUERY = "/rwd/instance/object/query?projectId={}&groupCode={}";
+	
+	public static String getObjectQueryUrl() {
+		return CommonConst.zktDMP + StrUtil.format(RWD_INSTANCE_OBJECT_QUERY, CommonConst.projectId, CommonConst.groupCode);
+	}
+	
+	/**
+	 * 将对应的设备封装为报警定义
+	 * 
+	 * @param ibmsSceneCode
+	 * @param ibmsClassCode
+	 * @param alarmDefines 控返信息点定义
+	 * @param meter2DefineKey 
+	 * @param datas	设备对象数据
+	 * @date 2021年12月14日 下午2:20:15
+	 */
+	public static void getAlarmDefines(String ibmsSceneCode, String ibmsClassCode, JSONArray alarmDefines, JSONArray datas) {
+		try {
+			synchronized (ExtraCommonConstant.sync) {
+				for (int i = 0; i < datas.size(); i++) {
+					JSONObject dataObject = datas.getJSONObject(i);
+					String id = dataObject.getString("id");
+					// 根据控返信息点,形成对应的报警定义,并加入临时缓存map
+					for (int j = 0; j < alarmDefines.size(); j++) {
+						// 获取详细的报警定义信息
+						JSONObject alarmDefine = alarmDefines.getJSONObject(j);
+						String controlCode = alarmDefine.getString("controlCode");
+						String returnCode = alarmDefine.getString("returnCode");
+						String alarmCondition = alarmDefine.getString("alarmCondition");
+						JSONObject alarmCodes = alarmDefine.getJSONObject("alarmCode");
+						
+						String controlMeter = dataObject.getString(controlCode);
+						String returnMeter = dataObject.getString(returnCode);
+						if (StrUtil.isAllNotBlank(controlMeter, returnMeter)) {
+							ReturnAlarmDefine define = getReturnAlarmDefine(controlCode, controlMeter, returnCode, returnMeter, alarmCodes);
+							define.setAlarmCondition(alarmCondition);
+							define.setIbmsSceneCode(ibmsSceneCode);
+							define.setIbmsClassCode(ibmsClassCode);
+							define.setEquipId(id);
+							
+							InitReturnAlarmConfig.controlCode2AlarmDefine.put(controlMeter, define);
+							InitReturnAlarmConfig.returnCode2AlarmDefine.put(returnMeter, define);
+							
+							// 默认不做任何处理
+							String alarmKey = getKey(alarmCodes.getString("meter"), alarmCodes.getString("funcid"));
+							InitReturnAlarmConfig.ibmsCode2AlarmResult.put(alarmKey, -1);
+							InitReturnAlarmConfig.ibmsCode2AlarmData.put(alarmKey, alarmCodes);
+						}
+					}
+				}
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+			log.error("查询管理范围设备信息失败", e);
+		}
+	}
+	
+	/**
+	 * 获取此设备下对应信息点的对应报警定义
+	 * 
+	 * @param controlCode
+	 * @param controlMeter 表号-功能号
+	 * @param returnCode
+	 * @param returnMeter 表号-功能号
+	 * @return
+	 * @date 2021年12月14日 下午2:52:09
+	 */
+	private static ReturnAlarmDefine getReturnAlarmDefine(String controlCode, String controlMeter, String returnCode, String returnMeter, JSONObject alarmCodes) {
+		ReturnAlarmDefine define = new ReturnAlarmDefine();
+		define.setGroupCode(CommonConst.groupCode);
+		define.setProjectId(CommonConst.projectId);
+		define.setBuilding(CommonConst.building);
+		
+		// 控制信息点信息
+		PonitData controlData = new PonitData();
+		String[] control = controlMeter.split("-");
+		controlData.setInfoCode(controlCode);
+		controlData.setMeter(control[0]);
+		controlData.setFuncid(Integer.valueOf(control[1]));
+		define.setControlInfo(controlData);
+		
+		// 反馈信息点信息
+		PonitData returnData = new PonitData();
+		String[] returnM = returnMeter.split("-");
+		returnData.setInfoCode(returnCode);
+		returnData.setMeter(returnM[0]);
+		returnData.setFuncid(Integer.valueOf(returnM[1]));
+		define.setReturnInfo(returnData);
+		
+		// 报警信息点信息
+		PonitData alarmData = new PonitData();
+		alarmData.setInfoCode(alarmCodes.getString("code"));
+		alarmData.setMeter(alarmCodes.getString("meter"));
+		alarmData.setFuncid(alarmCodes.getInteger("funcid"));
+		define.setAlarmInfo(alarmData);
+		
+		return define;
+	}
+	
+	/**
+	 * 查询对应设备类下的所有设备数据
+	 * 
+	 * @param ibmsSceneCode
+	 * @param ibmsClassCode
+	 * @return 设备数据
+	 * @date 2021年12月14日 下午2:20:15
+	 */
+	public static JSONArray getObjectArray(String ibmsSceneCode, String ibmsClassCode) {
+		try {
+			JSONObject params = new JSONObject();
+			JSONObject criteria = new JSONObject();
+	        criteria.put(IBMS_SCENE_CODE, ibmsSceneCode);
+	        criteria.put(IBMS_CLASS_CODE, ibmsClassCode);
+	        params.put(CRITERIA, criteria);
+			String post = HttpUtil.post(getObjectQueryUrl(), params.toJSONString(), 10 * 1000);
+			if (StrUtil.isBlank(post)) {
+				return null;
+			}
+			JSONObject result = JSONObject.parseObject(post);
+			if (!SUCCESS.equals(result.getString("result"))) {
+				return null;
+			}
+			JSONArray datas = result.getJSONArray("data");
+			if (datas == null || datas.size() == 0) {
+				return null;
+			}
+			
+			return datas;
+		} catch (Exception e) {
+			e.printStackTrace();
+			log.error("查询管理范围设备信息失败", e);
+		}
+		return null;
+	}
+	
+	/**
+	 * key 拼接
+	 * 
+	 * @param value1
+	 * @param value2
+	 * @return value1-value2
+	 * @date 2021年12月14日 下午2:31:28
+	 */
+    public static String getKey(String value1, String value2) {
+        return value1 + "-" + value2;
+    }
+    
+}

+ 14 - 2
src/main/java/com/persagy/entity/ReturnAlarmDefine.java

@@ -26,8 +26,17 @@ public class ReturnAlarmDefine {
     /** 项目ID,不带Pj */
     private String building;
     
-	/** 需要判断的信息点 */
-	private PonitData setInfo;
+    /** 产品类编码 */
+    private String ibmsSceneCode;
+    
+    /** 设备类编码 */
+    private String ibmsClassCode;
+    
+    /** 设备ID */
+    private String equipId;
+    
+	/** 需要控制的信息点 */
+	private PonitData controlInfo;
 	
 	/** 实际iot数据点位*/
 	private PonitData returnInfo;
@@ -35,6 +44,9 @@ public class ReturnAlarmDefine {
 	/** 报警信息点 */
 	private PonitData alarmInfo;
 	
+	/** 报警状态 false-正常,true-报警 */
+	private volatile boolean alarmStatus = false;
+	
 	/** 报警条件 */
 	private String alarmCondition;
 

+ 25 - 54
src/main/java/com/persagy/init/InitReturnAlarmConfig.java

@@ -5,7 +5,6 @@ import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -17,9 +16,8 @@ import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.parser.Feature;
-import com.persagy.cache.CurrentDataCache;
 import com.persagy.constant.CommonConst;
-import com.persagy.entity.PonitData;
+import com.persagy.constant.ExtraCommonConstant;
 import com.persagy.entity.ReturnAlarmDefine;
 
 import cn.hutool.core.util.BooleanUtil;
@@ -37,20 +35,20 @@ import lombok.extern.slf4j.Slf4j;
 @Component
 public class InitReturnAlarmConfig implements CommandLineRunner {
 	
+	/** 是否开启控返不一致的报警 */
 	public static volatile boolean alarmEnable = false;
 	
-	/** 信息点到报警定义 */
-	public static Map<String, ReturnAlarmDefine> infoCode2Alarm = new HashMap<String, ReturnAlarmDefine>();
-	/** 信息点到报警定义 */
-	public static Map<String, ReturnAlarmDefine> returnCode2Alarm = new HashMap<String, ReturnAlarmDefine>();
-	/** 信息点到报警定义 */
-	public static Map<String, ReturnAlarmDefine> alarmCode2Alarm = new HashMap<String, ReturnAlarmDefine>();
+	/** key: meter-funcid(控制信息点), value: 报警定义  */
+	public static final Map<String, ReturnAlarmDefine> controlCode2AlarmDefine = new ConcurrentHashMap<String, ReturnAlarmDefine>();
+	/** key: meter-funcid(反馈信息点),value:报警定义 */
+	public static final Map<String, ReturnAlarmDefine> returnCode2AlarmDefine = new ConcurrentHashMap<String, ReturnAlarmDefine>();
 	
-	/** 表号-功能号, 信息点 */
-	public static Map<String, String> meterFunid2Code = new HashMap<String, String>();
-	
-	/** 报警信息点, 1-报警,0-正常,-1-不作任何处理 */
-	public static Map<String, Integer> alarmCode2IsAlarm = new ConcurrentHashMap<String, Integer>();
+	/** key:meter-funcid(报警信息点), value:1-报警,0-正常,-1-不作任何处理 */
+	public static final Map<String, Integer> ibmsCode2AlarmResult = new ConcurrentHashMap<String, Integer>();
+	/** key:meter-funcid(报警信息点), value:报警信息点数据 */
+	public static final Map<String, JSONObject> ibmsCode2AlarmData = new ConcurrentHashMap<String, JSONObject>();
+	/** key:meter-funcid(报警信息点), value: 报警个数 */
+	public static final Map<String, Integer> alarmCount = new ConcurrentHashMap<String, Integer>();
 	
 	@Override
 	public void run(String... args) throws Exception {
@@ -64,6 +62,7 @@ public class InitReturnAlarmConfig implements CommandLineRunner {
 		}
 		// 解析文件
 		this.parseAlarmConfig(file);
+		log.info("控返不一致报警配置文件加载完成");
 	}
 	
 	/**
@@ -80,47 +79,19 @@ public class InitReturnAlarmConfig implements CommandLineRunner {
 			return;
 		}
 		
-		JSONArray alarmDefines = fileJSON.getJSONArray("alarm-define");
-		for (int i = 0; i < alarmDefines.size(); i++) {
-			JSONObject alarmDefine = alarmDefines.getJSONObject(i);
-			
-			ReturnAlarmDefine define = new ReturnAlarmDefine();
-			define.setGroupCode(CommonConst.groupCode);
-			define.setProjectId(CommonConst.projectId);
-			define.setBuilding(CommonConst.building);
-			
-			// 需要判断的信息点
-			JSONObject setInfo = alarmDefine.getJSONObject("setInfo");
-			PonitData setPonitData = new PonitData();
-			setPonitData.setInfoCode(setInfo.getString("code"));
-			setPonitData.setMeter(setInfo.getString("meter"));
-			setPonitData.setFuncid(Integer.valueOf(setInfo.getString("funcid")));
-			define.setSetInfo(setPonitData);
-			infoCode2Alarm.put(setInfo.getString("code"), define);
-			meterFunid2Code.put(CurrentDataCache.getKey(setInfo.getString("meter"), setInfo.getString("funcid")), setInfo.getString("code"));
+		JSONArray alarmConfigs = fileJSON.getJSONArray("alarm-config");
+		for (int i = 0; i < alarmConfigs.size(); i++) {
+			JSONObject alarmConfig = alarmConfigs.getJSONObject(i);
+			// 获取报警的设备类配置
+			String ibmsSceneCode = alarmConfig.getString("ibmsSceneCode");
+			String ibmsClassCode = alarmConfig.getString("ibmsClassCode");
+			JSONArray alarmDefines = alarmConfig.getJSONArray("alarmDefine");
 			
-			// 需要验证的实际信息点
-			JSONObject returnInfo = alarmDefine.getJSONObject("returnInfo");
-			PonitData returnPonitData = new PonitData();
-			returnPonitData.setInfoCode(returnInfo.getString("code"));
-			returnPonitData.setMeter(returnInfo.getString("meter"));
-			returnPonitData.setFuncid(Integer.valueOf(returnInfo.getString("funcid")));
-			define.setReturnInfo(returnPonitData);
-			returnCode2Alarm.put(returnInfo.getString("code"), define);
-			meterFunid2Code.put(CurrentDataCache.getKey(returnInfo.getString("meter"), returnInfo.getString("funcid")), returnInfo.getString("code"));
-			
-			// 需要产生报警的信息点
-			JSONObject alarmInfo = alarmDefine.getJSONObject("alarmInfo");
-			PonitData alarmPonitData = new PonitData();
-			alarmPonitData.setInfoCode(alarmInfo.getString("code"));
-			alarmPonitData.setMeter(alarmInfo.getString("meter"));
-			alarmPonitData.setFuncid(Integer.valueOf(alarmInfo.getString("funcid")));
-			define.setAlarmInfo(alarmPonitData);
-			alarmCode2Alarm.put(alarmInfo.getString("code"), define);
-			alarmCode2IsAlarm.put(alarmInfo.getString("code"), -1);		// 默认不做任何处理
-			meterFunid2Code.put(CurrentDataCache.getKey(alarmInfo.getString("meter"), alarmInfo.getString("funcid")), alarmInfo.getString("code"));
-			
-			define.setAlarmCondition(alarmDefine.getString("alarmCondition"));
+			// 报警定义配置
+			JSONArray objects = ExtraCommonConstant.getObjectArray(ibmsSceneCode, ibmsClassCode);
+			if (objects != null) {
+				ExtraCommonConstant.getAlarmDefines(ibmsSceneCode, ibmsClassCode, alarmDefines, objects);
+			}
 		}
 	}
 	

+ 98 - 40
src/main/java/com/persagy/netty/collect/ReturnDifferentAlarm.java

@@ -1,7 +1,9 @@
 package com.persagy.netty.collect;
 
 import java.math.BigDecimal;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -12,8 +14,8 @@ import org.springframework.stereotype.Component;
 import com.alibaba.fastjson.JSONObject;
 import com.googlecode.aviator.AviatorEvaluator;
 import com.googlecode.aviator.Expression;
-import com.persagy.cache.CurrentDataCache;
 import com.persagy.constant.CommonConst;
+import com.persagy.constant.ExtraCommonConstant;
 import com.persagy.entity.ReturnAlarmDefine;
 import com.persagy.init.InitReturnAlarmConfig;
 
@@ -38,34 +40,38 @@ public class ReturnDifferentAlarm {
 	/** 从左到右:项目,时间,表号,功能号,值 */
 	public static final String COMMAND = "({};1;report;{};123;{};1;{};{})";
 	
+	public static final List<String> tempIot = new ArrayList<String>();
+	
+	public static volatile int COUNT = 0;
+	
 	@Autowired
 	private IotCollectNettyClient iotCollectNettyClient;
 	
 	/**
-	 * 启动后 延时 10s触发,以5s的间隔时间触发控返不一致的信息点实时数据写入
+	 * 启动后 延时 10s触发,以10s的间隔时间触发控返不一致的信息点实时数据写入
 	 * 
-	 * 每5s的间隔,代表着人为抑制了5s的持续性报警
+	 * 每10s的间隔,代表着人为抑制了5s的持续性报警
 	 * 
 	 * @throws Exception
 	 * @date 2021年12月9日 下午8:11:36
 	 */
-    @Scheduled(initialDelay = 10 * 1000, fixedRate = 5 * 1000)
+    @Scheduled(initialDelay = 10 * 1000, fixedRate = 10 * 1000)
     public void returnDifferentAlarm() throws Exception {
-    	if (InitReturnAlarmConfig.alarmCode2Alarm.size() == 0) {
+    	if (InitReturnAlarmConfig.ibmsCode2AlarmResult.size() == 0) {
 			return;
 		}
     	String now = DateUtil.date().toString("yyyyMMddHHmmss");
     	
     	// 根据数据,拼接出指令信息,发送入库
     	StringBuilder sb = new StringBuilder();
-    	Set<String> alarmCodes = InitReturnAlarmConfig.alarmCode2IsAlarm.keySet();
+    	Set<String> alarmCodes = InitReturnAlarmConfig.ibmsCode2AlarmResult.keySet();
     	for (String alarmCode : alarmCodes) {
-    		Integer isAlarm = InitReturnAlarmConfig.alarmCode2IsAlarm.get(alarmCode);
+    		Integer isAlarm = InitReturnAlarmConfig.ibmsCode2AlarmResult.get(alarmCode);
     		if (isAlarm != null && isAlarm != -1) {
-    			ReturnAlarmDefine alarmDefine = InitReturnAlarmConfig.alarmCode2Alarm.get(alarmCode);
+    			JSONObject alarmDefine = InitReturnAlarmConfig.ibmsCode2AlarmData.get(alarmCode);
     			// 0-正常,1-报警
     			BigDecimal dataValue = new BigDecimal(isAlarm);
-    			String command = StrUtil.format(COMMAND, alarmDefine.getBuilding(), now, alarmDefine.getAlarmInfo().getMeter(), alarmDefine.getAlarmInfo().getFuncid(), dataValue.toPlainString());
+    			String command = StrUtil.format(COMMAND, CommonConst.building, now, alarmDefine.getString("meter"), alarmDefine.getInteger("funcid"), dataValue.toPlainString());
     			sb.append(command).append("&");
 			}
 		}
@@ -85,16 +91,42 @@ public class ReturnDifferentAlarm {
      * {"data":"20211209150133;10346;903;1.0","type":"pointset"}
      * {"data":"20211209155421;CW20379;902;0.0","type":"iot"}
      * 
+     * 实际iot数据接的会很快,所以这里需要加一下锁,防止设备类加载过于缓慢的时候,丢失iot数据,只要这里能够抢到一次锁,后续就不需要了
+     * 
      * @param message
      * @date 2021年12月9日 下午3:54:35
      */
     public void putMsg(String message) {
-    	if (InitReturnAlarmConfig.infoCode2Alarm.size() == 0) {
+    	if (InitReturnAlarmConfig.alarmEnable && InitReturnAlarmConfig.controlCode2AlarmDefine.size() == 0) {
+			tempIot.add(message);
 			return;
 		}
     	
-    	Set<String> infoCodes = InitReturnAlarmConfig.infoCode2Alarm.keySet();
-    	Set<String> returnCodes = InitReturnAlarmConfig.returnCode2Alarm.keySet();
+    	// 当设备类数据加载完成的时候,这里补充加载一次iot数据
+    	if (tempIot.size() != 0) {
+			synchronized (ExtraCommonConstant.sync) {
+				if (tempIot.size() != 0) {
+					for (String iot : tempIot) {
+						if (StrUtil.isNotBlank(iot)) {
+							this.parseMessage(iot);
+						}
+					}
+					
+					tempIot.clear();
+				}
+			}
+		}
+    	
+		this.parseMessage(message);
+    }
+    
+    /**
+     * iot数据解析
+     * 
+     * @param message
+     * @date 2021年12月14日 下午10:44:46
+     */
+    private void parseMessage(String message) {
     	try {
     		// 解析此条iot数据详情
 			JSONObject messageObj = JSONObject.parseObject(message);
@@ -107,30 +139,30 @@ public class ReturnDifferentAlarm {
 			BigDecimal dataValue = new BigDecimal(split[3]);
 			
 			// 根据表号和功能号判断是否需要进行控返不一致的报警验证
-			ReturnAlarmDefine returnAlarmDefine = null;
-			String code = InitReturnAlarmConfig.meterFunid2Code.get(CurrentDataCache.getKey(meter, funcid));
-			if (infoCodes.contains(code) && CommonConst.IOT_PONINTSET_TYPE.equals(type)) {
-				returnAlarmDefine = InitReturnAlarmConfig.infoCode2Alarm.get(code);
+			ReturnAlarmDefine controlAlarmDefine = InitReturnAlarmConfig.controlCode2AlarmDefine.get(ExtraCommonConstant.getKey(meter, funcid));
+			ReturnAlarmDefine returnAlarmDefine = InitReturnAlarmConfig.returnCode2AlarmDefine.get(ExtraCommonConstant.getKey(meter, funcid));
+			if (controlAlarmDefine == null && returnAlarmDefine == null) {
+				return;		// 为空,说明不是要进行判断的iot数据
+			}
+			if (controlAlarmDefine != null && CommonConst.IOT_PONINTSET_TYPE.equals(type)) {
 				// 防止频繁的控制,导致无法进入2分钟后的逻辑判断,这里如果值相同的话,取上一次的上报时间使用
-				BigDecimal oldValue = returnAlarmDefine.getSetInfo().getDataValue();
+				BigDecimal oldValue = controlAlarmDefine.getControlInfo().getDataValue();
 				if (oldValue == null || dataValue.compareTo(oldValue) != 0) {
-					returnAlarmDefine.getSetInfo().setDataTime(dataTime);
-					returnAlarmDefine.getSetInfo().setDataValue(dataValue);
+					controlAlarmDefine.getControlInfo().setDataTime(dataTime);
+					controlAlarmDefine.getControlInfo().setDataValue(dataValue);
 				}
-			} else if (returnCodes.contains(code) && CommonConst.IOT_IOT_TYPE.equals(type)) {
-				returnAlarmDefine = InitReturnAlarmConfig.returnCode2Alarm.get(code);
+				// 正常数据下,判断此条数据,是否会影响控返不一致的报警信息点
+				log.info("需要进行控返不一致判断的iot数据:{}", message);
+				this.returnAlarmHandler(controlAlarmDefine);
+			} else if (returnAlarmDefine != null && CommonConst.IOT_IOT_TYPE.equals(type)) {
 				returnAlarmDefine.getReturnInfo().setDataTime(dataTime);
 				returnAlarmDefine.getReturnInfo().setDataValue(dataValue);
+				// 正常数据下,判断此条数据,是否会影响控返不一致的报警信息点
+				log.info("需要进行控返不一致判断的iot数据:{}", message);
+				this.returnAlarmHandler(returnAlarmDefine);
+			} else {
+				return;		// 未知的iot数据
 			}
-			
-			if (returnAlarmDefine == null) {
-				return;
-			}
-			
-			log.info("需要进行控返不一致判断的iot数据:{}", message);
-			
-			// 正常数据下,判断此条数据,是否会影响控返不一致的报警信息点
-			this.returnAlarmHandler(returnAlarmDefine);
 		} catch (Exception e) {
 			e.printStackTrace();
 			log.error("控返不一致的报警,逻辑处理异常", e);
@@ -153,17 +185,20 @@ public class ReturnDifferentAlarm {
      * @date 2021年12月9日 下午5:29:37
      */
 	private void returnAlarmHandler(ReturnAlarmDefine returnAlarmDefine) {
-		String setTimeStr = returnAlarmDefine.getSetInfo().getDataTime();
+		// 报警结果key
+		String alarmKey = ExtraCommonConstant.getKey(returnAlarmDefine.getAlarmInfo().getMeter(), returnAlarmDefine.getAlarmInfo().getFuncid()+"");
+		
+		String setTimeStr = returnAlarmDefine.getControlInfo().getDataTime();
 		String returnTimeStr = returnAlarmDefine.getReturnInfo().getDataTime();
 		if (!StrUtil.isAllNotBlank(setTimeStr, returnTimeStr)) {
-			InitReturnAlarmConfig.alarmCode2IsAlarm.put(returnAlarmDefine.getAlarmInfo().getInfoCode(), -1);
+			InitReturnAlarmConfig.ibmsCode2AlarmResult.put(alarmKey, -1);
 			return;
 		}
 		long setTime = Long.valueOf(setTimeStr);
 		long returnTime = Long.valueOf(returnTimeStr);
 		if (setTime > returnTime) {
         	// 新的指令和旧的iot数据,无论是否满足报警定义都不做任何处理,等待最新的iot数据上传后在做判断
-        	InitReturnAlarmConfig.alarmCode2IsAlarm.put(returnAlarmDefine.getAlarmInfo().getInfoCode(), -1);
+			InitReturnAlarmConfig.ibmsCode2AlarmResult.put(alarmKey, -1);
         	return;
         }
 		
@@ -176,8 +211,8 @@ public class ReturnDifferentAlarm {
 		Expression triggerExp = AviatorEvaluator.compile(alarmCondition, true);
 		
 		// 判断实际是否应该产生报警
-		String infoCode = returnAlarmDefine.getSetInfo().getInfoCode();
-		BigDecimal infoValue = returnAlarmDefine.getSetInfo().getDataValue() == null ? null : returnAlarmDefine.getSetInfo().getDataValue();
+		String infoCode = returnAlarmDefine.getControlInfo().getInfoCode();
+		BigDecimal infoValue = returnAlarmDefine.getControlInfo().getDataValue() == null ? null : returnAlarmDefine.getControlInfo().getDataValue();
 		String returnCode = returnAlarmDefine.getReturnInfo().getInfoCode();
 		BigDecimal returnValue = returnAlarmDefine.getReturnInfo().getDataValue() == null ? null : returnAlarmDefine.getReturnInfo().getDataValue();
 		
@@ -186,18 +221,41 @@ public class ReturnDifferentAlarm {
 		paramMap.put(returnCode, returnValue);
         Boolean triggerResult = (Boolean) triggerExp.execute(paramMap);
         
+        Integer count = InitReturnAlarmConfig.alarmCount.get(alarmKey);
     	// 旧的指令和新的iot数据
     	if (!newest) {
     		// 不是2分钟后上传上来的iot数据,这里不做任何处理
-			InitReturnAlarmConfig.alarmCode2IsAlarm.put(returnAlarmDefine.getAlarmInfo().getInfoCode(), -1);
+    		InitReturnAlarmConfig.ibmsCode2AlarmResult.put(alarmKey, -1);
 		} else if (BooleanUtil.isTrue(triggerResult)) {
 			// 满足报警条件,产生报警
-        	InitReturnAlarmConfig.alarmCode2IsAlarm.put(returnAlarmDefine.getAlarmInfo().getInfoCode(), 1);
+			if (!returnAlarmDefine.isAlarmStatus()) {
+				// 如果之前没有报警
+				if (count == null) {
+					InitReturnAlarmConfig.alarmCount.put(alarmKey, 1);
+				} else {
+					InitReturnAlarmConfig.alarmCount.put(alarmKey, ++count);
+				}
+			}
+			// 这里一定时报警状态
+			returnAlarmDefine.setAlarmStatus(true);
+			InitReturnAlarmConfig.ibmsCode2AlarmResult.put(alarmKey, 1);
 		} else if (BooleanUtil.isFalse(triggerResult)) {
-			// 不满足报警条件,如果已报警,则需恢复
-        	InitReturnAlarmConfig.alarmCode2IsAlarm.put(returnAlarmDefine.getAlarmInfo().getInfoCode(), 0);
+			// 不满足报警条件,判断是否报警数归零,不归零的话,不能设置为正常状态
+			if (returnAlarmDefine.isAlarmStatus()) {
+				// 之前报警了
+				count--;
+				if (count < 1) {
+					InitReturnAlarmConfig.ibmsCode2AlarmResult.put(alarmKey, 0);
+				}
+				InitReturnAlarmConfig.alarmCount.put(alarmKey, count < 1 ? 0 : count);
+			}
+			// 如果之前未报警,且当前也不存在报警,可以设置为 0
+			Integer isAlarm = InitReturnAlarmConfig.ibmsCode2AlarmResult.get(alarmKey);
+			if (isAlarm != 1) {
+				InitReturnAlarmConfig.ibmsCode2AlarmResult.put(alarmKey, 0);
+			}
 		} else {
-			InitReturnAlarmConfig.alarmCode2IsAlarm.put(returnAlarmDefine.getAlarmInfo().getInfoCode(), -1);
+			InitReturnAlarmConfig.ibmsCode2AlarmResult.put(alarmKey, -1);
 		}
 	}
 	

+ 4 - 0
src/main/resources/application-ZSPj4403050019.yml

@@ -30,6 +30,10 @@ iot:
     # 需要更改,修改其中的项目ID和ip、port,其中port为websocket的端口,切记不是服务端口
     websocket: ws://39.96.55.242:9980/websocket?projectId=4403050019&type=pointset,iot
 
+persagy:
+  zkt:
+    dmp: http://39.102.43.179:9976
+
 spring:
   datasource:
     # 需要更改

+ 15 - 18
src/main/resources/return-alarm.json

@@ -1,24 +1,21 @@
 {
 	"alarm-enable": true,
-    "alarm-define": [
+    "alarm-config": [
         {
-			"primaryKey": "Eq5465154164646",
-            "setInfo": {
-                "code": "equipSwitchSet",
-                "meter": "BA2501",
-                "funcid": 101
-            },
-            "returnInfo": {
-                "code": "runStatus",
-                "meter": "BA2482",
-                "funcid": 101
-            },
-            "alarmInfo": {
-                "code": "orderFailAlarm",
-                "meter": "KF1005",
-                "funcid": 101
-            },
-            "alarmCondition": "equipSwitchSet != runStatus"
+			"ibmsSceneCode": "lzqk",
+			"ibmsClassCode": "lixinji",
+			"alarmDefine": [
+				{
+					"controlCode": "equipSwitchSet",
+					"returnCode": "runStatus",
+		            "alarmCode": {
+		                "code": "orderFailAlarm",
+		                "meter": "KF1005",
+		                "funcid": 101
+		            },
+		            "alarmCondition": "equipSwitchSet != runStatus"
+				}
+			]
         }
     ]
 }