Browse Source

修改为接受报警条件和报警条件与设备的关联关系

lixing 3 years ago
parent
commit
73cc401810
25 changed files with 727 additions and 772 deletions
  1. 9 0
      src/main/java/com/persagy/ZktProjectAlarmApplication.java
  2. 94 212
      src/main/java/com/persagy/cache/AlarmInfoCache.java
  3. 0 68
      src/main/java/com/persagy/cache/CurrentDataCache.java
  4. 3 3
      src/main/java/com/persagy/client/GroupNettyClient.java
  5. 69 38
      src/main/java/com/persagy/client/GroupNettyClientHandler.java
  6. 58 150
      src/main/java/com/persagy/controller/HelloWorld.java
  7. 3 7
      src/main/java/com/persagy/entity/AlarmDefineState.java
  8. 39 4
      src/main/java/com/persagy/entity/AlarmDefine.java
  9. 0 1
      src/main/java/com/persagy/entity/Condition.java
  10. 3 2
      src/main/java/com/persagy/entity/NettyMessage.java
  11. 78 0
      src/main/java/com/persagy/entity/v2/AlarmCondition.java
  12. 40 0
      src/main/java/com/persagy/entity/v2/CalculateMethodDTO.java
  13. 21 0
      src/main/java/com/persagy/entity/v2/Formula.java
  14. 25 0
      src/main/java/com/persagy/entity/v2/ItemCodeCondition.java
  15. 56 0
      src/main/java/com/persagy/entity/v2/ObjConditionInfo.java
  16. 25 0
      src/main/java/com/persagy/entity/v2/ObjConditionRel.java
  17. 0 1
      src/main/java/com/persagy/job/AlarmContinueJob.java
  18. 4 4
      src/main/java/com/persagy/job/AlarmExpireJob.java
  19. 0 20
      src/main/java/com/persagy/service/AlarmDefineService.java
  20. 84 0
      src/main/java/com/persagy/service/impl/AlarmConditionServiceImpl.java
  21. 0 119
      src/main/java/com/persagy/service/impl/AlarmDefineServiceImpl.java
  22. 104 124
      src/main/java/com/persagy/service/impl/AlarmHandleServiceImpl.java
  23. 0 1
      src/main/java/com/persagy/utils/LockUtil.java
  24. 2 2
      src/main/resources/application.yml
  25. 10 16
      src/test/java/com/persagy/zktprojectalarm/Mytest.java

+ 9 - 0
src/main/java/com/persagy/ZktProjectAlarmApplication.java

@@ -3,8 +3,11 @@ package com.persagy;
 import com.github.dadiyang.autologging.aop.annotation.AutoLogAll;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
 import org.springframework.scheduling.annotation.EnableScheduling;
 
+import java.util.Scanner;
+
 @SpringBootApplication
 @EnableScheduling
 @AutoLogAll
@@ -14,4 +17,10 @@ public class ZktProjectAlarmApplication {
         SpringApplication.run(ZktProjectAlarmApplication.class, args);
     }
 
+//    public static void main(String[] args) {
+//        Scanner scanner = new Scanner(System.in);
+//        String port = scanner.nextLine();
+//        new SpringApplicationBuilder(ZktProjectAlarmApplication.class)
+//                .properties("server.port=" + port).run(args);
+//    }
 }

+ 94 - 212
src/main/java/com/persagy/cache/AlarmInfoCache.java

@@ -1,22 +1,20 @@
 package com.persagy.cache;
 
 
-import cn.hutool.core.collection.CollectionUtil;
-import com.alibaba.fastjson.JSONObject;
 import com.googlecode.aviator.AviatorEvaluator;
-import com.googlecode.aviator.Expression;
+import com.persagy.entity.AlarmConditionState;
 import com.persagy.entity.AlarmDefine;
-import com.persagy.entity.AlarmDefineState;
-import com.persagy.entity.Condition;
+import com.persagy.entity.v2.AlarmCondition;
+import com.persagy.entity.v2.ItemCodeCondition;
+import com.persagy.entity.v2.ObjConditionInfo;
+import com.persagy.entity.v2.ObjConditionRel;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;
 import org.springframework.util.CollectionUtils;
 
-import java.util.ArrayList;
+import java.util.LinkedList;
 import java.util.List;
-import java.util.Objects;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.stream.Collectors;
 
 /**
  * @description: 报警存放报警定义缓存的的数据
@@ -30,21 +28,22 @@ import java.util.stream.Collectors;
 public class AlarmInfoCache {
 
     /**
-     * 报警定义  <报警定义标识,报警定义详情>
-     * 报警定义标识默认为:报警编码-报警对象id
+     * 报警对象id -> (条件Id,报警类型编码)列表,项目id
+     * objId -> {[{conditionId, itemCode}], projectId}
+     * 为线程安全,使用concurrentHashMap
      */
-    private ConcurrentHashMap<String, AlarmDefine> alarmDefineMap = new ConcurrentHashMap<>();
+    private final ConcurrentHashMap<String, ObjConditionInfo> objConditionMap = new ConcurrentHashMap<>();
+
     /**
-     * 信息点-报警定义 <表号-功能号,[报警定义1,报警定义2]>
+     * 报警条件id -> 报警条件
      */
-    private ConcurrentHashMap<String, List<AlarmDefine>> infoAlarmMap = new ConcurrentHashMap<>();
-
+    private final ConcurrentHashMap<String, AlarmCondition> alarmConditionMap = new ConcurrentHashMap<>();
 
     /**
-     * 报警定义  <报警定义标识,报警时间状态>
-     * 报警定义标识默认为:报警编码-报警对象id
+     * (报警类型编码-报警对象id) -> 状态
+     * 报警类型和设备id可以确认唯一的报警条件
      */
-    private ConcurrentHashMap<String, AlarmDefineState> alarmStateMap = new ConcurrentHashMap<>();
+    private final ConcurrentHashMap<String, AlarmConditionState> alarmConditionStateMap = new ConcurrentHashMap<>();
 
     /**
      * @param :
@@ -56,13 +55,13 @@ public class AlarmInfoCache {
      * @since: 2020/10/20 17:12
      * @version: V1.0
      */
-    public AlarmDefineState getAlarmDefineState(String definitionId) {
-        return alarmStateMap.get(definitionId);
+    public AlarmConditionState getAlarmDefineState(String definitionId) {
+        return alarmConditionStateMap.get(definitionId);
     }
 
     /**
      * @param definitionId: 报警定义id
-     * @param alarmState:   报警状态时间类
+     * @param alarmConditionState:   报警状态时间类
      * @description:设置报警定义
      * @exception:
      * @author: LuoGuangyi
@@ -71,234 +70,117 @@ public class AlarmInfoCache {
      * @since: 2020/10/20 17:15
      * @version: V1.0
      */
-    public AlarmDefineState setAlarmState(String definitionId, AlarmDefineState alarmState) {
-        return alarmStateMap.put(definitionId, alarmState);
+    public AlarmConditionState setAlarmState(String definitionId, AlarmConditionState alarmConditionState) {
+        return alarmConditionStateMap.put(definitionId, alarmConditionState);
     }
 
-    /**
-     * 获取报警定义Map <报警定义标识,报警定义详情>
-     *
-     * @return
-     */
-    public ConcurrentHashMap<String, AlarmDefine> getAlarmDefineMap() {
-        return alarmDefineMap;
+   /**
+    * 根据报警对象id获取关联的报警条件
+    *
+    * @param objId 报警对象id
+    * @return 关联的报警条件信息
+    * @author lixing
+    * @version V1.0 2021/10/22 4:46 下午
+    */
+    public ObjConditionInfo getAlarmConditionsByObjId(String objId) {
+        return objConditionMap.get(objId);
     }
 
-    /**
-     * 设置报警定义Map <报警定义标识,报警定义详情>
-     *
-     * @return
-     */
-    public void setAlarmDefineMap(ConcurrentHashMap<String, AlarmDefine> alarmDefineMap) {
-        this.alarmDefineMap = alarmDefineMap;
-    }
 
     /**
-     * 获取信息点-报警定义map <表号-功能号,[报警定义1,报警定义2]>
+     * 清空缓存
      *
-     * @return
+     * @author lixing
+     * @version V1.0 2021/10/25 9:50 上午
      */
-    public ConcurrentHashMap<String, List<AlarmDefine>> getInfoAlarmMap() {
-        return infoAlarmMap;
-    }
-
-    /**
-     * 设置信息点-报警定义map <表号-功能号,[报警定义1,报警定义2]>
-     *
-     * @return
-     */
-    public void setInfoAlarmMap(ConcurrentHashMap<String, List<AlarmDefine>> infoAlarmMap) {
-        this.infoAlarmMap = infoAlarmMap;
+    public void clear() {
+        objConditionMap.clear();
+        alarmConditionMap.clear();
+        //清除编译表达式缓存
+        AviatorEvaluator.getInstance().clearExpressionCache();
     }
 
     /**
-     * @param definitionId :
-     * @description:根据报警定义id获取报警定义详情
+     * @param alarmDefine:
+     * @description:获取报警定义id, 中台报警定义ID没有实际意义,根据itemCode-objId拼接作为唯一标识
      * @exception:
      * @author: LuoGuangyi
      * @company: Persagy Technology Co.,Ltd
-     * @return: AlarmDefine 报警定义详情
-     * @since: 2020/10/19 14:32
+     * @since: 2020/10/19 17:28
      * @version: V1.0
      */
-    public AlarmDefine getAlarmDefinitionById(String definitionId) {
-        return alarmDefineMap.get(definitionId);
+    public static String getAlarmDefineId(AlarmDefine alarmDefine) {
+        return alarmDefine.getItemCode() + "-" + alarmDefine.getObjId();
     }
 
-
     /**
-     * @param definitionId:报警定义ID
-     * @param alarmDefine:报警定义详情
-     * @description:保存报警定义详情
-     * @exception:
-     * @author: LuoGuangyi
-     * @company: Persagy Technology Co.,Ltd
-     * @return: void
-     * @since: 2020/10/19 14:32
-     * @version: V1.0
+     * 获取报警条件
+     *
+     * @param conditionId 报警条件id
+     * @return 报警条件
+     * @author lixing
+     * @version V1.0 2021/10/22 5:04 下午
      */
-    public void putAlarmDefinitionById(String definitionId, AlarmDefine alarmDefine) {
-        if (alarmDefine.getOpen() == 0) {
-            return;
-        }
-        Condition condition = alarmDefine.getCondition();
-        List<JSONObject> infoCodes = condition.getInfoCodes();
-        if (CollectionUtil.isEmpty(infoCodes)) {
-            log.error("报警定义ID为[{}],报警定义详情为[{}] 的报警定义信息点为空,请检查!!!!!  ", definitionId, alarmDefine.toString());
-            return;
-        }
-        String trigger = condition.getTrigger();
-        String end = condition.getEnd();
-        try {
-            Expression triggerCompiledExp = AviatorEvaluator.compile(trigger, true);
-        } catch (Exception e) {
-            log.info("触发表达式:{}", trigger);
-            log.error("触发表表达式不合法,请校验", e);
-            throw new IllegalArgumentException("触发表表达式不合法", e);
-        }
-        try {
-            Expression endCompiledExp = AviatorEvaluator.compile(end, true);
-        } catch (Exception e) {
-            log.error("恢复表达式:{}", end);
-            log.error("恢复表达式不合法,请校验", e);
-            throw new IllegalArgumentException("恢复表达式不合法", e);
-        }
-        alarmDefineMap.put(definitionId, alarmDefine);
-        for (JSONObject infoCode : infoCodes) {
-            String meterId = infoCode.getString("meterId");
-            String funcId = infoCode.getString("funcId");
-            putAlarmDefinitionIdByMeterFuncId(meterId, funcId, alarmDefine);
-        }
+    public AlarmCondition getAlarmCondition(String conditionId) {
+        return alarmConditionMap.get(conditionId);
     }
 
-    public void putAlarmDefinitionById(AlarmDefine alarmDefine) {
-        putAlarmDefinitionById(getAlarmDefineId(alarmDefine), alarmDefine);
-    }
-
-
     /**
-     * @param meterId: 表号
-     * @param funcId:  功能号
-     * @description:根据表号功能号获取多条报警定义
-     * @exception:
-     * @author: LuoGuangyi
-     * @company: Persagy Technology Co.,Ltd
-     * @return: java.util.List<com.alibaba.fastjson.JSONObject>
-     * @since: 2020/10/19 14:31
-     * @version: V1.0
+     * 缓存报警条件
+     *
+     * @param alarmCondition 报警条件
+     * @author lixing
+     * @version V1.0 2021/10/22 5:04 下午
      */
-    public List<AlarmDefine> getAlarmDefinitionsByMeterFuncId(String meterId, String funcId) {
-        return infoAlarmMap.get(getKey(meterId, funcId));
+    public void cacheAlarmCondition(AlarmCondition alarmCondition) {
+        alarmConditionMap.put(alarmCondition.getId(), alarmCondition);
     }
 
-
     /**
-     * @param meterId:    表号
-     * @param funcId:     功能号
-     * @param definition: 报警定义
-     * @description:根据表号功能号缓存报警定义
-     * @exception:
-     * @author: LuoGuangyi
-     * @company: Persagy Technology Co.,Ltd
-     * @return: void
-     * @since: 2020/10/19 14:26
-     * @version: V1.0
+     * 缓存报警条件列表
+     *
+     * @param alarmConditions 报警条件列表
+     * @author lixing
+     * @version V1.0 2021/10/22 5:04 下午
      */
-    public void putAlarmDefinitionIdByMeterFuncId(String meterId, String funcId, AlarmDefine definition) {
-        List<AlarmDefine> definitionList = getAlarmDefinitionsByMeterFuncId(meterId, funcId);
-        if (CollectionUtils.isEmpty(definitionList)) {
-            definitionList = new ArrayList<>();
+    public void cacheAlarmConditions(List<AlarmCondition> alarmConditions) {
+        if (CollectionUtils.isEmpty(alarmConditions)) {
+            return;
         }
-        //去重并添加
-        definitionList = definitionList.stream().filter(a -> !getAlarmDefineId(definition).equals(getAlarmDefineId(a))).collect(Collectors.toList());
-        definitionList.add(definition);
-        infoAlarmMap.put(getKey(meterId, funcId), definitionList);
-    }
-
-
-    /**
-     * @description:删除所有缓存的报警定义
-     * @exception:
-     * @author: LuoGuangyi
-     * @company: Persagy Technology Co.,Ltd
-     * @return: void
-     * @since: 2020/10/19 14:25
-     * @version: V1.0
-     */
-    public void clearAllAlarmDefine() {
-        alarmDefineMap.clear();
-        infoAlarmMap.clear();
-        //清除编译表达式缓存
-        AviatorEvaluator.getInstance().clearExpressionCache();
-    }
-
-    /**
-     * @param ad: 要删除掉的报警定义
-     * @description:根据报警定义删除缓存
-     * @exception:
-     * @author: LuoGuangyi
-     * @company: Persagy Technology Co.,Ltd
-     * @return: void
-     * @since: 2020/10/26 20:34
-     * @version: V1.0
-     */
-    public void clearAlarmDefine(AlarmDefine ad) {
-        String defineId = getAlarmDefineId(ad);
-        AlarmDefine alarmDefine = alarmDefineMap.get(defineId);
-        if (!Objects.isNull(alarmDefine)) {
-            List<JSONObject> infoCodes = alarmDefine.getCondition().getInfoCodes();
-            // 删除map中报警定义相关信息点与要删除的报警定义的映射
-            infoCodes.stream().forEach(info -> {
-                String meterId = info.getString("meterId");
-                String funcId = info.getString("funcId");
-                List<AlarmDefine> AlarmDefineList = infoAlarmMap.getOrDefault(getKey(meterId, funcId), new ArrayList<>());
-                // 过滤掉要删除的报警定义
-                infoAlarmMap.put(getKey(meterId, funcId),
-                        AlarmDefineList.stream().filter(
-                                adTmp -> !getAlarmDefineId(adTmp).equals(defineId)
-                        ).collect(Collectors.toList()));
-            });
+        for (AlarmCondition alarmCondition : alarmConditions) {
+            cacheAlarmCondition(alarmCondition);
         }
-        alarmDefineMap.remove(defineId);
-    }
-
-    /**
-     * @param alarmDefine:
-     * @description:获取报警定义id, 中台报警定义ID没有实际意义,根据itemCode-objId拼接作为唯一标识
-     * @exception:
-     * @author: LuoGuangyi
-     * @company: Persagy Technology Co.,Ltd
-     * @since: 2020/10/19 17:28
-     * @version: V1.0
-     */
-    public static String getAlarmDefineId(AlarmDefine alarmDefine) {
-        return alarmDefine.getItemCode() + "-" + alarmDefine.getObjId();
     }
 
-    /**
-     * @param meterId:表号
-     * @param funcId:功能号
-     * @description:判断是否包含有改表号功能号的改报警定义
-     * @exception:
-     * @author: LuoGuangyi
-     * @company: Persagy Technology Co.,Ltd
-     * @return: boolean
-     * @since: 2020/10/19 19:54
-     * @version: V1.0
-     */
-    public boolean hasKey(String meterId, String funcId) {
-        return infoAlarmMap.containsKey(getKey(meterId, funcId));
-    }
 
     /**
-     * 拼接表号-功能号为一个key
+     * 缓存对象与条件的关联关系
      *
-     * @param meterId
-     * @param funcId
-     * @return
+     * @param objConditionRels 对象与条件的关联关系
+     * @author lixing
+     * @version V1.0 2021/10/25 10:36 上午
      */
-    private String getKey(String meterId, String funcId) {
-        return meterId + "-" + funcId;
+    public void cacheObjConditionRels(List<ObjConditionRel> objConditionRels) {
+        if (CollectionUtils.isEmpty(objConditionRels)) {
+            return;
+        }
+        for (ObjConditionRel objConditionRel : objConditionRels) {
+            // 报警对象id
+            String objId = objConditionRel.getObjId();
+            // 报警对象和报警条件的关联信息
+            ObjConditionInfo objConditionInfo;
+            if (objConditionMap.containsKey(objId)) {
+                objConditionInfo = objConditionMap.get(objId);
+            } else {
+                objConditionInfo = new ObjConditionInfo(objConditionRel.getProjectId());
+            }
+            ItemCodeCondition condition = new ItemCodeCondition();
+            condition.setConditionId(objConditionRel.getConditionId());
+            condition.setItemCode(objConditionRel.getItemCode());
+            // 对象内部自己做去重操作
+            objConditionInfo.addCondition(condition);
+        }
     }
 
+
 }

+ 0 - 68
src/main/java/com/persagy/cache/CurrentDataCache.java

@@ -1,68 +0,0 @@
-package com.persagy.cache;
-
-import org.springframework.stereotype.Component;
-
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * @description: 实时数据
- * @author: feng
- * @company: Persagy Technology Co.,Ltd
- * @since: 2020/7/16 15:50
- * @version: V1.0
- */
-@Component
-public class CurrentDataCache {
-
-    private ConcurrentHashMap<String, Double> latestIOTDataMap = new ConcurrentHashMap<>();
-
-    /**
-     * @description:获取设备实时数据
-     * @exception:
-     * @author: LuoGuangyi
-     * @company: Persagy Technology Co.,Ltd
-     * @param meterId: 表号
-     * @param funcId: 功能号
-     * @return: java.lang.String
-     * @since: 2020/10/19 16:15
-     * @version: V1.0
-     */
-    public double getCurrentData(String meterId, String funcId) {
-        return latestIOTDataMap.get(getKey(meterId, funcId));
-    }
-
-    private String getKey(String meterId,String funcId) {
-        return meterId + "-" + funcId;
-    }
-
-    /**
-     * @description:存放实时数据
-     * @exception:
-     * @author: LuoGuangyi
-     * @company: Persagy Technology Co.,Ltd
-     * @param meterId: 表号
-     * @param funcId: 功能号
-     * @param currentData: 当前值
-     * @return: void
-     * @since: 2020/10/19 16:16
-     * @version: V1.0
-     */
-    public void putCurrentData(String meterId, String funcId, double currentData) {
-        latestIOTDataMap.put(getKey(meterId,funcId), currentData);
-    }
-
-    /**
-     * @description:判断是否包含有改表号功能号的数据
-     * @exception:
-     * @author: LuoGuangyi
-     * @company: Persagy Technology Co.,Ltd
-     * @param meterId:表号
-     * @param funcId:功能号
-     * @return: boolean
-     * @since: 2020/10/19 19:54
-     * @version: V1.0
-     */
-    public boolean hasKey(String meterId,String funcId) {
-        return latestIOTDataMap.containsKey(getKey(meterId,funcId));
-    }
-}

+ 3 - 3
src/main/java/com/persagy/client/GroupNettyClient.java

@@ -4,7 +4,7 @@ import com.persagy.cache.AlarmLastTimeCache;
 import com.persagy.cache.CreatedAlarmIdsCache;
 import com.persagy.job.NettyMessageQueue;
 import com.persagy.repository.AlarmRecordRepository;
-import com.persagy.service.AlarmDefineService;
+import com.persagy.service.impl.AlarmConditionServiceImpl;
 import io.netty.bootstrap.Bootstrap;
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelFuture;
@@ -35,7 +35,7 @@ import java.util.concurrent.ConcurrentHashMap;
 @Slf4j
 public class GroupNettyClient {
     @Autowired
-    AlarmDefineService alarmDefineService;
+    AlarmConditionServiceImpl alarmConditionService;
     @Autowired
     AlarmRecordRepository alarmRecordRepository;
     @Autowired
@@ -94,7 +94,7 @@ public class GroupNettyClient {
                             // pipeline可以理解为所有handler的初始化容器
                             ch.pipeline().addLast(new GroupNettyClientHandler(
                                     groupNettyClient,
-                                    alarmDefineService,
+                                    alarmConditionService,
                                     alarmRecordRepository,
                                     createdAlarmIdsCache,
                                     alarmLastTimeCache));// 添加自定义handler

+ 69 - 38
src/main/java/com/persagy/client/GroupNettyClientHandler.java

@@ -9,10 +9,11 @@ import com.persagy.cache.AlarmLastTimeCache;
 import com.persagy.cache.CreatedAlarmIdsCache;
 import com.persagy.entity.AlarmDefine;
 import com.persagy.entity.NettyMessage;
-import com.persagy.entity.ZktAlarmRecordDO;
+import com.persagy.entity.v2.AlarmCondition;
+import com.persagy.entity.v2.ObjConditionRel;
 import com.persagy.job.NettyMessageQueue;
 import com.persagy.repository.AlarmRecordRepository;
-import com.persagy.service.AlarmDefineService;
+import com.persagy.service.impl.AlarmConditionServiceImpl;
 import com.persagy.utils.LockUtil;
 import com.persagy.utils.StringUtil;
 import io.netty.channel.ChannelHandlerContext;
@@ -20,9 +21,8 @@ import io.netty.channel.ChannelInboundHandlerAdapter;
 import io.netty.handler.timeout.IdleState;
 import io.netty.handler.timeout.IdleStateEvent;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
+import org.springframework.util.CollectionUtils;
 
-import javax.transaction.Transactional;
 import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
@@ -41,7 +41,7 @@ public class GroupNettyClientHandler extends ChannelInboundHandlerAdapter {
     // Reconnect when the server sends nothing for 10 seconds.
     private static final int READ_TIMEOUT = Integer.parseInt(System.getProperty("readTimeout", "10"));
 
-    private AlarmDefineService alarmDefineService;
+    private AlarmConditionServiceImpl alarmConditionService;
     private GroupNettyClient groupNettyClient;
     private AlarmRecordRepository alarmRecordRepository;
     private CreatedAlarmIdsCache createdAlarmIdsCache;
@@ -50,11 +50,11 @@ public class GroupNettyClientHandler extends ChannelInboundHandlerAdapter {
 
     public GroupNettyClientHandler(
             GroupNettyClient groupNettyClient,
-            AlarmDefineService alarmDefineService,
+            AlarmConditionServiceImpl alarmConditionService,
             AlarmRecordRepository alarmRecordRepository,
             CreatedAlarmIdsCache createdAlarmIdsCache,
             AlarmLastTimeCache alarmLastTimeCache) {
-        this.alarmDefineService = alarmDefineService;
+        this.alarmConditionService = alarmConditionService;
         this.groupNettyClient = groupNettyClient;
         this.alarmRecordRepository = alarmRecordRepository;
         this.createdAlarmIdsCache = createdAlarmIdsCache;
@@ -84,10 +84,10 @@ public class GroupNettyClientHandler extends ChannelInboundHandlerAdapter {
     @Override
     public void channelActive(ChannelHandlerContext ctx) throws Exception {
         log.info("Connected to: " + ctx.channel().remoteAddress());
-        ctx.channel().writeAndFlush(new NettyMessage<>(200,groupNettyClient.projectId).toString());
+        ctx.channel().writeAndFlush(new NettyMessage<>(200, groupNettyClient.projectId).toString());
         //启动的时候发送消息,获取全部报警定义
         //{"groupCode":"wd", "projectId":"Pj123"}
-        NettyMessage nettyMessage = new NettyMessage(4,groupNettyClient.projectId);
+        NettyMessage nettyMessage = new NettyMessage(4, groupNettyClient.projectId);
         nettyMessage.setRemark("连接已经建立;");
         JSONObject content = new JSONObject();
         content.put("groupCode", groupNettyClient.groupCode);
@@ -102,13 +102,13 @@ public class GroupNettyClientHandler extends ChannelInboundHandlerAdapter {
         try {
             log.info("--initAlarmResult--");
             TimeInterval timer = DateUtil.timer();
-            while (NettyMessageQueue.getNettyMessageQueue().size()>0 && timer.interval()<10000){
+            while (NettyMessageQueue.getNettyMessageQueue().size() > 0 && timer.interval() < 10000) {
                 String msg = NettyMessageQueue.getNettyMessageQueue().consume();
-                log.info("剩余报警消息令总数:{}",NettyMessageQueue.getNettyMessageQueue().size());
+                log.info("剩余报警消息令总数:{}", NettyMessageQueue.getNettyMessageQueue().size());
                 ctx.writeAndFlush(msg);
             }
         } catch (Exception e) {
-            log.error("发送报警消息失败",e);
+            log.error("发送报警消息失败", e);
         }
     }
 
@@ -124,7 +124,7 @@ public class GroupNettyClientHandler extends ChannelInboundHandlerAdapter {
         if (StringUtil.isJSONObject((String) msg)) {
             NettyMessage message = StringUtil.tranferItemToDTO((String) msg, NettyMessage.class);
             if (message.getOpCode() != 9) {
-                log.info("Client received: {}",msg);
+                log.info("Client received: {}", msg);
             } else {
                 log.info("全量获取报警定义完成");
             }
@@ -133,7 +133,7 @@ public class GroupNettyClientHandler extends ChannelInboundHandlerAdapter {
         try {
             TimeInterval timer = DateUtil.timer();
             handlerMsg(ctx, msg);
-            log.info("处理消息时间[{}]",timer.interval());
+            log.info("处理消息时间[{}]", timer.interval());
         } catch (Exception e) {
             log.error("channelRead", e);
         }
@@ -143,41 +143,27 @@ public class GroupNettyClientHandler extends ChannelInboundHandlerAdapter {
         if (StringUtil.isJSONObject((String) msg)) {
             NettyMessage message = StringUtil.tranferItemToDTO((String) msg, NettyMessage.class);
             if (message.getOpCode() == 9) {
-                NettyMessage<AlarmDefine> AlarmDefineMessage = JSONObject.parseObject(String.valueOf(msg), new TypeReference<NettyMessage<AlarmDefine>>() {
-                });
-                List<AlarmDefine> definesList = AlarmDefineMessage.getContent();
-                if (CollectionUtil.isNotEmpty(definesList)) {
-                    try {
-                        LockUtil.getInstance().lock.lock();
-                        LockUtil.getInstance().setExecute(false);
-                        //加个等待,保证正在执行的逻辑执行成功
-                        Thread.sleep(4000);
-                        alarmDefineService.listAllAlarmDefine(definesList);
-                        LockUtil.getInstance().setExecute(true);
-                        LockUtil.getInstance().condition.signalAll();
-                    } catch (Exception e) {
-                        log.error("全量获取报警定义发生异常", e);
-                    } finally {
-                        LockUtil.getInstance().lock.unlock();
-                    }
-                }
+                log.info("开始全量同步报警条件");
+                cacheAlarmConditions(msg);
             } else if (message.getOpCode() == 7) {
-                NettyMessage<AlarmDefine> alarmDefineNettyMessage = JSONObject.parseObject(String.valueOf(msg), new TypeReference<NettyMessage<AlarmDefine>>() {
-                });
+                NettyMessage<AlarmDefine> alarmDefineNettyMessage = JSONObject.parseObject(
+                        String.valueOf(msg),
+                        new TypeReference<NettyMessage<AlarmDefine>>() {
+                        });
                 List<AlarmDefine> definesList = alarmDefineNettyMessage.getContent();
                 if (CollectionUtil.isNotEmpty(definesList)) {
-                    alarmDefineService.listSomeAlarmDefine(definesList);
+                    alarmConditionService.listSomeAlarmDefine(definesList);
                 }
             } else if (message.getOpCode() == 10) {
                 NettyMessage<AlarmDefine> alarmDefineNettyMessage = JSONObject.parseObject(String.valueOf(msg), new TypeReference<NettyMessage<AlarmDefine>>() {
                 });
                 List<AlarmDefine> definesList = alarmDefineNettyMessage.getContent();
                 if (CollectionUtil.isNotEmpty(definesList)) {
-                    alarmDefineService.deleteAlarmDefine(definesList);
+                    alarmConditionService.deleteAlarmDefine(definesList);
                 }
-            }else if (message.getOpCode() == 8) {
+            } else if (message.getOpCode() == 8) {
                 log.info("云端完成报警记录创建");
-                log.info("返回报警记录id[{}]",message);
+                log.info("返回报警记录id[{}]", message);
                 //{"id":"","objId":"","itemCode":""}  id为报警记录ID
 
                 List content = message.getContent();
@@ -188,6 +174,20 @@ public class GroupNettyClientHandler extends ChannelInboundHandlerAdapter {
                     createdAlarmIdsCache.put(alarmId);
                     alarmLastTimeCache.setAlarmHasCreated(alarmId);
                 }
+            } else if (message.getOpCode() == 11) {
+                log.info("正在同步报警条件与设备的关联关系");
+                NettyMessage<ObjConditionRel> objConditionRelNettyMessage = JSONObject.parseObject(
+                        String.valueOf(msg),
+                        new TypeReference<NettyMessage<ObjConditionRel>>() {
+                        });
+
+                List<ObjConditionRel> content = objConditionRelNettyMessage.getContent();
+                if (CollectionUtils.isEmpty(content)) {
+                    log.info("接收到的消息中报警条件与设备的关联关系为空");
+                }
+                log.info("报警条件与设备的关联关系 -> 项目id:[{}], 同步条数[{}]",
+                        content.get(0).getProjectId(), content.size());
+                alarmConditionService.cacheObjConditionRels(content);
             }
             NettyMessage response = new NettyMessage(groupNettyClient.projectId);
             response.setOpCode(3);
@@ -196,6 +196,37 @@ public class GroupNettyClientHandler extends ChannelInboundHandlerAdapter {
         }
     }
 
+
+    /**
+     * 缓存报警条件
+     *
+     * @param msg 全量报警条件消息
+     * @author lixing
+     * @version V1.0 2021/10/22 3:21 下午
+     */
+    private void cacheAlarmConditions(Object msg) {
+        NettyMessage<AlarmCondition> alarmConditionNettyMessage = JSONObject.parseObject(
+                String.valueOf(msg),
+                new TypeReference<NettyMessage<AlarmCondition>>() {
+                });
+        List<AlarmCondition> conditionList = alarmConditionNettyMessage.getContent();
+        if (CollectionUtil.isNotEmpty(conditionList)) {
+            try {
+                LockUtil.getInstance().lock.lock();
+                LockUtil.getInstance().setExecute(false);
+                //加个等待,保证正在执行的逻辑执行成功
+                Thread.sleep(4000);
+                alarmConditionService.cacheAllConditions(conditionList);
+                LockUtil.getInstance().setExecute(true);
+                LockUtil.getInstance().condition.signalAll();
+            } catch (Exception e) {
+                log.error("全量同步报警条件发生异常", e);
+            } finally {
+                LockUtil.getInstance().lock.unlock();
+            }
+        }
+    }
+
     @Override
     public void channelReadComplete(ChannelHandlerContext ctx) {
         ctx.flush();

+ 58 - 150
src/main/java/com/persagy/controller/HelloWorld.java

@@ -7,10 +7,8 @@ import com.googlecode.aviator.Expression;
 import com.persagy.cache.AlarmInfoCache;
 import com.persagy.client.GroupNettyClient;
 import com.persagy.entity.NettyMessage;
-import com.persagy.entity.ZktAlarmRecordDO;
 import com.persagy.repository.AlarmRecordRepository;
 import com.persagy.service.AlarmHandleService;
-import com.persagy.utils.LockUtil;
 import io.swagger.annotations.Api;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -19,159 +17,69 @@ import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
-import javax.transaction.Transactional;
-import java.util.*;
-import java.util.concurrent.atomic.AtomicInteger;
+import java.util.Arrays;
+import java.util.HashMap;
 
 @Api(tags = "hello")
 @RestController
 @RequestMapping("hello")
 @Slf4j
 public class HelloWorld {
-	@Autowired
-	AlarmHandleService alarmHandleService;
-
-	@Autowired
-	private GroupNettyClient groupNettyClient;
-	@Autowired
-	AlarmInfoCache alarmInfoCache;
-	@Autowired
-	AlarmRecordRepository alarmRecordRepository;
-	@PostMapping("/")
-	public String world(@RequestBody JSONObject jsonObject) throws Exception {
-		return "hello world!";
-	}
-	@PostMapping("/testMesage")
-	public String testMesage(@RequestBody JSONObject jsonObject) throws Exception {
-		NettyMessage nettyMessage = new NettyMessage(groupNettyClient.projectId);
-		nettyMessage.setRemark("连接已经建立;");
-		nettyMessage.setOpCode(4);
-		JSONObject content = new JSONObject();
-		content.put("groupCode", groupNettyClient.groupCode);
-		content.put("projectId", groupNettyClient.projectId);
-		nettyMessage.setContent(Arrays.asList(content));
-		groupNettyClient.sendMessage(nettyMessage.toString());
-		return "成功";
-	}
-
-	@PostMapping("/testMesage5")
-	public String testMesage5(@RequestBody JSONObject jsonObject) throws Exception {
-		NettyMessage nettyMessage = new NettyMessage(groupNettyClient.projectId);
-		nettyMessage.setRemark("连接已经建立;");
-		nettyMessage.setOpCode(5);
-		jsonObject.put("groupCode", groupNettyClient.groupCode);
-		jsonObject.put("projectId", groupNettyClient.projectId);
-		nettyMessage.setContent(Arrays.asList(jsonObject));
-		groupNettyClient.sendMessage(nettyMessage.toString());
-		return "成功";
-	}
-
-	@PostMapping("/test")
-	public String test(@RequestBody JSONObject jsonObject) throws Exception {
-		LockUtil.getInstance().lock.lock();
-		try {
-			LockUtil.getInstance().setExecute(!LockUtil.getInstance().isExecute());
-			//加个等待,保证正在执行的逻辑执行成功
-			Thread.sleep(2000);
-			if(LockUtil.getInstance().isExecute()){
-				LockUtil.getInstance().condition.signalAll();
-			}
-		} catch (InterruptedException e) {
-			e.printStackTrace();
-		} finally {
-			LockUtil.getInstance().lock.unlock();
-		}
-		AtomicInteger atomicInteger = new AtomicInteger(0);
-		alarmInfoCache.getAlarmDefineMap().entrySet().forEach(entry->{
-//			log.info("[{}]的key:[{}],value:[{}]",atomicInteger.getAndIncrement(),entry.getKey(),entry.getValue());
-		});
-		return "成功";
-	}
-
-	@PostMapping("/test2")
-	public String test2(@RequestBody JSONObject jsonObject) throws Exception {
-		String message = jsonObject.getString("message");
-		alarmHandleService.handleIotMsg(message);
-		return "成功";
-	}
-
-	@PostMapping("/test3")
-	public ArrayList<ZktAlarmRecordDO> test3(@RequestBody JSONObject jsonObject) throws Exception {
-		String defineId = jsonObject.getString("itemCode") + "-" + jsonObject.getString("objId");
-		ZktAlarmRecordDO zktAlarmRecordDO = alarmRecordRepository.findById(defineId).orElse(new ZktAlarmRecordDO());
-		zktAlarmRecordDO.setDefinitionId(defineId);
-		zktAlarmRecordDO.setItemCode(jsonObject.getString("itemCode"));
-		zktAlarmRecordDO.setObjId(jsonObject.getString("objId"));
-		zktAlarmRecordDO.setAlarmId(jsonObject.getString("id"));
-		ZktAlarmRecordDO save = alarmRecordRepository.save(zktAlarmRecordDO);
-		log.info("保存结果为:{}",save);
-		Iterable<ZktAlarmRecordDO> all = alarmRecordRepository.findAll();
-		Iterator<ZktAlarmRecordDO> iterator = all.iterator();
-		ArrayList<ZktAlarmRecordDO> list = new ArrayList<>();
-		while (iterator.hasNext()) {
-			list.add(iterator.next());
-		}
-		return list;
-	}
-
-	@PostMapping("/test4")
-	public void test4() throws Exception {
-		String defineId = "2004-VOEi56c25a67412a417fbf225ca1722f3a27";
-		Thread thread1 = new Thread() {
-			@Override
-			public void run() {
-				try {
-					log.info("{}开始,参数为: {}, {}", Thread.currentThread().getName(), null, "1");
-					alarmRecordFindAndUpdate(defineId, null, "1");
-				} catch (Exception e) {
-					e.printStackTrace();
-				}
-			}
-		};
-		thread1.start();
-
-		Thread thread2 = new Thread() {
-			@Override
-			public void run() {
-				try {
-					log.info("{}开始,参数为: {}, {}", Thread.currentThread().getName(), "xxx", "2");
-					alarmRecordFindAndUpdate(defineId, "xxx", "2");
-				} catch (Exception e) {
-					e.printStackTrace();
-				}
-			}
-		};
-		thread2.start();
-	}
-
-	@Transactional
-	public void alarmRecordFindAndUpdate(String defineId, String alarmId, String state) throws Exception {
-		Optional<ZktAlarmRecordDO> zktAlarmRecordDO = alarmRecordRepository.findById(defineId);
-		log.info("{}完成查询", Thread.currentThread().getName());
-		Thread.sleep(3000);
-		if (zktAlarmRecordDO.isPresent()) {
-			ZktAlarmRecordDO alarmRecordDO = zktAlarmRecordDO.get();
-			alarmRecordDO.setAlarmId(alarmId);
-			alarmRecordDO.setState(state);
-			alarmRecordRepository.save(alarmRecordDO);
-		}
-		log.info("{}完成更新", Thread.currentThread().getName());
-	}
-
-
-	private static boolean checkExpression(String expression, HashMap<String, Object> paramMap) {
-		Expression triggerExp = AviatorEvaluator.compile(expression, false);
-		// 执行报警条件公式,得到触发和恢复结果
-		return (Boolean) triggerExp.execute(paramMap);
-	}
-	public static void main(String[] args) {
-		String expression = "((Eq11010600015b743693f66e430e85334cc5e48cbf6d_ACATFU_SupplyAirTemp!=NaN && Eq11010600015b743693f66e430e85334cc5e48cbf6d_ACATFU_SupplyAirTemp!=NaN)) && (((Eq11010600015b743693f66e430e85334cc5e48cbf6d_ACATFU_SupplyAirTemp==NaN || Eq11010600015b743693f66e430e85334cc5e48cbf6d_ACATFU_SupplyAirTemp==NaN)?true:((Eq11010600015b743693f66e430e85334cc5e48cbf6d_ACATFU_SupplyAirTemp>=Eq11010600015b743693f66e430e85334cc5e48cbf6d_ACATFU_SupplyAirTemp))))";
-
-		HashMap<String, Object> paramMap = new HashMap<>();
-		paramMap.put("Eq11010600015b743693f66e430e85334cc5e48cbf6d_ACATFU_SupplyAirTemp", 1.0);
-//		paramMap.put("EnergyData", 6.125);
-//		paramMap.put("Pclose", 5.0);
-		System.out.println(checkExpression(expression, paramMap));
-	}
+    @Autowired
+    AlarmHandleService alarmHandleService;
+
+    @Autowired
+    private GroupNettyClient groupNettyClient;
+    @Autowired
+    AlarmInfoCache alarmInfoCache;
+    @Autowired
+    AlarmRecordRepository alarmRecordRepository;
+
+    @PostMapping("/")
+    public String world(@RequestBody JSONObject jsonObject) throws Exception {
+        return "hello world!";
+    }
+
+    @PostMapping("/testMesage")
+    public String testMesage(@RequestBody JSONObject jsonObject) throws Exception {
+        NettyMessage nettyMessage = new NettyMessage(groupNettyClient.projectId);
+        nettyMessage.setRemark("连接已经建立;");
+        nettyMessage.setOpCode(4);
+        JSONObject content = new JSONObject();
+        content.put("groupCode", groupNettyClient.groupCode);
+        content.put("projectId", groupNettyClient.projectId);
+        nettyMessage.setContent(Arrays.asList(content));
+        groupNettyClient.sendMessage(nettyMessage.toString());
+        return "成功";
+    }
+
+    @PostMapping("/testMesage5")
+    public String testMesage5(@RequestBody JSONObject jsonObject) throws Exception {
+        NettyMessage nettyMessage = new NettyMessage(groupNettyClient.projectId);
+        nettyMessage.setRemark("连接已经建立;");
+        nettyMessage.setOpCode(5);
+        jsonObject.put("groupCode", groupNettyClient.groupCode);
+        jsonObject.put("projectId", groupNettyClient.projectId);
+        nettyMessage.setContent(Arrays.asList(jsonObject));
+        groupNettyClient.sendMessage(nettyMessage.toString());
+        return "成功";
+    }
+
+    private static boolean checkExpression(String expression, HashMap<String, Object> paramMap) {
+        Expression triggerExp = AviatorEvaluator.compile(expression, false);
+        // 执行报警条件公式,得到触发和恢复结果
+        return (Boolean) triggerExp.execute(paramMap);
+    }
+
+    public static void main(String[] args) {
+        String expression = "((ACATAH_FreshAirH!=NaN && ACATAH_RunStatus!=NaN) || (ACATAH_FreshAirH!=NaN && ACATAH_FreshAirH!=NaN)) && (((ACATAH_FreshAirH==NaN || ACATAH_RunStatus==NaN)?false:((ACATAH_FreshAirH>=1) && (ACATAH_RunStatus==0))) || ((ACATAH_FreshAirH==NaN || ACATAH_FreshAirH==NaN)?false:((ACATAH_FreshAirH>=ACATAH_FreshAirH+1))))";
+
+        HashMap<String, Object> paramMap = new HashMap<>();
+        //		paramMap.put("ACATAH_FreshAirH", 1.0);
+        paramMap.put("ACATAH_RunStatus", 0.0);
+        //		paramMap.put("EnergyData", 6.125);
+        //		paramMap.put("Pclose", 5.0);
+        System.out.println(checkExpression(expression, paramMap));
+    }
 }
 

+ 3 - 7
src/main/java/com/persagy/entity/AlarmDefineState.java

@@ -11,19 +11,15 @@ import lombok.Data;
  * @version:V1.0
  **/
 @Data
-public class AlarmDefineState {
+public class AlarmConditionState {
     /**
-     * 报警定义ID
+     * 报警定义ID (报警类型编码-报警对象id)
      */
     private String definitionId;
     /**
      * 报警状态( 0-正常 1-报警)
      */
     private String state = "0";
-//    /**
-//     * 最近下一次数据正常状态
-//     */
-//    private boolean latestDataNormalstate = true;
     /**
      * 是否过期(0-未过期,1-已过期)
      */
@@ -37,7 +33,7 @@ public class AlarmDefineState {
      */
     private String alarmSuspendStartTime = "";
 
-    public AlarmDefineState(String definitionId) {
+    public AlarmConditionState(String definitionId) {
         this.definitionId = definitionId;
     }
 

+ 39 - 4
src/main/java/com/persagy/entity/AlarmDefine.java

@@ -1,6 +1,7 @@
 package com.persagy.entity;
 
 import com.alibaba.fastjson.JSONObject;
+import com.persagy.entity.v2.AlarmCondition;
 import lombok.Data;
 
 /**
@@ -88,12 +89,46 @@ public class AlarmDefine {
      */
     private int concern;
 
-
-
-
-
     @Override
     public String toString() {
         return JSONObject.toJSONString(this);
     }
+
+    /**
+     * 将报警条件转换为报警定义
+     *
+     * @param itemCode 报警类型编码
+     * @param alarmCondition 报警条件
+     * @param meterId 报警对象id
+     * @param projectId 项目id
+     * @return 报警定义
+     * @author lixing
+     * @version V1.0 2021/10/22 5:59 下午
+     */
+    public static AlarmDefine convert2AlarmDefine(
+            String itemCode, AlarmCondition alarmCondition, String meterId, String projectId) {
+        AlarmDefine alarmDefine = new AlarmDefine();
+        alarmDefine.setId(itemCode + "-" + meterId);
+        alarmDefine.setObjId(meterId);
+        alarmDefine.setProjectId(projectId);
+        alarmDefine.setLevel(alarmCondition.getAlarmLevel());
+        alarmDefine.setItemCode(itemCode);
+        // 屏蔽状态 1-生效 0-屏蔽
+        alarmDefine.setOpen(1);
+        // 设置报警条件
+        Condition condition = new Condition();
+        condition.setInfoCode(alarmCondition.getInfoCodes());
+        condition.setConfigs(JSONObject.toJSONString(alarmCondition.getTriggerFrontend()));
+        JSONObject effectTime = alarmCondition.getEffectTimeDetail();
+        effectTime.put("type", alarmCondition.getEffectTimeType());
+        condition.setEffectTime(effectTime);
+        condition.setRules(alarmCondition.getTriggerRules());
+        condition.setTrigger(alarmCondition.getTriggerBackend());
+        condition.setEnd(alarmCondition.getEndBackend());
+        // 时间转换为秒
+        condition.setTriggerUphold(alarmCondition.getTriggerUphold() * 60);
+        condition.setEndUphold(alarmCondition.getEndUphold() * 60);
+        alarmDefine.setCondition(condition);
+        return alarmDefine;
+    }
 }

+ 0 - 1
src/main/java/com/persagy/entity/Condition.java

@@ -47,7 +47,6 @@ public class Condition {
     List<String> infoCode;
     private String configs;
     private List<String> rules;
-    List<JSONObject> infoCodes;
     private String trigger;
     private String end;
     private int triggerUphold;

+ 3 - 2
src/main/java/com/persagy/entity/NettyMessage.java

@@ -26,8 +26,9 @@ public class NettyMessage<T> {
      * 6-边缘端主动更新报警记录状态、
      * 7-云端推送修改的报警定义给边缘端(增量新增修改报警定义)、
      * 8-云端把报警记录的id推送到边缘端
-     * 9-边缘端取报警定义,云端推送给边缘端的标记(全量报警定义)
-     * 10-云端推送删除的报警定义给边缘端(增量删除报警定义)、
+     * 9-边缘端取报警条件,云端推送给边缘端的标记(全量报警条件)
+     * 10-云端推送删除的报警定义给边缘端(增量删除报警定义)
+     * 11-边缘端取设备与报警条件关联关系,云端推送给边缘端的标记(按项目推送)
      * 200 - 建立连接,此时的source == 项目id
      */
     @JSONField()

+ 78 - 0
src/main/java/com/persagy/entity/v2/AlarmCondition.java

@@ -0,0 +1,78 @@
+package com.persagy.entity.v2;
+
+import com.alibaba.fastjson.JSONObject;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 报警条件
+ *
+ * @author lixing
+ * @version V1.0 2021/10/22 3:24 下午
+ */
+@Data
+public class AlarmCondition {
+    /**
+     * 主键
+     */
+    private String id;
+
+    /**
+     * 包含的参数
+     */
+    private List<String> infoCodes;
+
+    /**
+     * 触发条件-前端展示
+     */
+    private List<List<CalculateMethodDTO>> triggerFrontend;
+
+    /**
+     * 触发条件-后端使用
+     */
+    private String triggerBackend;
+
+    /**
+     * 触发时长
+     */
+    private Integer triggerUphold;
+
+    /**
+     *报警等级
+     */
+    private String alarmLevel;
+
+    /**
+     * 持续多久后恢复
+     */
+    private Integer endUphold;
+
+    /**
+     * 触发规则-中文描述
+     */
+    private List<String> triggerRules;
+
+    //    @ApiModelProperty("恢复条件-前端")
+    //    private List<List<CalculateMethodDTO>> endFrontend;
+
+    /**
+     * 恢复条件-后端
+     */
+    private String endBackend;
+
+    /**
+     * 恢复规则-中文描述
+     */
+    private List<String> endRules;
+
+    /**
+     * 生效时间类型
+     */
+    private String effectTimeType;
+
+    /**
+     * 生效时间详情
+     */
+    private JSONObject effectTimeDetail;
+}

+ 40 - 0
src/main/java/com/persagy/entity/v2/CalculateMethodDTO.java

@@ -0,0 +1,40 @@
+package com.persagy.entity.v2;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 报警规则
+ *
+ * @author lixing
+ * @version V1.0 2021-09-08 22:43:58
+ */
+@Data
+public class CalculateMethodDTO {
+    /**
+     * 操作符
+     */
+    private String operator;
+    
+    /**
+     * 公式
+     */
+    private List<Formula> formula;
+    
+    /**
+     * 监测指标id
+     */
+    private String monitorIndicatorId;
+
+    /**
+     * 监测指标name
+     */
+    private String monitorIndicatorName;
+    
+    /**
+     * 临时存储公式
+     */
+    private String tempFormula;
+    
+}

+ 21 - 0
src/main/java/com/persagy/entity/v2/Formula.java

@@ -0,0 +1,21 @@
+package com.persagy.entity.v2;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 公式实体类
+ *
+ * @author lixing
+ * @version V1.0 2021-09-08 22:30:38
+ */
+@Data
+public class Formula implements Serializable {
+    private static final long serialVersionUID = 268657175929005281L;
+
+    private String key;
+    private String label;
+    private String value;
+
+}

+ 25 - 0
src/main/java/com/persagy/entity/v2/ItemCodeCondition.java

@@ -0,0 +1,25 @@
+package com.persagy.entity.v2;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 设备与报警条件的关联
+ *
+ * @author lixing
+ * @version V1.0 2021/10/22 9:42 上午
+ **/
+public class ItemCodeCondition {
+    /**
+     * 报警类型编码
+     */
+    @Setter
+    @Getter
+    private String itemCode;
+    /**
+     * 报警条件id
+     */
+    @Setter
+    @Getter
+    private String conditionId;
+}

+ 56 - 0
src/main/java/com/persagy/entity/v2/ObjConditionInfo.java

@@ -0,0 +1,56 @@
+package com.persagy.entity.v2;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.LinkedList;
+
+/**
+ * 设备的报警条件信息
+ *
+ * @author lixing
+ * @version V1.0 2021/10/22 9:42 上午
+ **/
+public class ObjConditionInfo {
+
+    public ObjConditionInfo(String projectId) {
+        this.projectId = projectId;
+        this.conditions = new LinkedList<>();
+    }
+    /**
+     * 项目id
+     */
+    @Setter
+    @Getter
+    private String projectId;
+
+    /**
+     * 报警条件列表[{itemCode, conditionId}]
+     */
+    @Setter
+    @Getter
+    private LinkedList<ItemCodeCondition> conditions;
+
+    /**
+     * 设备报警条件列表中添加一个条件
+     *
+     * @param itemCodeCondition 条件对象
+     * @author lixing
+     * @version V1.0 2021/10/25 11:30 上午
+     */
+    public void addCondition(ItemCodeCondition itemCodeCondition) {
+        if (itemCodeCondition == null) {
+            return;
+        }
+        if (conditions == null) {
+            conditions = new LinkedList<>();
+        }
+        // 如果存在相同报警类型的配置,删除之前的配置,添加新的配置
+        for (ItemCodeCondition condition : conditions) {
+            if (itemCodeCondition.getItemCode().equals(condition.getItemCode())) {
+                conditions.remove(condition);
+            }
+        }
+        conditions.add(itemCodeCondition);
+    }
+}

+ 25 - 0
src/main/java/com/persagy/entity/v2/ObjConditionRel.java

@@ -0,0 +1,25 @@
+package com.persagy.entity.v2;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 设备与报警条件的关联
+ *
+ * @author lixing
+ * @version V1.0 2021/10/22 9:42 上午
+ **/
+public class ObjConditionRel extends ItemCodeCondition {
+    /**
+     * 报警对象id
+     */
+    @Setter
+    @Getter
+    private String objId;
+    /**
+     * 项目id
+     */
+    @Setter
+    @Getter
+    private String projectId;
+}

+ 0 - 1
src/main/java/com/persagy/job/AlarmContinueJob.java

@@ -39,7 +39,6 @@ public class AlarmContinueJob extends QuartzJobBean {
     protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
         ConcurrentHashMap<String, AlarmLastTime> alarmLastTimeMap = alarmLastTimeCache.getAll();
         if (alarmLastTimeMap.isEmpty()) {return;}
-        log.info("向云端发送报警持续消息");
         for (String alarmId : alarmLastTimeMap.keySet()) {
             AlarmLastTime alarmLastTime = alarmLastTimeMap.get(alarmId);
             if (YesNoEnum.NO.equals(alarmLastTime.getHasSent()) &&

+ 4 - 4
src/main/java/com/persagy/job/AlarmExpireJob.java

@@ -6,7 +6,7 @@ import cn.hutool.core.date.DateUtil;
 import com.persagy.cache.AlarmInfoCache;
 import com.persagy.cache.CreatedAlarmIdsCache;
 import com.persagy.client.GroupNettyClient;
-import com.persagy.entity.AlarmDefineState;
+import com.persagy.entity.AlarmConditionState;
 import com.persagy.entity.AlarmRecord;
 import com.persagy.entity.NettyMessage;
 import com.persagy.entity.ZktAlarmRecordDO;
@@ -177,9 +177,9 @@ public class AlarmExpireJob extends QuartzJobBean {
 
                     // 过期任务执行时,如果报警仍是创建任务时的报警,重置报警定义的状态
                     if (AlarmDefineStateEnum.EXPIRED.getValue().equals(state)) {
-                        AlarmDefineState alarmState = new AlarmDefineState(this.defineId);
-                        alarmState.setAlarmStartTime("");
-                        alarmInfoCache.setAlarmState(this.defineId, alarmState);
+                        AlarmConditionState alarmConditionState = new AlarmConditionState(this.defineId);
+                        alarmConditionState.setAlarmStartTime("");
+                        alarmInfoCache.setAlarmState(this.defineId, alarmConditionState);
                     }
 
                     // 如果报警仍是创建任务时的报警,数据库中删除这条报警定义

+ 0 - 20
src/main/java/com/persagy/service/AlarmDefineService.java

@@ -1,20 +0,0 @@
-package com.persagy.service;
-
-import com.persagy.entity.AlarmDefine;
-
-import java.util.List;
-
-/**
- * @description:报警定义逻辑接口类(项目报警定义全量获取,报警定义添加修改删除同步更新)
- * @author:LuoGuangyi
- * @company:PersagyTechnologyCo.,Ltd
- * @since:2020/10/15 11:22
- * @version:V1.0
- **/
-public interface AlarmDefineService {
-    List listAllAlarmDefine(List<AlarmDefine> definesList);
-
-    void listSomeAlarmDefine(List<AlarmDefine> alarmDefineList);
-
-    void deleteAlarmDefine(List<AlarmDefine> alarmDefineList);
-}

+ 84 - 0
src/main/java/com/persagy/service/impl/AlarmConditionServiceImpl.java

@@ -0,0 +1,84 @@
+package com.persagy.service.impl;
+
+import com.persagy.cache.AlarmInfoCache;
+import com.persagy.entity.AlarmDefine;
+import com.persagy.entity.v2.AlarmCondition;
+import com.persagy.entity.v2.ObjConditionRel;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.util.List;
+
+/**
+ * 报警条件处理类
+ *
+ * @author lixing
+ * @version V1.0 2021/10/25 10:06 上午
+ */
+@Service
+public class AlarmConditionServiceImpl {
+    @Autowired
+    AlarmInfoCache alarmInfoCache;
+
+   /**
+    * 将报警定义缓存起来
+    *
+    * @param conditionList 报警定义类别
+    * @author lixing
+    * @version V1.0 2021/10/25 10:08 上午
+    */
+    public void cacheAllConditions(List<AlarmCondition> conditionList) {
+        // 先清空之前缓存的条件和关联关系
+        alarmInfoCache.clear();
+        alarmInfoCache.cacheAlarmConditions(conditionList);
+    }
+
+    /**
+     * @description:批量修改(添加)报警定义
+     * (根据报警条目+对象Id先删除,再添加)
+     * @exception:
+     * @author: LuoGuangyi
+     * @company: Persagy Technology Co.,Ltd
+     * @param alarmDefineList:
+     * @return: void
+     * @since: 2020/10/26 20:38
+     * @version: V1.0
+     */
+    public void listSomeAlarmDefine(List<AlarmDefine> alarmDefineList) {
+        for (AlarmDefine alarmDefine : alarmDefineList) {
+            alarmInfoCache.clearAlarmDefine(alarmDefine);
+            alarmInfoCache.putAlarmDefinitionById(alarmDefine);
+        }
+    }
+
+    /**
+     * @description:根据标号功能号删除报警定义
+     * @exception:
+     * @author: LuoGuangyi
+     * @company: Persagy Technology Co.,Ltd
+     * @param alarmDefineList:
+     * @return: void
+     * @since: 2020/10/29 18:26
+     * @version: V1.0
+     */
+    public void deleteAlarmDefine(List<AlarmDefine> alarmDefineList) {
+        for (AlarmDefine alarmDefine : alarmDefineList) {
+            alarmInfoCache.clearAlarmDefine(alarmDefine);
+        }
+    }
+
+    /**
+     * 缓存对象与条件的关联关系
+     *
+     * @param objConditionRels 对象与条件的关联关系
+     * @author lixing
+     * @version V1.0 2021/10/25 10:36 上午
+     */
+    public void cacheObjConditionRels(List<ObjConditionRel> objConditionRels) {
+        if (CollectionUtils.isEmpty(objConditionRels)) {
+            return;
+        }
+        alarmInfoCache.cacheObjConditionRels(objConditionRels);
+    }
+}

+ 0 - 119
src/main/java/com/persagy/service/impl/AlarmDefineServiceImpl.java

@@ -1,119 +0,0 @@
-package com.persagy.service.impl;
-
-import com.alibaba.fastjson.JSONObject;
-import com.alibaba.fastjson.TypeReference;
-import com.persagy.cache.AlarmInfoCache;
-import com.persagy.entity.AlarmDefine;
-import com.persagy.entity.NettyMessage;
-import com.persagy.service.AlarmDefineService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-
-/**
- * @description:报警定义逻辑实现类(项目报警定义全量获取,报警定义添加修改删除同步更新)
- * @author:LuoGuangyi
- * @company:PersagyTechnologyCo.,Ltd
- * @since:2020/10/15 11:24
- * @version:V1.0
- **/
-@Service
-public class AlarmDefineServiceImpl implements AlarmDefineService {
-    @Autowired
-    AlarmInfoCache alarmInfoCache;
-
-    @Override
-    public List listAllAlarmDefine(List<AlarmDefine> alarmDefineList) {
-//        String ad = "{\n" +
-//                "    \"streamId\": \"\",\n" +
-//                "    \"opCode\": \"\",\n" +
-//                "    \"content\": [\n" +
-//                "        {\n" +
-//                "            \"id\": 1,\n" +
-//                "            \"objId\": \"obj1\",\n" +
-//                "            \"itemCode\": \"1055\",\n" +
-//                "            \"projectId\": \"xxx\",\n" +
-//                "            \"name\": \"室内高温\",\n" +
-//                "            \"dealFunc\": \"point\",\n" +
-//                "            \"category\": \"环境报警\",\n" +
-//                "            \"level\": \"B\",\n" +
-//                "            \"remark\": \"我是备注哈\",\n" +
-//                "            \"open\": 1,\n" +
-//                "            \"condition\": {\n" +
-//                "                \"infoCode\": [\n" +
-//                "                    \"$infoCode1\",\n" +
-//                "                    \"$infoCode1\"\n" +
-//                "                ],\n" +
-//                "                \"infoCodeId\": [\n" +
-//                "                    {\n" +
-//                "                        \"infoCode\": \"infoCode1\",\n" +
-//                "                        \"meterId\": \"11\",\n" +
-//                "                        \"funcId\": \"12\"\n" +
-//                "                    },\n" +
-//                "                    {\n" +
-//                "                        \"infoCode\": \"infoCode2\",\n" +
-//                "                        \"meterId\": \"21\",\n" +
-//                "                        \"funcId\": \"22\"\n" +
-//                "                    }\n" +
-//                "                ],\n" +
-//                "                \"trigger\": \"($infoCode1 > 10 && $infoCode1 < 20) && ($infoCode2 < 20)\",\n" +
-//                "                \"end\": \"!($infoCode1 < 20 && $infoCode1 > 10)\",\n" +
-//                "                \"$triggerUphold\": 10,\n" +
-//                "                \"$endUphold\": 5,\n" +
-//                "                \"$time\": {\n" +
-//                "                    \"type\": \"period\",\n" +
-//                "                    \"period\": {\n" +
-//                "                        \"$gt\": \"090000\",\n" +
-//                "                        \"$lt\": \"210000\"\n" +
-//                "                    }\n" +
-//                "                }\n" +
-//                "            }\n" +
-//                "        }\n" +
-//                "    ]\n" +
-//                "}";
-//        NettyMessage<AlarmDefine> message = JSONObject.parseObject(ad,  new TypeReference<NettyMessage<AlarmDefine>>(){});
-//        List<AlarmDefine> alarmDefineList =message.getContent();
-        alarmInfoCache.clearAllAlarmDefine();
-        for (AlarmDefine alarmDefine : alarmDefineList) {
-            alarmInfoCache.putAlarmDefinitionById(alarmDefine);
-        }
-        return alarmDefineList;
-    }
-
-    /**
-     * @description:批量修改(添加)报警定义
-     * (根据报警条目+对象Id先删除,再添加)
-     * @exception:
-     * @author: LuoGuangyi
-     * @company: Persagy Technology Co.,Ltd
-     * @param alarmDefineList:
-     * @return: void
-     * @since: 2020/10/26 20:38
-     * @version: V1.0
-     */
-    @Override
-    public void listSomeAlarmDefine(List<AlarmDefine> alarmDefineList) {
-        for (AlarmDefine alarmDefine : alarmDefineList) {
-            alarmInfoCache.clearAlarmDefine(alarmDefine);
-            alarmInfoCache.putAlarmDefinitionById(alarmDefine);
-        }
-    }
-
-    /**
-     * @description:根据标号功能号删除报警定义
-     * @exception:
-     * @author: LuoGuangyi
-     * @company: Persagy Technology Co.,Ltd
-     * @param alarmDefineList:
-     * @return: void
-     * @since: 2020/10/29 18:26
-     * @version: V1.0
-     */
-    @Override
-    public void deleteAlarmDefine(List<AlarmDefine> alarmDefineList) {
-        for (AlarmDefine alarmDefine : alarmDefineList) {
-            alarmInfoCache.clearAlarmDefine(alarmDefine);
-        }
-    }
-}

+ 104 - 124
src/main/java/com/persagy/service/impl/AlarmHandleServiceImpl.java

@@ -9,9 +9,11 @@ import com.googlecode.aviator.Expression;
 import com.persagy.cache.AlarmInfoCache;
 import com.persagy.cache.AlarmLastTimeCache;
 import com.persagy.cache.CreatedAlarmIdsCache;
-import com.persagy.cache.CurrentDataCache;
 import com.persagy.client.GroupNettyClient;
 import com.persagy.entity.*;
+import com.persagy.entity.v2.AlarmCondition;
+import com.persagy.entity.v2.ItemCodeCondition;
+import com.persagy.entity.v2.ObjConditionInfo;
 import com.persagy.job.ExpireAlarmQueue;
 import com.persagy.repository.AlarmRecordRepository;
 import com.persagy.service.AlarmHandleService;
@@ -26,6 +28,7 @@ import org.quartz.JobDataMap;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
 
 import java.time.LocalDate;
 import java.time.LocalDateTime;
@@ -46,8 +49,6 @@ public class AlarmHandleServiceImpl implements AlarmHandleService {
     @Autowired
     AlarmInfoCache alarmInfoCache;
     @Autowired
-    CurrentDataCache currentDataCache;
-    @Autowired
     GroupNettyClient groupNettyClient;
     @Autowired
     AlarmQuartzService alarmQuartzService;
@@ -107,11 +108,11 @@ public class AlarmHandleServiceImpl implements AlarmHandleService {
         }
     }
 
-//    public static void main(String[] args) throws Exception {
-//        String msg = "20210331094500;Eq4403050002cfb2cd6c7475465397e8738ee9ada861;Pclose,EnergyData,CsLJCWDetaTemp;0.1,0.81,1.2;";
-//        AlarmHandleServiceImpl alarmHandleService = new AlarmHandleServiceImpl();
-//        alarmHandleService.handleIotMsg(msg);
-//    }
+    //    public static void main(String[] args) throws Exception {
+    //        String msg = "20210331094500;Eq4403050002cfb2cd6c7475465397e8738ee9ada861;Pclose,EnergyData,CsLJCWDetaTemp;0.1,0.81,1.2;";
+    //        AlarmHandleServiceImpl alarmHandleService = new AlarmHandleServiceImpl();
+    //        alarmHandleService.handleIotMsg(msg);
+    //    }
 
     /**
      * @description: 处理iot数据, iot数据可能包含一个设备多个信息点的采集值
@@ -131,104 +132,83 @@ public class AlarmHandleServiceImpl implements AlarmHandleService {
         String funcIdSeparator = ",";
         String[] funcIdArray = funcIdStr.split(funcIdSeparator);
         String[] values = valueStr.split(funcIdSeparator);
-        // 更新缓存中的设备信息点当前采集值
+
+        // 拼装报警条件参数
+        HashMap<String, Object> paramMap = new HashMap<>();
+
+        // 拼装报警条件参数
         for (int i = 0; i < funcIdArray.length; i++) {
-            // 如果有对应的报警定义
-            if (alarmInfoCache.hasKey(meterId, funcIdArray[i])) {
-                currentDataCache.putCurrentData(meterId, funcIdArray[i], Double.parseDouble(values[i]));
-            } else {
-                log.info("未获取到对应的报警定义, meterId:{}, funcId:{}", meterId, funcIdArray[i]);
-            }
+            paramMap.put(funcIdArray[i], Double.parseDouble(values[i]));
         }
 
-        // 将一组数据拆分为单条处理
-        for (String funcId : funcIdArray) {
-            if (alarmInfoCache.hasKey(meterId, funcId)) {
-                handleSingleIotData(dataTime, meterId, funcId);
-            } else {
-                log.info("未获取到对应的报警定义, meterId:{}, funcId:{}", meterId, funcId);
-            }
-        }
+        calculateAlarmConditions(dataTime, meterId, paramMap);
     }
 
     /**
-     * @description: 处理单条iot数据
-     * @param: dataTime 采集时间
-     * @param: meterId 设备id
-     * @param: funcId 信息点id
-     * @return: void
-     * @exception:
-     * @author: lixing
-     * @company: Persagy Technology Co.,Ltd
-     * @since: 2021/2/1 4:01 下午
-     * @version: V1.0
+     * 遍历设备的所有报警条件,计算报警的产生和恢复
+     *
+     * @param dataTime 采集日期
+     * @param meterId  报警对象id
+     * @param paramMap 采集数据
+     * @author lixing
+     * @version V1.0 2021/10/22 5:19 下午
      */
-    private void handleSingleIotData(String dataTime, String meterId, String funcId) throws Exception {
-        // 获取和采集值相关的报警定义
-        List<AlarmDefine> alarmDefines = alarmInfoCache.getAlarmDefinitionsByMeterFuncId(meterId, funcId);
-        for (AlarmDefine alarmDefine : alarmDefines) {
-            Condition condition = alarmDefine.getCondition();
-            String defineId = AlarmInfoCache.getAlarmDefineId(alarmDefine);
-            log.info("defineId: [{}]", defineId);
-
-            // 判断报警定义所包含的信息点在缓存中是否都有值
-            List<JSONObject> infoCodes = condition.getInfoCodes();
-            boolean infoCodesFullFill = infoCodes.stream().allMatch(
-                    p -> currentDataCache.hasKey(p.getString("meterId"), p.getString("funcId"))
-            );
-
-            //报警定义的所有信息点都有采集数值,具备判断条件
-            if (infoCodesFullFill) {
-                // 解析触发和恢复条件
-                String trigger = condition.getTrigger();
-                Expression triggerExp = AviatorEvaluator.compile(trigger, true);
-                String end = condition.getEnd();
-                Expression endExp = AviatorEvaluator.compile(end, true);
-
-                // 拼装报警条件参数
-                HashMap<String, Object> paramMap = new HashMap<>();
-                for (JSONObject code : infoCodes) {
-                    paramMap.put(
-                            code.getString("infoCode"),
-                            currentDataCache.getCurrentData(code.getString("meterId"), code.getString("funcId")));
-                }
-
-                // 执行报警条件公式,得到触发和恢复结果
+    private void calculateAlarmConditions(String dataTime, String meterId, HashMap<String, Object> paramMap) throws Exception {
+        // 获取设备的报警条件
+        ObjConditionInfo objConditionInfo = alarmInfoCache.getAlarmConditionsByObjId(meterId);
+        if (objConditionInfo == null || CollectionUtils.isEmpty(objConditionInfo.getConditions())) {
+            log.info("未获取到设备{}的报警条件", meterId);
+            return;
+        }
+        LinkedList<ItemCodeCondition> itemCodeConditions = objConditionInfo.getConditions();
+
+        // 遍历这些条件,将采集值带入条件,判断是否产生报警
+        for (ItemCodeCondition itemCodeCondition : itemCodeConditions) {
+            String conditionId = itemCodeCondition.getConditionId();
+            AlarmCondition alarmCondition = alarmInfoCache.getAlarmCondition(conditionId);
+            // 解析触发和恢复条件
+            String trigger = alarmCondition.getTriggerBackend();
+            Expression triggerExp = AviatorEvaluator.compile(trigger, true);
+            String end = alarmCondition.getEndBackend();
+            Expression endExp = AviatorEvaluator.compile(end, true);
+
+            // 执行报警条件公式,得到触发和恢复结果
+            Boolean triggerResult = null;
+            Boolean endResult = null;
+            try {
+                triggerResult = (Boolean) triggerExp.execute(paramMap);
+                endResult = (Boolean) endExp.execute(paramMap);
+            } catch (Exception e) {
+                log.error("报警条件解析异常");
+                log.error("触发条件:");
+                log.error(trigger);
+                log.error("恢复条件:");
+                log.error(end);
+                log.error("参数:");
+                log.error(paramMap.toString());
+            }
+            log.info("triggerResult:[{}],endResult:[{}]", triggerResult, endResult);
+            if (triggerResult && endResult) {
+                log.error("报警触发条件和报警恢复条件同时满足,请检查,报警定义详情【{}】", alarmCondition);
+            }
 
-                Boolean triggerResult = null;
-                Boolean endResult = null;
-                try {
-                    triggerResult = (Boolean) triggerExp.execute(paramMap);
-                    endResult = (Boolean) endExp.execute(paramMap);
-                } catch (Exception e) {
-                    log.error("报警条件解析异常");
-                    log.error("触发条件:");
-                    log.error(trigger);
-                    log.error("恢复条件:");
-                    log.error(end);
-                    log.error("参数:");
-                    log.error(paramMap.toString());
-                }
-                log.info("triggerResult:[{}],endResult:[{}]", triggerResult, endResult);
-                if (triggerResult && endResult) {
-                    log.error("报警触发条件和报警恢复条件同时满足,请检查,报警定义详情【{}】", alarmDefine);
-                }
-                synchronized (defineId.intern()) {
-                    //报警产生值满足(这里的满足不考虑报警持续时间)
-                    if (triggerResult) {
-                        log.info("满足报警条件");
-                        //报警的时候不考虑报警恢复,因为同时报警和报警恢复是不应该出现的
-                        handleAlarmTriggerData(alarmDefine, dataTime, paramMap);
-                    } else {
-                        log.info("不满足报警条件");
-                        //当前数据正常
-                        handlerNormalData(alarmDefine, dataTime, endResult, paramMap);
-                    }
+            synchronized (conditionId.intern()) {
+                AlarmDefine alarmDefine = AlarmDefine.convert2AlarmDefine(itemCodeCondition.getItemCode(),
+                        alarmCondition, meterId, objConditionInfo.getProjectId());
+                //报警产生值满足(这里的满足不考虑报警持续时间)
+                if (triggerResult) {
+                    log.info("满足报警条件");
+                    //报警的时候不考虑报警恢复,因为同时报警和报警恢复是不应该出现的
+                    handleAlarmTriggerData(alarmDefine, dataTime, paramMap);
+                } else {
+                    log.info("不满足报警条件");
+                    //当前数据正常
+                    handlerNormalData(alarmDefine, dataTime, endResult, paramMap);
                 }
-            } else {
-                log.warn("部分信息点没有数值");
             }
         }
+
+
     }
 
     /**
@@ -330,23 +310,23 @@ public class AlarmHandleServiceImpl implements AlarmHandleService {
      * @since: 2021/1/8 上午11:05
      * @version: V1.0
      */
-    private AlarmDefineState getAlarmDefineStateFromCacheOrDb(String defineId) {
-        AlarmDefineState alarmDefineState = alarmInfoCache.getAlarmDefineState(defineId);
-        if (Objects.isNull(alarmDefineState)) {
+    private AlarmConditionState getAlarmDefineStateFromCacheOrDb(String defineId) {
+        AlarmConditionState alarmConditionState = alarmInfoCache.getAlarmDefineState(defineId);
+        if (Objects.isNull(alarmConditionState)) {
             //默认正常报警状态
-            alarmDefineState = new AlarmDefineState(defineId);
+            alarmConditionState = new AlarmConditionState(defineId);
             Optional<ZktAlarmRecordDO> recordOptional = alarmRecordRepository.findById(defineId);
             if (recordOptional.isPresent()) {
                 ZktAlarmRecordDO alarmRecordDO = recordOptional.get();
                 //数据库报警状态:1-未处理
                 if ("1".equals(alarmRecordDO.getState())) {
-                    alarmDefineState.setState(AlarmDefineState.State.NOT_DEAL.getType());
-                    alarmDefineState.setAlarmStartTime(alarmRecordDO.getAlarmTime());
+                    alarmConditionState.setState(AlarmConditionState.State.NOT_DEAL.getType());
+                    alarmConditionState.setAlarmStartTime(alarmRecordDO.getAlarmTime());
                 }
             }
         }
-        log.info("alarmDefineState: [{}], ( 0-正常 1-报警)", alarmDefineState.getState());
-        return alarmDefineState;
+        log.info("alarmDefineState: [{}], ( 0-正常 1-报警)", alarmConditionState.getState());
+        return alarmConditionState;
     }
 
     /**
@@ -366,23 +346,23 @@ public class AlarmHandleServiceImpl implements AlarmHandleService {
             AlarmDefine alarmDefine, String dataTime,
             Boolean endResult, HashMap<String, Object> paramMap) throws InterruptedException {
         String defineId = AlarmInfoCache.getAlarmDefineId(alarmDefine);
-        AlarmDefineState alarmDefineState = getAlarmDefineStateFromCacheOrDb(defineId);
+        AlarmConditionState alarmConditionState = getAlarmDefineStateFromCacheOrDb(defineId);
 
         Condition condition = alarmDefine.getCondition();
         //当前数据正常,报警状态为正常:清空之前的报警计时,重置回默认状态
-        if (AlarmDefineState.State.NORMAL.getType().equals(alarmDefineState.getState())) {
-            alarmDefineState = new AlarmDefineState(defineId);
-        } else if (AlarmDefineState.State.NOT_DEAL.getType().equals(alarmDefineState.getState())) {
+        if (AlarmConditionState.State.NORMAL.getType().equals(alarmConditionState.getState())) {
+            alarmConditionState = new AlarmConditionState(defineId);
+        } else if (AlarmConditionState.State.NOT_DEAL.getType().equals(alarmConditionState.getState())) {
             // 报警恢复条件不满足,不处理
             if (!endResult) {
                 return;
             }
             /* 判断是否满足报警恢复持续时间 */
-            String alarmSuspendStartTime = alarmDefineState.getAlarmSuspendStartTime();
+            String alarmSuspendStartTime = alarmConditionState.getAlarmSuspendStartTime();
             if (StringUtil.isEmpty(alarmSuspendStartTime)) {
                 alarmSuspendStartTime = dataTime;
                 //设置开始恢复时间
-                alarmDefineState.setAlarmSuspendStartTime(alarmSuspendStartTime);
+                alarmConditionState.setAlarmSuspendStartTime(alarmSuspendStartTime);
             }
             // 计算报警恢复持续时间
             long alarmSuspendLastTime = DateUtils.betweenTwoTimeSecond(alarmSuspendStartTime, dataTime);
@@ -415,10 +395,10 @@ public class AlarmHandleServiceImpl implements AlarmHandleService {
             // 取消过期任务
             cancelRelatedExpireJob(alarmId);
             //报警恢复,报警状态重置回默认
-            alarmDefineState.reset();
+            alarmConditionState.reset();
         }
         // 更新报警定义缓存
-        alarmInfoCache.setAlarmState(defineId, alarmDefineState);
+        alarmInfoCache.setAlarmState(defineId, alarmConditionState);
     }
 
     /**
@@ -584,7 +564,7 @@ public class AlarmHandleServiceImpl implements AlarmHandleService {
             HashMap<String, Object> paramMap) throws Exception {
         // 根据defineId获取报警定义状态
         String defineId = AlarmInfoCache.getAlarmDefineId(alarmDefine);
-        AlarmDefineState alarmDefineState = getAlarmDefineStateFromCacheOrDb(defineId);
+        AlarmConditionState alarmConditionState = getAlarmDefineStateFromCacheOrDb(defineId);
 
         Condition condition = alarmDefine.getCondition();
         // 判断报警是否在有效期内
@@ -592,9 +572,9 @@ public class AlarmHandleServiceImpl implements AlarmHandleService {
 
         if (inEffectTime) {
             // 已经产生报警
-            if (AlarmDefineState.State.NOT_DEAL.getType().equals(alarmDefineState.getState())) {
+            if (AlarmConditionState.State.NOT_DEAL.getType().equals(alarmConditionState.getState())) {
                 // 获取报警持续时间
-                String alarmStartTime = alarmDefineState.getAlarmStartTime();
+                String alarmStartTime = alarmConditionState.getAlarmStartTime();
                 long lastTime = DateUtils.betweenTwoTimeSecond(alarmStartTime, dataTime);
                 String alarmId = alarmRecordRepository.findById(defineId).orElse(new ZktAlarmRecordDO()).getAlarmId();
                 if (StringUtils.isNotBlank(alarmId)) {
@@ -604,14 +584,14 @@ public class AlarmHandleServiceImpl implements AlarmHandleService {
                 }
             }
             //之前是是正常状态
-            if (AlarmDefineState.State.NORMAL.getType().equals(alarmDefineState.getState())) {
+            if (AlarmConditionState.State.NORMAL.getType().equals(alarmConditionState.getState())) {
                 // 报警持续时间
                 long alarmLastTime = 0;
-                if (StringUtil.isNotEmpty(alarmDefineState.getAlarmStartTime())) {
-                    alarmLastTime = DateUtils.betweenTwoTimeSecond(alarmDefineState.getAlarmStartTime(), dataTime);
+                if (StringUtil.isNotEmpty(alarmConditionState.getAlarmStartTime())) {
+                    alarmLastTime = DateUtils.betweenTwoTimeSecond(alarmConditionState.getAlarmStartTime(), dataTime);
                 } else {
                     //设置开始报警时间
-                    alarmDefineState.setAlarmStartTime(dataTime);
+                    alarmConditionState.setAlarmStartTime(dataTime);
                 }
 
                 // 获取报警过期时间
@@ -627,7 +607,7 @@ public class AlarmHandleServiceImpl implements AlarmHandleService {
                     // 边缘端保存报警信息
                     saveZktAlarmRecordWhenAlarmStart(alarmId, alarmDefine, dataTime);
                     // 报警定义状态更新为未处理
-                    alarmDefineState.setState(AlarmDefineState.State.NOT_DEAL.getType());
+                    alarmConditionState.setState(AlarmConditionState.State.NOT_DEAL.getType());
                     // 发送创建报警记录的消息
                     sendCreateAlarmRecordMessage(alarmId, alarmDefine, dataTime, paramMap,
                             DateUtils.localDateTime2Date(expireDateTime));
@@ -637,7 +617,7 @@ public class AlarmHandleServiceImpl implements AlarmHandleService {
                         //过期时间
                         log.info("产生一条定时过期报警消息, 过期时间为:{}", expireDateTime);
                         // 创建一条过期任务
-                        createExpireJob(alarmId, alarmDefine, alarmDefineState, expireDateTime);
+                        createExpireJob(alarmId, alarmDefine, alarmConditionState, expireDateTime);
                     }
                 }
             }
@@ -645,9 +625,9 @@ public class AlarmHandleServiceImpl implements AlarmHandleService {
             // 其他条件全部改成默认值(不报警,不过期,报警开始时间和结束时间为空)
             log.info("[{}]不在生效时间,重置报警状态", dataTime);
             log.info("生效时间为:[{}]", condition.getEffectTime());
-            alarmDefineState.reset();
+            alarmConditionState.reset();
         }
-        alarmInfoCache.setAlarmState(defineId, alarmDefineState);
+        alarmInfoCache.setAlarmState(defineId, alarmConditionState);
     }
 
     /**
@@ -690,10 +670,10 @@ public class AlarmHandleServiceImpl implements AlarmHandleService {
      * @since: 2021/1/13 下午3:39
      * @version: V1.0
      */
-    private void createExpireJob(String alarmId, AlarmDefine alarmDefine, AlarmDefineState alarmDefineState, LocalDateTime expireDateTime) throws InterruptedException {
+    private void createExpireJob(String alarmId, AlarmDefine alarmDefine, AlarmConditionState alarmConditionState, LocalDateTime expireDateTime) throws InterruptedException {
         String defineId = AlarmInfoCache.getAlarmDefineId(alarmDefine);
         ZktAlarmRecordDO alarmRecordDO = ZktAlarmRecordDO.builder()
-                .alarmTime(alarmDefineState.getAlarmStartTime())
+                .alarmTime(alarmConditionState.getAlarmStartTime())
                 .effectEndTime(DateUtils.format(expireDateTime))
                 .definitionId(defineId)
                 .itemCode(alarmDefine.getItemCode())

+ 0 - 1
src/main/java/com/persagy/utils/LockUtil.java

@@ -1,6 +1,5 @@
 package com.persagy.utils;
 
-import cn.hutool.core.date.DateUtil;
 import lombok.extern.slf4j.Slf4j;
 
 import java.util.concurrent.ExecutorService;

+ 2 - 2
src/main/resources/application.yml

@@ -39,12 +39,12 @@ spring:
 group:
   code: WD   #标识哪个集团 比如万达使用WD, 华润使用HR
   alarm:
-    host: 192.168.17.57    #netty IP
+    host: localhost    #netty IP
     port: 9986          #netty 端口9986
 terminal:  #边缘端IOT采集程序地址
   alarm:  # 拼接后的地址为ws://host:port/suffix
     compress: false    #采用的是压缩方式还是不压缩方式  true-压缩 false-不压缩
-    host: 192.168.17.57
+    host: localhost
     port: 8080
     suffix: websocket/iot   #websocker后缀
 project:

+ 10 - 16
src/test/java/com/persagy/zktprojectalarm/Mytest.java

@@ -1,22 +1,16 @@
 package com.persagy.zktprojectalarm;
 
-import com.alibaba.fastjson.JSONObject;
 import com.google.common.base.CaseFormat;
 import com.persagy.ZktProjectAlarmApplication;
 import com.persagy.cache.AlarmInfoCache;
-import com.persagy.entity.AlarmDefine;
-import com.persagy.service.AlarmDefineService;
 import com.persagy.utils.LockUtil;
 
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.CountDownLatch;
 
 
@@ -37,16 +31,16 @@ public class Mytest {
 
     @Test
     public void test2 () throws Exception {
-        alarmDefineService.listAllAlarmDefine(new ArrayList<>());
-        ConcurrentHashMap<String, AlarmDefine> alarmDefineMap = alarmInfoCache.getAlarmDefineMap();
-        for (Map.Entry entry :alarmDefineMap.entrySet()) {
-            System.out.println("[key]:"+entry.getKey()+"[value]"+entry.getValue());
-        }
-        System.out.println("--------------------");
-        ConcurrentHashMap<String, List<AlarmDefine>> infoAlarmMap = alarmInfoCache.getInfoAlarmMap();
-        for (Map.Entry entry :infoAlarmMap.entrySet()) {
-            System.out.println("[key]:"+entry.getKey()+"[value]"+ JSONObject.toJSONString(entry.getValue()));
-        }
+//        alarmDefineService.listAllAlarmDefine(new ArrayList<>());
+//        ConcurrentHashMap<String, AlarmDefine> alarmDefineMap = alarmInfoCache.getAlarmDefineMap();
+//        for (Map.Entry entry :alarmDefineMap.entrySet()) {
+//            System.out.println("[key]:"+entry.getKey()+"[value]"+entry.getValue());
+//        }
+//        System.out.println("--------------------");
+//        ConcurrentHashMap<String, List<AlarmDefine>> infoAlarmMap = alarmInfoCache.getInfoAlarmMap();
+//        for (Map.Entry entry :infoAlarmMap.entrySet()) {
+//            System.out.println("[key]:"+entry.getKey()+"[value]"+ JSONObject.toJSONString(entry.getValue()));
+//        }
 
         new CountDownLatch(1).await();
     }