工业互联网平台2.0版本后端代码
dengzedong
2025-05-14 8444f52bfaae777dc0dafd40f13db75fa574f159
预测结果t+l 根据调整用户自动调整
已修改3个文件
217 ■■■■■ 文件已修改
iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/influxdb/service/impl/InfluxDBServiceImpl.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mcs/pre/enums/AutoAdjustValueRuleEnum.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mcs/pre/service/impl/MmPredictAutoAdjustConfigServiceImpl.java 189 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/influxdb/service/impl/InfluxDBServiceImpl.java
@@ -67,6 +67,7 @@
        String measurement = MeasurementUtils.getMeasurement(pojo.getType());
        StringBuilder sb = new StringBuilder();
        sb.append("from(bucket:\"" + influxDBInstance.getBucket() + "\") ");
        // range函数 是左闭右开区间
        sb.append("|> range(start: ").append(start).append(", stop: ").append(stop).append(") ");
        sb.append("|> filter(fn: (r) => r[\"_measurement\"] == \"" + measurement + "\")");
        sb.append("|> filter(fn: (r) => r[\"_field\"] == \"value\")");
iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mcs/pre/enums/AutoAdjustValueRuleEnum.java
@@ -1,11 +1,13 @@
package com.iailab.module.model.mcs.pre.enums;
import com.iailab.module.data.api.point.dto.ApiPointValueDTO;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.function.Function;
/**
@@ -15,22 +17,23 @@
@AllArgsConstructor
public enum AutoAdjustValueRuleEnum {
    // 均值差
    AVERAGE_GAP_VALUE("average_gap_value",(map) -> {
        if (!map.containsKey("startValue") || !map.containsKey("endValue")) {
            return 0.0;
    // 流量累计
    FLOW_RATE_ACCUMULATION("flow_rate_accumulation",(apiPointValues) -> {
        // 基准值
        double refValue = apiPointValues.get(0).getV();
        double adjustValue = 0.0;
        for (ApiPointValueDTO pointValue : apiPointValues) {
            adjustValue += pointValue.getV() - refValue;
        }
        Double startValue = Double.valueOf(map.get("startValue").toString());
        Double endValue = Double.valueOf(map.get("endValue").toString());
        return endValue - startValue;
        return adjustValue / 60;
    });
    private final String code;
    private final Function<HashMap<String,Object>, Double> calculator;
    private final Function<List<ApiPointValueDTO>, Double> calculator;
    public Double calculate(HashMap<String,Object> map) {
        return calculator.apply(map);
    public Double calculate(List<ApiPointValueDTO> apiPointValues) {
        return calculator.apply(apiPointValues);
    }
    public static AutoAdjustValueRuleEnum fromCode(String code) {
@@ -42,13 +45,13 @@
        return null;
    }
    public static Double getAdjustValue(String code,HashMap<String,Object> map) {
    public static Double getAdjustValue(String code, List<ApiPointValueDTO> apiPointValues) {
        AutoAdjustValueRuleEnum rule = AutoAdjustValueRuleEnum.fromCode(code);
        if (rule == null) {
            return 0.0;
        }
        return rule.calculate(map);
        return rule.calculate(apiPointValues);
    }
}
iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mcs/pre/service/impl/MmPredictAutoAdjustConfigServiceImpl.java
@@ -4,6 +4,7 @@
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.common.service.impl.BaseServiceImpl;
import com.iailab.module.data.api.point.DataPointApi;
import com.iailab.module.data.api.point.dto.ApiPointDTO;
import com.iailab.module.data.api.point.dto.ApiPointValueDTO;
import com.iailab.module.data.api.point.dto.ApiPointValueQueryDTO;
import com.iailab.module.model.common.enums.DataTypeEnum;
@@ -27,6 +28,7 @@
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
@@ -88,93 +90,127 @@
            return false;
        }
        Double adjustValue = 0.0;
        ApiPointValueQueryDTO queryDTO;
        // 查询调整用户adjustStartTime 至 adjustStartTime - 预测长度 * 预测粒度 范围的值
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(adjustStartTime);
        Date endTime;
        Date startTime;
        List<ApiPointValueDTO> apiPointValueDTOS;
        Date endTime = calendar.getTime();
        ItemVO item = mmPredictItemService.getItemByOutPutId(configEntity.getOutputId());
        if (item == null) {
            log.info("自动调整失败原因:getItemByOutPutId为null,outputId:" + configEntity.getOutputId());
            return false;
        }
        calendar.add(Calendar.SECOND,item.getPredictLength() * item.getGranularity() * -1);
        Date startTime = calendar.getTime();
        ApiPointValueQueryDTO queryDTO = new ApiPointValueQueryDTO();
        ApiPointDTO pointInfo = dataPointApi.getInfoById(configEntity.getPointId());
        queryDTO.setPointNo(pointInfo.getPointNo());
        queryDTO.setEnd(endTime);
        queryDTO.setStart(startTime);
        List<ApiPointValueDTO> apiPointValueDTOS = dataPointApi.queryPointHistoryValue(queryDTO);
        if (CollectionUtils.isEmpty(apiPointValueDTOS)) {
            log.info("自动调整失败原因:测点数据长度为0。queryDTO:" + queryDTO);
            return false;
        }
        // 过滤掉-2
        apiPointValueDTOS = apiPointValueDTOS.stream().filter(e -> !Double.valueOf(e.getV()).equals(-2.0)).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(apiPointValueDTOS)) {
            log.info("自动调整失败原因:过滤掉-2之后测点数据长度为0。queryDTO:" + queryDTO);
            return false;
        }
        // 获取预测历史结果
        InfluxModelResultPOJO pojo = new InfluxModelResultPOJO();
        pojo.setType(DataTypeEnum.FLOAT_LAST_BAK.getCode());
        pojo.setOutPutId(configEntity.getOutputId());
        List<InfluxModelResultVO> influxModelResult = influxDBService.queryModelResults(pojo, new Date(adjustStartTime), new Date(adjustStartTime));
        if (CollectionUtils.isEmpty(influxModelResult)) {
            log.info("自动调整失败原因:预测历史结果为空。itemNo:" + item.getItemNo() + ",itemName" + item.getItemName() + ",outputId" + configEntity.getOutputId() + ",time" + adjustStartTime);
            return false;
        }
        // 触发规则
        AutoAdjustTriggerRuleEnum triggerRuleEnum = AutoAdjustTriggerRuleEnum.fromCode(configEntity.getTriggerRule());
        Double adjustValue = null;
        // 判断是否符合触发条件 并计算调整值
        switch (triggerRuleEnum) {
            case SLOPE:
                queryDTO = new ApiPointValueQueryDTO();
                queryDTO.setPointNo(dataPointApi.getInfoById(configEntity.getPointId()).getPointNo());
                endTime = calendar.getTime();
                queryDTO.setEnd(endTime);
                calendar.add(Calendar.MINUTE,-1 * configEntity.getT());
                startTime = calendar.getTime();
                queryDTO.setStart(startTime);
                apiPointValueDTOS = dataPointApi.queryPointHistoryValue(queryDTO);
                if (CollectionUtils.isEmpty(apiPointValueDTOS)) {
                    log.info("自动调整失败原因:测点数据长度为0");
                // 计算每个△t的斜率,任意一个大于触发值则认为该区间有调整
                Calendar slopeCalendar = Calendar.getInstance();
                slopeCalendar.setTime(startTime);
                Date slopeStartTime = slopeCalendar.getTime();
                slopeCalendar.add(Calendar.MINUTE,configEntity.getT());
                Date slopeEndTime = slopeCalendar.getTime();
                if (slopeEndTime.after(endTime)) {
                    log.info("自动调整失败原因:△t设置过大,大于模型预测长度 * 预测粒度。△t:" + configEntity.getT());
                    return false;
                }
                apiPointValueDTOS = apiPointValueDTOS.stream().filter(e -> e.getV() != -2).collect(Collectors.toList());
                if (CollectionUtils.isEmpty(apiPointValueDTOS)) {
                    log.info("自动调整失败原因:测点数据长度为0");
                    return false;
                }
                Optional<ApiPointValueDTO> startOptional = apiPointValueDTOS.stream().filter(e -> e.getT().equals(startTime)).findFirst();
                if (!startOptional.isPresent()) {
                    log.info("自动调整失败原因:计算斜率startTime时间点测点值为null,startTime:" + startTime);
                    return false;
                }
                Optional<ApiPointValueDTO> endOptional = apiPointValueDTOS.stream().filter(e -> e.getT().equals(endTime)).findFirst();
                if (!endOptional.isPresent()) {
                    log.info("自动调整失败原因:计算斜率endTime时间点测点值为null,endTime:" + endTime);
                    return false;
                }
                while (!slopeEndTime.after(endTime)) {
                    //计算斜率
                    //△t开始时间测点值
                    Date finalSlopeStartTime = slopeStartTime;
                    Optional<ApiPointValueDTO> startOptional = apiPointValueDTOS.stream().filter(apiPointValueDTO -> apiPointValueDTO.getT().equals(finalSlopeStartTime)).findFirst();
                    //△t结束时间测点值
                    Date finalSlopeEndTime = slopeEndTime;
                    Optional<ApiPointValueDTO> endOptional = apiPointValueDTOS.stream().filter(e -> e.getT().equals(finalSlopeEndTime)).findFirst();
                    if (startOptional.isPresent() && endOptional.isPresent()) {
                ApiPointValueDTO startPointValue = startOptional.get();
                ApiPointValueDTO endPointValue = endOptional.get();
                // 计算斜率,有正负之分,代表上升或下降
                        // 计算斜率
                double slope = BigDecimal.valueOf(endPointValue.getV() - startPointValue.getV()).divide(BigDecimal.valueOf(configEntity.getT())).doubleValue();
                //斜率绝对值大于等于触发值则进行调整
                        // 斜率大于等于触发值则进行调整
                if (Double.valueOf(Math.abs(slope)).compareTo(configEntity.getTriggerValue()) >= 0) {
                    //计算调整值
                    HashMap<String,Object> map = new HashMap<>();
                    map.put("startValue",startPointValue.getV());
                    map.put("endValue",endPointValue.getV());
                    adjustValue = AutoAdjustValueRuleEnum.getAdjustValue(configEntity.getAdjustValueRule(), map);
                } else {
                    log.info("自动调整失败原因:斜率小于调整值,斜率:" + slope);
                    return false;
                            // 计算调整值 并跳出循环
                            adjustValue = AutoAdjustValueRuleEnum.getAdjustValue(configEntity.getAdjustValueRule(), apiPointValueDTOS);
                            log.info("计算调整值:" + adjustValue + ",斜率:" + slope + ",pointNo:" + pointInfo.getPointNo() + ",pointName:" + pointInfo.getPointName() + ",slopeStartTime:" + slopeStartTime + ",slopeEndTime:" + slopeEndTime);
                            break;
                        }
                    }
                    // 下一个△t
                    slopeStartTime = slopeCalendar.getTime();
                    slopeCalendar.add(Calendar.MINUTE,configEntity.getT());
                    slopeEndTime = slopeCalendar.getTime();
                }
                break;
            case AVERAGE_GAP:
                queryDTO = new ApiPointValueQueryDTO();
                queryDTO.setPointNo(dataPointApi.getInfoById(configEntity.getPointId()).getPointNo());
                endTime = calendar.getTime();
                queryDTO.setEnd(endTime);
                calendar.add(Calendar.MINUTE,-1 * configEntity.getT() * 2 + 1);
                startTime = calendar.getTime();
                queryDTO.setStart(startTime);
                apiPointValueDTOS = dataPointApi.queryPointHistoryValue(queryDTO);
                if (CollectionUtils.isEmpty(apiPointValueDTOS)) {
                    log.info("自动调整失败原因:测点数据长度为0");
                // 计算每两个△t的平均差,任意一个大于触发值则认为该区间有调整
                Calendar averageCalendar = Calendar.getInstance();
                averageCalendar.setTime(startTime);
                Date averageStartTime = averageCalendar.getTime();
                averageCalendar.add(Calendar.MINUTE,configEntity.getT());
                Date averageMiddleTime = averageCalendar.getTime();
                averageCalendar.add(Calendar.MINUTE,configEntity.getT());
                Date averageEndTime = averageCalendar.getTime();
                if (averageEndTime.after(endTime)) {
                    log.info("自动调整失败原因:△t设置过大,△t*2大于模型预测长度 * 预测粒度。△t:" + configEntity.getT());
                    return false;
                }
                apiPointValueDTOS = apiPointValueDTOS.stream().filter(e -> e.getV() != -2).collect(Collectors.toList());
                if (CollectionUtils.isEmpty(apiPointValueDTOS)) {
                    log.info("自动调整失败原因:测点数据长度为0");
                    return false;
                while (!averageEndTime.after(endTime)) {
                    //计算均值差
                    //前△t测点平均值
                    Date finalAverageStartTime = averageStartTime;
                    Date finalAverageMiddleTime = averageMiddleTime;
                    OptionalDouble startAverage = apiPointValueDTOS.stream().filter(e -> e.getT().after(finalAverageStartTime) && !e.getT().after(finalAverageMiddleTime)).mapToDouble(ApiPointValueDTO::getV).average();
                    //后△t测点平均值
                    Date finalAverageEndTime = averageEndTime;
                    OptionalDouble endAverage = apiPointValueDTOS.stream().filter(e -> e.getT().after(finalAverageMiddleTime) && !e.getT().after(finalAverageEndTime)).mapToDouble(ApiPointValueDTO::getV).average();
                    if (startAverage.isPresent() && endAverage.isPresent()) {
                        double averageGapValue = startAverage.getAsDouble() - endAverage.getAsDouble();
                        // 均值差,大于等于触发值则进行调整
                        if (Double.valueOf(Math.abs(averageGapValue)).compareTo(configEntity.getTriggerValue()) >= 0) {
                            // 计算调整值 并跳出循环
                            adjustValue = AutoAdjustValueRuleEnum.getAdjustValue(configEntity.getAdjustValueRule(), apiPointValueDTOS);
                            log.info("计算调整值:" + adjustValue + ",均值差:" + averageGapValue + ",pointNo:" + pointInfo.getPointNo() + ",pointName:" + pointInfo.getPointName() + ",averageStartTime:" + averageStartTime + ",averageMiddleTime:" + averageMiddleTime + ",averageEndTime:" + averageEndTime);
                            break;
                }
                calendar.add(Calendar.MINUTE,configEntity.getT());
                double startAverage = apiPointValueDTOS.stream().filter(e -> e.getT().before(calendar.getTime())).collect(Collectors.summarizingDouble(ApiPointValueDTO::getV)).getAverage();
                double endAverage = apiPointValueDTOS.stream().filter(e -> e.getT().compareTo(calendar.getTime()) >= 0).collect(Collectors.summarizingDouble(ApiPointValueDTO::getV)).getAverage();
                // 计算均值差,大于等于触发值则进行调整
                if (Double.valueOf(Math.abs(startAverage - endAverage)).compareTo(configEntity.getTriggerValue()) >= 0) {
                    //计算调整值
                    HashMap<String,Object> map = new HashMap<>();
                    map.put("startValue",startAverage);
                    map.put("endValue",endAverage);
                    adjustValue = AutoAdjustValueRuleEnum.getAdjustValue(configEntity.getAdjustValueRule(), map);
                } else {
                    log.info("自动调整失败原因:均值差小于调整值,均值差:" + (startAverage - endAverage));
                    return false;
                    }
                    // 下一个△t
                    averageStartTime = averageMiddleTime;
                    averageMiddleTime = averageEndTime;
                    averageCalendar.add(Calendar.MINUTE,configEntity.getT());
                    averageEndTime = averageCalendar.getTime();
                }
                break;
            default:
@@ -185,21 +221,6 @@
        // 调整方向
        adjustValue = adjustValue * configEntity.getAdjustDirection();
        // 获取历史结果
        ItemVO item = mmPredictItemService.getItemByOutPutId(configEntity.getOutputId());
        if (item == null) {
            log.info("自动调整失败原因:getItemByOutPutId为null,outputId:" + configEntity.getOutputId());
            return false;
        }
        Calendar resultCalendar = Calendar.getInstance();
        resultCalendar.setTimeInMillis(adjustStartTime);
        Date resultStartTime = resultCalendar.getTime();
        resultCalendar.add(Calendar.SECOND,configEntity.getAdjustLength() * item.getGranularity());
        Date resultEndTime = resultCalendar.getTime();
        InfluxModelResultPOJO pojo = new InfluxModelResultPOJO();
        pojo.setType(DataTypeEnum.FLOAT_LAST_BAK.getCode());
        pojo.setOutPutId(configEntity.getOutputId());
        List<InfluxModelResultVO> influxModelResult = influxDBService.queryModelResults(pojo, resultStartTime, resultEndTime);
        List<InfluxModelResultPOJO> lastList = new ArrayList<>();
        for (InfluxModelResultVO resultVO : influxModelResult) {
@@ -212,7 +233,7 @@
        }
        // 相同时间直接覆盖旧值
        influxDBService.asyncWriteModelResults(lastList);
        log.info("t+l自动调整。configCode:" + configCode + ",adjustValue:" + adjustValue + ",resultStartTime:" + resultStartTime + ",resultEndTime:" + resultEndTime + "调整长度:" + lastList.size());
        log.info("t+l自动调整。configCode:" + configCode + ",adjustValue:" + adjustValue + ",itemNo:" + item.getItemNo() + ",itemName" + item.getItemName() + ",outputId" + configEntity.getOutputId() + ",adjustTime:" + adjustStartTime);
        return true;
    }
}