Просмотр исходного кода

告警:离线告警阶段提交

yf_zn 11 месяцев назад
Родитель
Сommit
ada245a414

+ 68 - 100
src/main/java/com/yunfeiyun/agmp/iots/task/IotStatusService.java

@@ -10,6 +10,7 @@ import com.yunfeiyun.agmp.iot.common.model.device.IotDeviceStatusResVo;
 import com.yunfeiyun.agmp.iots.core.manager.ConnectionManager;
 import com.yunfeiyun.agmp.iots.service.IIotDeviceService;
 import com.yunfeiyun.agmp.iots.service.IIotDeviceconfigService;
+import com.yunfeiyun.agmp.iots.warn.service.WarnService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Scheduled;
@@ -27,8 +28,7 @@ import java.util.*;
 @Slf4j
 public class IotStatusService {
     /**
-     * 用于存放检测的设备类型
-     * 稳定后,所有设备都基于devcieConfig 更新最新数据,进而统一监控
+     * 用于存放检测的设备类型,saas需要检测所有的,看似无用,保留它按类型检查搜索设备,集中处理
      */
     private Set validateDeviceType = new HashSet();
 
@@ -37,78 +37,61 @@ public class IotStatusService {
 
     @Autowired
     IIotDeviceconfigService iIotDeviceconfigService;
+
     @Resource
     private ConnectionManager connectionManager;
 
+    @Autowired
+    private WarnService warnService;
+
     @PostConstruct
     void init() {
-        // 目前基于已经实现将最新数据放到DeviceConfig的设备,没有的将进行实现
-//        validateDeviceType.add(IotDeviceDictConst.TYPE_YF_CBD);// 云飞测报灯
-//        validateDeviceType.add(IotDeviceDictConst.TYPE_YF_BZY);// 云飞孢子仪
-//        validateDeviceType.add(IotDeviceDictConst.TYPE_YF_SCD);// 云飞杀虫灯
-//        validateDeviceType.add(IotDeviceDictConst.TYPE_YF_SQZ);// 云飞墒情站
-//        validateDeviceType.add(IotDeviceDictConst.TYPE_YF_QXZ);// 云飞环境监测
-//        validateDeviceType.add(IotDeviceDictConst.TYPE_XPH_YF_GSSQ);// 新浦会管式墒情
-//        validateDeviceType.add(IotDeviceDictConst.TYPE_XPH_YF_SQZ);// 新浦会云飞墒情站
-//        validateDeviceType.add(IotDeviceDictConst.TYPE_ADZN_GSSQ);// 爱迪智农管式墒情
-//        validateDeviceType.add(IotDeviceDictConst.TYPE_YF_XYCB_2);// 性诱测报2.0
-//        validateDeviceType.add(IotDeviceDictConst.TYPE_YF_XYCB_III);// 云飞-性诱测报灯III
-//        validateDeviceType.add(IotDeviceDictConst.TYPE_ZJSF_XYCB);// 中捷四方性诱
-//        validateDeviceType.add(IotDeviceDictConst.TYPE_YF_XCT);// 云飞吸虫塔
-
-
-        //validateDeviceType.add(IotDeviceDictConst.TYPE_ZHAO_HE_SFJ);// 赵赫水肥机
-
-        //validateDeviceType.add(IotDeviceDictConst.TYPE_XPH_LDSW_JC);// 新浦会雷达水位监测
-        //validateDeviceType.add(IotDeviceDictConst.TYPE_XPH_SZZX_JC);// 新浦会水质在线监测
-        //validateDeviceType.add(IotDeviceDictConst.TYPE_XPH_WSHJ_JC);// 新浦会温室环境监测
-
-        //validateDeviceType.add(IotDeviceDictConst.TYPE_YF_GXZW);// 根系作物
-        //validateDeviceType.add(IotDeviceDictConst.TYPE_XPH_TRSH_CL);// 新普惠土壤水势
-        //validateDeviceType.add(IotDeviceDictConst.TYPE_XPH_WSKZ);// 新浦会温室环境控制
-        //validateDeviceType.add(IotDeviceDictConst.TYPE_HPF_WSMJ_ZNKG);// 海普发智能温室控制
-
-        //validateDeviceType.add(IotDeviceDictConst.TYPE_BY_SFJ);// 云飞水肥机
-        //validateDeviceType.add(IotDeviceDictConst.TYPE_HT_SFJ);// 宏泰水肥机
-
         String[] deviceTypes = {
+                IotDeviceDictConst.TYPE_DAHUA_DEVICE,
+                IotDeviceDictConst.TYPE_HIK_OPEN_DEVICE,
+                IotDeviceDictConst.TYPE_BIG_DATA_MONITOR_DEVICE,
+                IotDeviceDictConst.TYPE_OB_NTSWJ,
                 IotDeviceDictConst.TYPE_YF_CBD,
-                IotDeviceDictConst.TYPE_YF_BZY,
                 IotDeviceDictConst.TYPE_YF_SCD,
                 IotDeviceDictConst.TYPE_YF_SQZ,
                 IotDeviceDictConst.TYPE_YF_QXZ,
-                IotDeviceDictConst.TYPE_XPH_YF_GSSQ,
-                IotDeviceDictConst.TYPE_XPH_YF_SQZ,
-                IotDeviceDictConst.TYPE_ADZN_GSSQ,
-                IotDeviceDictConst.TYPE_YF_XYCB_2,
-                IotDeviceDictConst.TYPE_YF_XYCB_III,
-                IotDeviceDictConst.TYPE_ZJSF_XYCB,
-                IotDeviceDictConst.TYPE_YF_XCT,
+                IotDeviceDictConst.TYPE_YF_GKCBD,
+                IotDeviceDictConst.TYPE_YF_SDCBD,
+                IotDeviceDictConst.TYPE_YF_FXSSCD,
+                IotDeviceDictConst.TYPE_YF_JGFXSSCD,
+                IotDeviceDictConst.TYPE_XPH_YF_QXZ,
+                IotDeviceDictConst.TYPE_XPH_GP_QXZ,
                 IotDeviceDictConst.TYPE_HS_YBQ_DWB,
                 IotDeviceDictConst.TYPE_HS_YBQ_CMB,
                 IotDeviceDictConst.TYPE_HS_YBQ_DBB,
                 IotDeviceDictConst.TYPE_HS_YBQ_TXB,
-                IotDeviceDictConst.TYPE_HS_YBQ_BFB
-        };
+                IotDeviceDictConst.TYPE_HS_YBQ_BFB,
+                IotDeviceDictConst.TYPE_ADZN_GSSQ,
+                IotDeviceDictConst.TYPE_YF_BZY,
+                IotDeviceDictConst.TYPE_YF_XYCB_III,
+                IotDeviceDictConst.TYPE_DAHUA_YUNRUI_DEVICE,
+                IotDeviceDictConst.TYPE_XPH_YF_SQZ,
+                IotDeviceDictConst.TYPE_XPH_YF_GSSQ,
+                IotDeviceDictConst.TYPE_ZJSF_XYCB,
+                IotDeviceDictConst.TYPE_YF_XYCB_2,
+                IotDeviceDictConst.TYPE_YF_XCT,
 
+        };
         Collections.addAll(validateDeviceType, deviceTypes);
-
-
         try {
             validateStatusByDevType();
         } catch (Exception e) {
             log.error("【设备检测】异常", e);
         }
-
     }
 
     /**
      * 定期根据类型查设备最新设备数据,是否长时间不上报。
      */
-//    @Scheduled(cron = "30 * * * * ?")
+    // @Scheduled(cron = "30 * * * * ?")
     @Scheduled(cron = "0 0/20 * * * ? ")
     public void validateStatusByDevType() {
-        if(!connectionManager.initCompleted()){
+        if (!connectionManager.initCompleted()) {
             return;
         }
         Iterator<String> iterator = validateDeviceType.iterator();
@@ -127,66 +110,25 @@ public class IotStatusService {
         log.info("【设备检测开始 类型:{}】#########################", type);
         Map param = new HashMap();
         param.put("type", type);
-        // 查出来待检查的设备。根据类型
-        if(Objects.equals(type, IotDeviceDictConst.TYPE_YF_XCT)){
-            log.info("【吸虫塔检测");
-        }
         List<IotDeviceStatusResVo> iotDeviceStatusResVos = iIotDeviceService.selectAllDeviceConfigStatus(param);
         log.info("【设备检测】【设备类型{} 】设备:{} 个", type, iotDeviceStatusResVos.size());
         for (IotDeviceStatusResVo iotDeviceStatusResVo : iotDeviceStatusResVos) {
             try {
                 // 获取设备类型id,存在的在进行检查,因为有些设备不是基于device config 上报
                 String devtypeBid = iotDeviceStatusResVo.getDevtypeBid();
-                if (validateDeviceType.contains(devtypeBid)) {
-                    String devStatus = iotDeviceStatusResVo.getDevStatus();
-                    // 获取最新上报时间
-                    // 如果没有更新的上报时间,使用创建时间
-                    //      因为刚创建的离线设备,不会上报激活设备,导致设备一直处于待激活状态
-                    // 如果没有更新的上报时间,则跳过不处理,正常他本身就是离线
-                    String updateTime = iotDeviceStatusResVo.getDevUpdateddate();
-                    if(StringUtils.isEmpty(updateTime) && IotDeviceStatusTypeEnum.WAIT_ACTIVATE.getCode().equals(devStatus)){
-                        updateTime = iotDeviceStatusResVo.getDevCreateddate();
-                    }
-
-                    if (StringUtils.isEmpty(updateTime)) {
-                        continue;
-                    }
-                    String devCode = iotDeviceStatusResVo.getDevCode();
-                    String devName = iotDeviceStatusResVo.getDevName();
-                    String devBid = iotDeviceStatusResVo.getDevBid();
-
-                    // 检查时间上报间隔是否异常,60分钟没有,则异常
-                    if (!validateTime(updateTime, 90)) {
-                        log.info("【设备检测】【正常】:设备:{} {} 上次时间:{}", iotDeviceStatusResVo.getDevName(), iotDeviceStatusResVo.getDevCode(), updateTime);
-                        continue;
-                    }
-                    // 1. 当前在线的进行检查;
-                    if (!IotDeviceStatusTypeEnum.OFFLINE.getCode().equals(devStatus)) {
-                        // 更新状态
-                        IotDevice iotDevice = new IotDevice();
-                        iotDevice.setDevCode(iotDeviceStatusResVo.getDevCode());
-                        iotDevice.setDevBid(devBid);
-                        iotDevice.setDevStatus(IotDeviceStatusTypeEnum.OFFLINE.getCode());
-                        iotDevice.setDevOfflinedate(DateUtils.dateTimeNow());
-                        iotDevice.setDevModifieddate(DateUtils.dateTimeNow());
-                        iotDevice.setDevtypeBid(iotDeviceStatusResVo.getDevtypeBid());
-                        iotDevice.setDevconnBid(iotDeviceStatusResVo.getDevconnBid());
-
-                        if(IotDeviceStatusTypeEnum.WAIT_ACTIVATE.getCode().equals(devStatus)){
-                            iotDevice.setDevUpdateddate(iotDeviceStatusResVo.getDevCreateddate());
-                        }
-                        iIotDeviceService.updateIotDevice(iotDevice);
-                        log.info("【设备检测】【设备状态异常更新-设备类型{} 】设备标识:{} 设备编号 {} 设备名称 {} 异常状态 {}", type, devBid, devCode, devName, iotDeviceStatusResVo.getDevStatus());
-                        reCreateDeviceTopic(iotDevice);
-                    }else{
-                        log.info("【设备检测】【设备状态异常更新-不处理-设备类型{} 】设备标识:{} 设备编号 {} 设备名称 {} 异常状态 {}", type, devBid, devCode, devName, iotDeviceStatusResVo.getDevStatus());
-
-                        // 更新状态
-//                        IotDevice iotDevice = new IotDevice();
-//                        iotDevice.setDevBid(devBid);
-//                        iotDevice.setDevStatus(IotDeviceStatusTypeEnum.ONLINE.getCode());
-//                        iIotDeviceService.updateIotDevice(iotDevice);
-                    }
+                if (!validateDeviceType.contains(devtypeBid)) {
+                    continue;
+                }
+                // 不管状态,只要超过时间,就将他改为离线
+                // 1. 本身是离线,一个周期检查后还是离线,告警
+                // 2. 本身是在线,发现上报数据没上报,告警
+                // 3. 本身处于待激活,没有更新时间,改为离线,告警
+                String updateTime = iotDeviceStatusResVo.getDevUpdateddate();
+                log.info("【设备检测】【异常】:设备:{} {} 上次时间:{}", iotDeviceStatusResVo.getDevName(), iotDeviceStatusResVo.getDevCode(), updateTime);
+                // updateTime时间为空,或者 检查时间上报间隔超过60min
+                if (StringUtils.isEmpty(updateTime) || validateTime(updateTime, 60)) {
+                    //处理离线的设备
+                    handleOfflineDevice(iotDeviceStatusResVo);
                 }
             } catch (Exception e) {
                 log.info("【设备检测】【程序异常】:设备:{} {} {} {}", iotDeviceStatusResVo.getDevName(), iotDeviceStatusResVo.getDevCode(), iotDeviceStatusResVo, e);
@@ -196,6 +138,32 @@ public class IotStatusService {
     }
 
     /**
+     * 集中处理离线设备
+     *
+     * @param iotDeviceStatusResVo
+     */
+    void handleOfflineDevice(IotDeviceStatusResVo iotDeviceStatusResVo) {
+        String devCode = iotDeviceStatusResVo.getDevCode();
+        String devName = iotDeviceStatusResVo.getDevName();
+        String devBid = iotDeviceStatusResVo.getDevBid();
+        // 更新状态
+        IotDevice iotDevice = new IotDevice();
+        iotDevice.setDevCode(iotDeviceStatusResVo.getDevCode());
+        iotDevice.setDevBid(iotDeviceStatusResVo.getDevBid());
+        iotDevice.setDevStatus(IotDeviceStatusTypeEnum.OFFLINE.getCode());
+        iotDevice.setDevOfflinedate(DateUtils.dateTimeNow());
+        iotDevice.setDevModifieddate(DateUtils.dateTimeNow());
+        iotDevice.setDevtypeBid(iotDeviceStatusResVo.getDevtypeBid());
+        iotDevice.setDevconnBid(iotDeviceStatusResVo.getDevconnBid());
+        //编辑离线
+        iIotDeviceService.updateIotDevice(iotDevice);
+        //发送预警
+        warnService.processWarningOfflineDataSyn(iotDevice);
+        log.info("【设备检测】【设备状态异常更新-设备类型{} 】设备标识:{} 设备编号 {} 设备名称 {} 异常状态 {}", iotDeviceStatusResVo.getDevtypeBid(), devBid, devCode, devName, iotDeviceStatusResVo.getDevStatus());
+        reCreateDeviceTopic(iotDevice);
+    }
+
+    /**
      * 重新订阅和构建topic
      *
      * @param iotDevice

+ 3 - 0
src/main/java/com/yunfeiyun/agmp/iots/warn/mapper/IotWarnBussinessMapper.java

@@ -1,5 +1,6 @@
 package com.yunfeiyun.agmp.iots.warn.mapper;
 
+import com.yunfeiyun.agmp.iot.common.domain.IotWarnconfig;
 import com.yunfeiyun.agmp.iot.common.domain.IotWarncount;
 import com.yunfeiyun.agmp.iot.common.domain.IotWarnlog;
 import com.yunfeiyun.agmp.iots.warn.model.WarnConfigInfo;
@@ -50,4 +51,6 @@ public interface IotWarnBussinessMapper {
     List<WarnConfigInfo> selectIotWarnConfigInfoList(WarnConfigInfo warnConfigInfo);
 
     int resetReCountByDevIdAndConfigId(@Param("devBid") String devBid, @Param("wcBid") String configId);
+
+    IotWarnconfig selectIotWarnOfflineConfigInfo(@Param("tid") String tid);
 }

+ 7 - 0
src/main/java/com/yunfeiyun/agmp/iots/warn/model/WarnResult.java

@@ -49,11 +49,18 @@ public class WarnResult extends IotBaseEntity {
      */
     private IotWarnconfig config;
 
+    /**
+     * 是不是离线指标
+     */
+    private boolean isOffline;
+
     public WarnResult(boolean isTriggered, String message) {
         this.isTriggered = isTriggered;
         this.message = message;
+        this.isOffline = false;
     }
 
     public WarnResult() {
+        this.isOffline = false;
     }
 }

+ 7 - 1
src/main/java/com/yunfeiyun/agmp/iots/warn/service/IotWarnBussinessService.java

@@ -4,6 +4,7 @@ import com.yunfeiyun.agmp.common.enums.RedisCacheKey;
 import com.yunfeiyun.agmp.common.framework.manager.RedisCacheManager;
 import com.yunfeiyun.agmp.common.utils.DateUtils;
 import com.yunfeiyun.agmp.common.utils.uuid.IdUtils;
+import com.yunfeiyun.agmp.iot.common.domain.IotWarnconfig;
 import com.yunfeiyun.agmp.iot.common.domain.IotWarncount;
 import com.yunfeiyun.agmp.iot.common.domain.IotWarnlog;
 import com.yunfeiyun.agmp.iots.warn.mapper.IotWarnBussinessMapper;
@@ -105,12 +106,17 @@ public class IotWarnBussinessService {
         return result;
     }
 
-    List<WarnConfigInfo> selectIotWarnConfigInfoList(WarnConfigInfo warnConfigInfo) {
+    public List<WarnConfigInfo> selectIotWarnConfigInfoList(WarnConfigInfo warnConfigInfo) {
         log.info("查询预警配置信息列表");
         List<WarnConfigInfo> list = iotWarncountMapper.selectIotWarnConfigInfoList(warnConfigInfo);
         log.info("查询到 {} 条预警配置信息", list.size());
         return list;
     }
+    public IotWarnconfig selectIotWarnOfflineConfigInfo(String tid) {
+        log.info("查询预警配置信息列表");
+        IotWarnconfig list = iotWarncountMapper.selectIotWarnOfflineConfigInfo(tid);
+        return list;
+    }
 
     Map<String, List<WarnConfigInfo>> selectIotWarnConfigInfoMap(WarnConfigInfo warnConfigInfo) {
         log.info("构建预警配置信息映射");

+ 8 - 2
src/main/java/com/yunfeiyun/agmp/iots/warn/service/ReCountService.java

@@ -29,9 +29,15 @@ public class ReCountService {
     public void handlerMessage(WarnResult warnResult) {
         // 注意必要字段必须传过来
         validateMessageParam(warnResult);
-
         String messageId = warnResult.getMessageId();
         log.info("【设备预警】消息标识{}:处理数据:{}", messageId, warnResult);
+
+        // 离线的只用直接入库即可
+        if (warnResult.isTriggered() && warnResult.isOffline()) {
+            log.info("【设备预警】消息标识{}:当前设备ID:{},离线告警", messageId, warnResult.getDevId(), warnResult.getConfigId(), warnResult);
+            iotWarnBussinessService.insertWarnRecord(buildWarnMessage(messageId, warnResult));
+            return;
+        }
         // 触发了预警,进行校验处理
         if (warnResult.isTriggered()) {
             Long reCount = iotWarnBussinessService.selectIotWarnCountByDevAndConfig(warnResult.getDevId(), warnResult.getConfigId());
@@ -41,7 +47,7 @@ public class ReCountService {
             if (thisReCount + 1 > targetReCount) {
                 log.info("【设备预警】消息标识{}:达到或超过阈值, 不再增加重复次数,直接生成预警记录", messageId);
                 iotWarnBussinessService.insertWarnRecord(buildWarnMessage(messageId, warnResult));
-            }else {
+            } else {
                 log.info("【设备预警】消息标识{}:未达阈值, 增加重复次数", messageId);
                 iotWarnBussinessService.incrementReCount(reCount, warnResult);
             }

+ 102 - 50
src/main/java/com/yunfeiyun/agmp/iots/warn/service/WarnService.java

@@ -1,8 +1,10 @@
 package com.yunfeiyun.agmp.iots.warn.service;
 
+import com.alibaba.fastjson2.JSON;
 import com.alibaba.fastjson2.JSONArray;
 import com.alibaba.fastjson2.JSONObject;
 import com.yunfeiyun.agmp.common.utils.StringUtils;
+import com.yunfeiyun.agmp.iot.common.constant.IotEnumOnlineStatus;
 import com.yunfeiyun.agmp.iot.common.constant.device.ElementFormatUtil;
 import com.yunfeiyun.agmp.iot.common.constant.devicetype.IotDeviceDictEnum;
 import com.yunfeiyun.agmp.iot.common.constant.devicetype.IotDeviceTypeLv1Enum;
@@ -47,25 +49,67 @@ public class WarnService {
     @Autowired
     private IIotDevicefactorService iotDevicefactorService;
 
-    private Map<String, IotDevicefactor> getDevicefactorMap(String devBid){
-        IotDevicefactor param = new IotDevicefactor();
-        param.setDevBid(devBid);
-        List<IotDevicefactor> factorList = iotDevicefactorService.selectIotDevicefactorList(param);
-        Map<String, IotDevicefactor> factorMap = new HashMap<>();
-        for(IotDevicefactor factor : factorList){
-            String dfCode = factor.getDfCode();
-            String dfAddress = factor.getDfAddress();
-            String key = dfAddress + dfCode;
-            factorMap.put(key, factor);
-        }
-        return factorMap;
+
+    /**
+     * 统一处理上报数据
+     *
+     * @param data 上报的数据对象
+     *             param ext   上报的原始数据
+     */
+    public void processWarningOfflineData(IotDevice iotDevice, JSONObject data) {
+        //转异步处理
+        processWarningReportDataSyn(iotDevice, data);
+    }
+
+    /**
+     * 处理离线数据:针对主动上报的的离线消息
+     *
+     * @param iotDevice
+     * @param data
+     */
+    public void processWarningOfflineDataSyn(IotDevice iotDevice, JSONObject data) {
+        CompletableFuture.runAsync(() -> {
+            // 获取该设备有哪些告警配置
+            IotWarnconfig warnConfigInfo = iotWarnBussinessService.selectIotWarnOfflineConfigInfo(iotDevice.getTid());
+            //存在离线配置,且开启
+            if (warnConfigInfo != null && "0".equals(warnConfigInfo.getWcStatus())) {
+                //离线
+                if (IotEnumOnlineStatus.OFFLINE.getStatus().equals(iotDevice.getDevStatus())) {
+                    WarnResult warnResult = new WarnResult();
+                    warnResult.setMessageId(warnResult.getUUId());
+                    warnResult.setDevId(iotDevice.getDevBid());
+                    warnResult.setTid(iotDevice.getTid());
+                    warnResult.setConfigId(warnConfigInfo.getWcBid());
+                    warnResult.setReportData(data.toJSONString());
+                    warnResult.setTargetReCount(warnConfigInfo.getWcRepeatnum());
+                    warnResult.setDevtypeBid(iotDevice.getDevtypeBid());
+                    warnResult.setConfig(warnConfigInfo);
+                    warnResult.setOffline(true);
+                    warnResult.setTriggered(true);
+                    warnResult.setMessage(WarnMessageBuilderUtil.buildWarningOfflineMessage(iotDevice.getDevtypeBid(), iotDevice.getDevCode(), iotDevice.getDevName()));
+                    handleWarnRecord(warnResult);
+                }
+            } else {
+                log.error("[设备告警] tid{},没有离线告警配置或者已经关闭:{}", iotDevice.getTid(), warnConfigInfo);
+            }
+
+        }, threadPoolTaskExecutor);
+    }
+
+    /**
+     * 处理离线数据:针对定时检查的离线
+     *
+     * @param iotDevice
+     */
+    public void processWarningOfflineDataSyn(IotDevice iotDevice) {
+        processWarningOfflineDataSyn(iotDevice, JSONObject.from(iotDevice));
     }
 
     /**
      * 统一处理上报数据
      *
-     * @param data  上报的数据对象
-     * param ext   上报的原始数据
+     * @param data 上报的数据对象
+     *             param ext   上报的原始数据
      */
     public void processWarningReportData(IotDevice iotDevice, JSONObject data) {
         //转异步处理
@@ -76,12 +120,12 @@ public class WarnService {
     /**
      * 统一处理上报数据:异步处理
      *
-     * @param data  上报的数据对象
+     * @param data 上报的数据对象
      */
     private void processWarningReportDataSyn(IotDevice iotDevice, JSONObject data) {
         String devBid = iotDevice.getDevBid();
         String devtypeBid = iotDevice.getDevtypeBid();
-        String devClass =  IotDeviceDictEnum.getLv1CodeByCode(devtypeBid);
+        String devClass = IotDeviceDictEnum.getLv1CodeByCode(devtypeBid);
         IotDeviceTypeLv1Enum iotDeviceTypeLv1Enum = IotDeviceTypeLv1Enum.findEnumByCode(devClass);
         if (iotDeviceTypeLv1Enum == null) {
             log.error("[设备告警] 设备大类不存在,devBid:{}, devtypeBid:{}", devBid, devtypeBid);
@@ -103,7 +147,7 @@ public class WarnService {
             Map<String, IotDevicefactor> factorMap = getDevicefactorMap(devBid);
 
             //配置一个个检查
-            for(Map.Entry<String, List<WarnConfigInfo>> entry : configMap.entrySet()) {
+            for (Map.Entry<String, List<WarnConfigInfo>> entry : configMap.entrySet()) {
                 List<WarnConfigInfo> configList = entry.getValue();
                 WarnResult warnResult = null;
 
@@ -114,7 +158,7 @@ public class WarnService {
                 warnInfoDto.setFactorMap(factorMap);
                 warnInfoDto.setIotDeviceTypeLv1Enum(iotDeviceTypeLv1Enum);
 
-                try{
+                try {
                     switch (iotDeviceTypeLv1Enum) {
                         case QXZ: {
                             warnResult = comparableQxzReportData(warnInfoDto);
@@ -135,7 +179,7 @@ public class WarnService {
                         default:
                             break;
                     }
-                }catch (Exception e){
+                } catch (Exception e) {
                     log.error("[设备告警] 设备上报数据 异常,devBid:{}, config:{}, data:{}", devBid, configList, data, e);
                 }
 
@@ -156,6 +200,20 @@ public class WarnService {
         reCountService.handlerMessage(warnResult);
     }
 
+    private Map<String, IotDevicefactor> getDevicefactorMap(String devBid) {
+        IotDevicefactor param = new IotDevicefactor();
+        param.setDevBid(devBid);
+        List<IotDevicefactor> factorList = iotDevicefactorService.selectIotDevicefactorList(param);
+        Map<String, IotDevicefactor> factorMap = new HashMap<>();
+        for (IotDevicefactor factor : factorList) {
+            String dfCode = factor.getDfCode();
+            String dfAddress = factor.getDfAddress();
+            String key = dfAddress + dfCode;
+            factorMap.put(key, factor);
+        }
+        return factorMap;
+    }
+
     /**
      * 根据设备id获取策略,可能有多个
      *
@@ -171,7 +229,7 @@ public class WarnService {
         String devCode = iotDevice.getDevCode();
         BigDecimal errorValue = new BigDecimal("-99");
         Map<String, String> currentValueMap = new HashMap<>();
-        for(Object obj : jsonArray) {
+        for (Object obj : jsonArray) {
             JSONObject ob;
             try {
                 ob = JSONObject.from(obj);
@@ -201,16 +259,16 @@ public class WarnService {
         return currentValueMap;
     }
 
-    private String getDisplayName(String key, Map<String, IotDevicefactor> factorMap){
+    private String getDisplayName(String key, Map<String, IotDevicefactor> factorMap) {
         String wiName = "";
-        if(factorMap.containsKey(key)){
+        if (factorMap.containsKey(key)) {
             IotDevicefactor iotDevicefactor = factorMap.get(key);
             // 如果禁用,直接返回null,不进行预警判断
-            if(Objects.equals(iotDevicefactor.getDfDisable(), "1")){
+            if (Objects.equals(iotDevicefactor.getDfDisable(), "1")) {
                 return null;
             }
             String displayname = iotDevicefactor.getDfDisplayname();
-            if(StringUtils.isNotEmpty(displayname)){
+            if (StringUtils.isNotEmpty(displayname)) {
                 wiName = displayname;
             }
         }
@@ -235,7 +293,7 @@ public class WarnService {
 
         // 如果配置禁用,或者要素禁用,直接返回null,不进行预警判断
         boolean status = "0".equals(wcStatus) && "0".equals(wiStatus);
-        if(!status){
+        if (!status) {
             return null;
         }
 
@@ -245,25 +303,25 @@ public class WarnService {
         }
 
         // 如果没有配置预警条件和值,直接返回null,不进行预警判断
-        if(StringUtils.isEmpty(expression) || StringUtils.isEmpty(targetValue)){
+        if (StringUtils.isEmpty(expression) || StringUtils.isEmpty(targetValue)) {
             return null;
         }
 
         String wiName = config.getWiName();
         // 如果禁用,直接返回null,不进行预警判断
         String displayname = getDisplayName(key, factorMap);
-        if(displayname == null){
+        if (displayname == null) {
             return null;
         }
 
-        if(StringUtils.isNotEmpty(displayname)){
+        if (StringUtils.isNotEmpty(displayname)) {
             wiName = displayname;
         }
         String wiUnit = config.getWiUnit();
         String currentValue = currentValueMap.get(key);
 
         EnumWarnRuleOp warnRuleOp = EnumWarnRuleOp.findEnumByCode(expression);
-        if(warnRuleOp == null){
+        if (warnRuleOp == null) {
             log.error("[设备告警] 表达式不正确,devCode:{}, wiAddress:{}, config:{}", devCode, wiAddress, config);
             return null;
         }
@@ -285,11 +343,9 @@ public class WarnService {
 
     /**
      * 【气象站】比较该设备上报的任一要素否达到预警条件
+     *
      * @param warnResult
-     * @param configList
-     * @param factorMap
-     * @param currentValueMap
-     * @param devCode
+     * @param warnInfoDto
      * @return
      */
     public WarnResult comparableQxzSingleIndicator(WarnResult warnResult, WarnInfoDto warnInfoDto) {
@@ -298,14 +354,14 @@ public class WarnService {
         for (WarnConfigInfo config : configList) {
             warnStatusDto = getQxzWarnStatusDto(config, warnInfoDto);
             // 如果没有预警配置,直接返回null,不进行预警判断
-            if(warnStatusDto == null){
+            if (warnStatusDto == null) {
                 continue;
             }
-            if(warnStatusDto.isWarn()){
+            if (warnStatusDto.isWarn()) {
                 break;
             }
         }
-        if(warnStatusDto != null && warnStatusDto.isWarn()){
+        if (warnStatusDto != null && warnStatusDto.isWarn()) {
             String message = WarnMessageBuilderUtil.buildQxzWarningMessage(
                     warnStatusDto.getDevType(),
                     warnStatusDto.getDevCode(),
@@ -325,9 +381,8 @@ public class WarnService {
     /**
      * 处理多个指标是否同时满足预警条件。
      *
-     * @param devId      设备ID
-     * @param config     告警规则
-     * @param jsonObject 上报的数据
+     * @param warnResult
+     * @param warnInfoDto
      * @return WarnResult 包含是否触发告警的信息
      */
     public WarnResult comparableQxzMultipleIndicators(WarnResult warnResult, WarnInfoDto warnInfoDto) {
@@ -337,24 +392,24 @@ public class WarnService {
         for (WarnConfigInfo config : configList) {
             warnStatusDto = getQxzWarnStatusDto(config, warnInfoDto);
             // 如果没有预警配置,直接返回null,不进行预警判断
-            if(warnStatusDto == null){
+            if (warnStatusDto == null) {
                 continue;
             }
-            if(!warnStatusDto.isWarn()){
+            if (!warnStatusDto.isWarn()) {
                 return warnResult;
             }
             warnStatusDtos.add(warnStatusDto);
         }
-        if(warnStatusDtos.isEmpty()){
+        if (warnStatusDtos.isEmpty()) {
             return warnResult;
         }
 
         StringBuilder messageBuilder = new StringBuilder();
-        for(int i = 0; i < warnStatusDtos.size(); i++){
+        for (int i = 0; i < warnStatusDtos.size(); i++) {
             warnStatusDto = warnStatusDtos.get(i);
             String devType = null;
             String dCode = null;
-            if(i == 0){
+            if (i == 0) {
                 devType = warnStatusDto.getDevType();
                 dCode = warnStatusDto.getDevCode();
             }
@@ -378,9 +433,8 @@ public class WarnService {
     /**
      * 【气象站】比较该设备上报的要素和配置是否达到预警条件
      *
-     * @param devBid      设备id
-     * @param config     对应的配置
-     * @param jsonObject 上报的数据
+     * @param warnInfoDto
+     * @return
      */
     private WarnResult comparableQxzReportData(WarnInfoDto warnInfoDto) {
         IotDevice iotDevice = warnInfoDto.getIotDevice();
@@ -409,7 +463,7 @@ public class WarnService {
         warnResult.setConfig(iotWarnconfig);
         warnResult.setTriggered(false);
 
-        if("0".equals(wcCondition)){
+        if ("0".equals(wcCondition)) {
             warnResult = comparableQxzSingleIndicator(warnResult, warnInfoDto);
         } else {
             warnResult = comparableQxzMultipleIndicators(warnResult, warnInfoDto);
@@ -420,7 +474,6 @@ public class WarnService {
 
     /**
      * 【墒情站】比较该设备上报的要素和配置是否达到预警条件
-     *
      */
     WarnResult comparableSqzReportData(WarnInfoDto warnInfoDto) {
         return comparableQxzReportData(warnInfoDto);
@@ -429,7 +482,6 @@ public class WarnService {
 
     /**
      * 【管式墒情】比较该设备上报的要素和配置是否达到预警条件
-     *
      */
     WarnResult comparableGssqReportData(WarnInfoDto warnInfoDto) {
         return comparableQxzReportData(warnInfoDto);

+ 17 - 1
src/main/java/com/yunfeiyun/agmp/iots/warn/util/WarnMessageBuilderUtil.java

@@ -16,7 +16,7 @@ public class WarnMessageBuilderUtil {
     public static String buildQxzWarningMessage(String devType, String devCode, String name, String value, String unit, String opt, String indicatorValue) {
         // 格式化字符串,将设备类型、设备唯一编码、告警参数名、当前值、单位、动作和目标对比值插入到模板中
         String tag = "";
-        if(devType != null && devCode != null){
+        if (devType != null && devCode != null) {
             tag = String.format("%s设备(%s), 触发告警,告警原因: \n", devType, devCode);
         }
         return String.format("%s %s 上报值 %s%s,%s设置的阀值%s。",
@@ -28,6 +28,22 @@ public class WarnMessageBuilderUtil {
                 indicatorValue);
     }
 
+    /**
+     * 构建离线消息
+     *
+     * @param devType
+     * @param devCode
+     * @param name
+     * @return
+     */
+    public static String buildWarningOfflineMessage(String devType, String devCode, String name) {
+        String tag = "";
+        if (devType != null && devCode != null) {
+            tag = String.format("%s设备(%s), 触发告警,告警原因: \n", devType, devCode);
+        }
+        return String.format("%s %s 离线。", tag, name);
+    }
+
     public static void main(String[] args) {
         String message = buildQxzWarningMessage("气象站", "87872877485", "温度", "42", "℃", "超过", "10-35℃");
         System.out.println(message);

+ 3 - 0
src/main/resources/mapper/IotWarnBusinessMapper.xml

@@ -99,4 +99,7 @@
     <select id="getAllReCount" resultType="com.yunfeiyun.agmp.iot.common.domain.IotWarncount">
         select  * from IotWarncount
     </select>
+    <select id="selectIotWarnOfflineConfigInfo" resultType="com.yunfeiyun.agmp.iot.common.domain.IotWarnconfig">
+        select * from IotWarnconfig where tid = #{tid};
+    </select>
 </mapper>