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

+ 0 - 3
src/main/java/com/yunfeiyun/agmp/iots/device/serviceImp/XphYfQxzDeviceImpl.java

@@ -19,7 +19,6 @@ import com.yunfeiyun.agmp.iots.device.domain.yfqxz.YfQxzReqMsg;
 import com.yunfeiyun.agmp.iots.device.service.IXphYfQxzDevice;
 import com.yunfeiyun.agmp.iots.service.*;
 import com.yunfeiyun.agmp.iots.service.impl.IotDeviceAddressService;
-import com.yunfeiyun.agmp.iots.service.impl.WarnService;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.http.util.TextUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -64,8 +63,6 @@ public class XphYfQxzDeviceImpl extends DeviceAbstractImpl implements IXphYfQxzD
     @Autowired
     private IIotCmdlogService iIotCmdlogService;
 
-    @Autowired
-    private WarnService warnService;
 
     @Autowired
     private IotDeviceAddressService iotDeviceAddressService;

+ 0 - 3
src/main/java/com/yunfeiyun/agmp/iots/device/serviceImp/YfQxzDeviceImpl.java

@@ -29,7 +29,6 @@ import com.yunfeiyun.agmp.iots.service.IIotDeviceService;
 import com.yunfeiyun.agmp.iots.service.IIotDeviceconfigService;
 import com.yunfeiyun.agmp.iots.service.IIotDevicelasteddataService;
 import com.yunfeiyun.agmp.iots.service.impl.IotDeviceAddressService;
-import com.yunfeiyun.agmp.iots.service.impl.WarnService;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.http.util.TextUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -74,8 +73,6 @@ public class YfQxzDeviceImpl extends DeviceAbstractImpl implements IYfQxzDevice
     @Autowired
     private IIotCmdlogService iIotCmdlogService;
 
-    @Autowired
-    private WarnService warnService;
 
     @Autowired
     private IotDeviceAddressService iotDeviceAddressService;

+ 0 - 2
src/main/java/com/yunfeiyun/agmp/iots/service/impl/IotCbdImgService.java

@@ -43,8 +43,6 @@ public class IotCbdImgService {
     @Resource
     private IIotPestService iotPestService;
 
-    @Autowired
-    private WarnService warnService;
 
 
 

Разница между файлами не показана из-за своего большого размера
+ 649 - 635
src/main/java/com/yunfeiyun/agmp/iots/service/impl/WarnService.java


+ 17 - 0
src/main/java/com/yunfeiyun/agmp/iots/warn/job/WarnJob.java

@@ -0,0 +1,17 @@
+package com.yunfeiyun.agmp.iots.warn.job;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component
+public class WarnJob {
+    /**
+     * 每天凌晨12点清除重复次数
+     */
+    @Scheduled(cron = "0 0 0 * * ?")
+    public void resetReCount() {
+
+    }
+}

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

@@ -0,0 +1,20 @@
+package com.yunfeiyun.agmp.iots.warn.model;
+
+import lombok.Data;
+
+/**
+ * 预警结果,不是对应数据库层面的
+ */
+@Data
+public class WarnResult {
+    private boolean isTriggered;
+    private String message;
+
+    public WarnResult(boolean isTriggered, String message) {
+        this.isTriggered = isTriggered;
+        this.message = message;
+    }
+
+    public WarnResult() {
+    }
+}

+ 204 - 0
src/main/java/com/yunfeiyun/agmp/iots/warn/service/WarnService.java

@@ -0,0 +1,204 @@
+package com.yunfeiyun.agmp.iots.warn.service;
+
+import com.alibaba.fastjson2.JSONObject;
+import com.yunfeiyun.agmp.iot.common.enums.EnumWarnRuleOp;
+import com.yunfeiyun.agmp.iots.warn.model.WarnResult;
+import com.yunfeiyun.agmp.iots.warn.util.CompareUtil;
+import com.yunfeiyun.agmp.iots.warn.util.WarnMessageBuilderUtil;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * 预警核心服务类
+ */
+@Service
+public class WarnService {
+
+    @Resource(name = "threadPoolTaskExecutor")
+    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
+
+    /**
+     * 统一处理上报数据
+     *
+     * @param devId 设备id
+     * @param data  上报的数据对象
+     */
+    public void processWarningReportData(String devId, JSONObject data) {
+        //转异步处理
+        processWarningReportDataSyn(devId, data);
+    }
+
+
+    /**
+     * 统一处理上报数据:异步处理
+     *
+     * @param devId 设备id
+     * @param data  上报的数据对象
+     */
+    private void processWarningReportDataSyn(String devId, JSONObject data) {
+        CompletableFuture.runAsync(() -> {
+            String devClass = "设备大类"; // todo
+            // 获取该设备有哪些告警配置
+            List<Object> objects = getConfigByDevId(devId);
+            //配置一个个检查
+            for (Object config : objects) {
+                WarnResult warnResult = null;
+                switch (devClass) {
+                    case "气象站": {
+                        warnResult = comparableQxzReportData(devId, config, data);
+                        break;
+                    }
+                    case "墒情站": {
+                        warnResult = comparableSqzReportData(devId, config, data);
+                        break;
+                    }
+                    case "病虫害": {
+                        warnResult = comparableBchReportData(devId, config, data);
+                        break;
+                    }
+                    default:
+                        break;
+                }
+                if (warnResult != null) {
+                    handleWarnRecord(warnResult);
+                }
+            }
+        }, threadPoolTaskExecutor);
+    }
+
+    /**
+     * 基于预警结果统一处理入库操作
+     *
+     * @param warnResult
+     */
+    void handleWarnRecord(WarnResult warnResult) {
+        if (warnResult.isTriggered()) {
+            //进行预警重复次数处理机制
+            //入库 todo
+        }
+    }
+
+    /**
+     * 根据设备id获取策略,可能有多个
+     *
+     * @param devId
+     * @return
+     */
+    List<Object> getConfigByDevId(String devId) {
+
+        return null;
+    }
+
+    /**
+     * 【气象站】比较该设备上报的要素和配置是否达到预警条件
+     *
+     * @param devId      设备id
+     * @param config     对应的配置
+     * @param jsonObject 上报的数据
+     */
+    WarnResult comparableQxzReportData(String devId, Object config, JSONObject jsonObject) {
+        WarnResult warnResult = null;
+        if ("指标类型" == "多指标满足") {
+            warnResult = comparableQxzMultipleIndicators(devId, config, jsonObject);
+        } else {
+            warnResult = comparableQxzSingleIndicator(devId, config, jsonObject);
+        }
+        return warnResult;
+    }
+
+    /**
+     * 处理单一指标是否达到预警条件。
+     *
+     * @param devId      设备ID
+     * @param config     配置对象
+     * @param jsonObject 上报的数据
+     * @return WarnResult 包含是否触发告警的信息
+     */
+    public WarnResult comparableQxzSingleIndicator(String devId, Object config, JSONObject jsonObject) {
+        //从config取出需要匹配的要素列表 todo
+        List<Object> items = new ArrayList<>();
+        //循环要素,一个个对比
+        for (Object item : items) {
+            // 取出来需要比较的要素 todo
+            String comparableItem = "item.getField";
+            //要对比的目标值 todo
+            String targetValue = "item.targetValue";
+            //取出来当前的最新值 todo
+            String currentValue = "jsonObject.get[item.getField]";
+            // 字段表达式比较
+            boolean result = CompareUtil.comp(currentValue, EnumWarnRuleOp.EQUAL.getCode(), targetValue);
+            if (result) {
+                String message = WarnMessageBuilderUtil.buildQxzWarningMessage("气象站设备", devId, comparableItem, Double.parseDouble(currentValue), "℃", "超过", targetValue);
+                return new WarnResult(true, message);
+            }
+        }
+        return new WarnResult(false, null);
+    }
+
+    /**
+     * 处理多个指标是否同时满足预警条件。
+     *
+     * @param devId      设备ID
+     * @param config     告警规则
+     * @param jsonObject 上报的数据
+     * @return WarnResult 包含是否触发告警的信息
+     */
+    public WarnResult comparableQxzMultipleIndicators(String devId, Object config, JSONObject jsonObject) {
+        //从config取出需要匹配的要素列表 todo
+        List<Object> items = new ArrayList<>();
+        int successCount = 0;
+        StringBuilder messages = new StringBuilder();
+        //循环要素,一个个对比
+        for (Object item : items) {
+            // 取出来需要比较的要素 todo
+            String comparableItem = "item.getField";
+            //要对比的目标值 todo
+            String targetValue = "item.targetValue";
+            //取出来当前的最新值 todo
+            String currentValue = "jsonObject.get[item.getField]";
+            // 字段表达式比较
+            boolean result = CompareUtil.comp(currentValue, EnumWarnRuleOp.EQUAL.getCode(), targetValue);
+            if (result) {
+                messages.append(WarnMessageBuilderUtil.buildQxzWarningMessage("气象站设备", devId, comparableItem, Double.parseDouble(currentValue), "℃", "超过", targetValue));
+                successCount += 1;
+            }
+        }
+
+        if (successCount == items.size()) {
+            return new WarnResult(true, messages.toString());
+        } else {
+            return new WarnResult(false, null);
+        }
+    }
+
+
+    /**
+     * 【墒情站】比较该设备上报的要素和配置是否达到预警条件,暂不实现,预留
+     *
+     * @param devId
+     * @param config
+     * @param jsonObject
+     */
+    WarnResult comparableSqzReportData(String devId, Object config, JSONObject jsonObject) {
+        return null;
+
+    }
+
+    /**
+     * 【病虫害】比较该设备上报的要素和配置是否达到预警条件,暂不实现,预留
+     *
+     * @param devId
+     * @param config
+     * @param jsonObject
+     */
+    WarnResult comparableBchReportData(String devId, Object config, JSONObject jsonObject) {
+        return null;
+
+    }
+
+}

+ 60 - 0
src/main/java/com/yunfeiyun/agmp/iots/warn/util/CompareUtil.java

@@ -0,0 +1,60 @@
+package com.yunfeiyun.agmp.iots.warn.util;
+
+import com.yunfeiyun.agmp.common.utils.StringUtils;
+import com.yunfeiyun.agmp.iot.common.enums.EnumWarnRuleOp;
+
+import java.math.BigDecimal;
+
+public class CompareUtil {
+
+    /**
+     * @param currentValue 当前值
+     * @param opCode       表达式
+     * @param targetValue  对比值,如果是范围,则10-100
+     * @return
+     */
+    public static boolean comp(String currentValue, String opCode, String targetValue) {
+        if (StringUtils.isEmpty(currentValue)) {
+            return false;
+        }
+        boolean ret = false;
+        if (EnumWarnRuleOp.GREATER_THAN.equal(opCode)) {
+            int compRet = new BigDecimal(currentValue).compareTo(new BigDecimal(targetValue));
+            if (compRet > 0) {
+                ret = true;
+            }
+        } else if (EnumWarnRuleOp.LESS_THAN.equal(opCode)) {
+            int compRet = new BigDecimal(currentValue).compareTo(new BigDecimal(targetValue));
+            if (compRet < 0) {
+                ret = true;
+            }
+        } else if (EnumWarnRuleOp.GT_EQUAL.equal(opCode)) {
+            int compRet = new BigDecimal(currentValue).compareTo(new BigDecimal(targetValue));
+            if (compRet > 0 || compRet == 0) {
+                ret = true;
+            }
+        } else if (EnumWarnRuleOp.LT_EQUAL.equal(opCode)) {
+            int compRet = new BigDecimal(currentValue).compareTo(new BigDecimal(targetValue));
+            if (compRet < 0 || compRet == 0) {
+                ret = true;
+            }
+        } else if (EnumWarnRuleOp.BETWEEN.equal(opCode)) {
+            String[] value = targetValue.split("-");
+            //大于等于min 且 小于等于max
+            boolean ret1 = false;
+            int compRet = new BigDecimal(currentValue).compareTo(new BigDecimal(value[0]));
+            if (compRet > 0 || compRet == 0) {
+                ret1 = true;
+            }
+
+            boolean ret2 = false;
+            int compRet2 = new BigDecimal(currentValue).compareTo(new BigDecimal(value[1]));
+            if (compRet2 < 0 || compRet2 == 0) {
+                ret2 = true;
+            }
+
+            ret = ret1 && ret2;
+        }
+        return ret;
+    }
+}

+ 31 - 0
src/main/java/com/yunfeiyun/agmp/iots/warn/util/WarnMessageBuilderUtil.java

@@ -0,0 +1,31 @@
+package com.yunfeiyun.agmp.iots.warn.util;
+
+public class WarnMessageBuilderUtil {
+    /**
+     * 构建告警信息。
+     *
+     * @param devType        设备类型,例如“气象站设备”。
+     * @param devCode        设备唯一编码,例如“87872877485”。
+     * @param code           告警参数名,例如“温度”。
+     * @param value          当前值,例如42。
+     * @param unit           单位,例如“℃”。
+     * @param opt            触发预警目标值的动作,例如超过,低于、大于等。
+     * @param indicatorValue 设定的目标对比值,例如“10-35℃”。
+     * @return 格式化后的告警信息。
+     */
+    public static String buildQxzWarningMessage(String devType, String devCode, String code, double value, String unit, String opt, String indicatorValue) {
+        return String.format("%s设备(%s),触发告警,告警原因(%s%s%s),%s设置的阀值%s",
+                devType,
+                devCode,
+                code,
+                value,
+                unit,
+                opt,
+                indicatorValue);
+    }
+
+    public static void main(String[] args) {
+        String message = buildQxzWarningMessage("气象站设备", "87872877485", "温度", 42, "℃", "超过", "10-35℃");
+        System.out.println(message);
+    }
+}