Browse Source

万达运行诊断1.0.0

shaohongbo 3 years ago
parent
commit
e39f13df02

+ 42 - 0
pom.xml

@@ -29,6 +29,16 @@
             <name>persagy Repository</name>
             <url>http://47.93.132.139:8081/nexus/content/repositories/persagy/</url>
         </repository>
+
+        <repository>
+            <id>snapshot</id>
+            <name>snapshot Repository</name>
+            <url>http://47.93.132.139:8081/nexus/content/repositories/snapshots/</url>
+            <snapshots>
+                <enabled>true</enabled>
+                <updatePolicy>always</updatePolicy>
+            </snapshots>
+        </repository>
     </repositories>
 
     <dependencies>
@@ -82,6 +92,21 @@
             <artifactId>integrated-ribbon-spring-boot-starter</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-logging</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>redis.clients</groupId>
+            <artifactId>jedis</artifactId>
+        </dependency>
+
         <!-- swagger -->
         <dependency>
             <groupId>com.persagy</groupId>
@@ -100,6 +125,23 @@
             <artifactId>apm-mybatis</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>com.persagy.apm</groupId>
+            <artifactId>alarm-data-starter</artifactId>
+            <version>v1.0.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>com.persagy.apm</groupId>
+            <artifactId>collect-data-starter</artifactId>
+            <version>v1.0.0-SNAPSHOT</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.persagy.apm</groupId>
+            <artifactId>alarm-engine-starter</artifactId>
+            <version>v1.0.0-SNAPSHOT</version>
+        </dependency>
+
         <!-- actuator:查询项目状态;项目上线需要把这个包注释掉,不然会有安全风险 -->
         <dependency>
             <groupId>org.springframework.boot</groupId>

+ 2 - 2
src/main/java/com/persagy/apm/diagnose/indicatorcompute/model/ProjectIndicatorCompute.java

@@ -13,10 +13,10 @@ import java.util.Date;
  * @author lixing
  * @version V1.0 2021-09-21 13:32:58
  */
-@EqualsAndHashCode(callSuper = true)
+
 @Data
 @ApiModel(description = "")
-public class ProjectIndicatorCompute extends AuditableEntity<ProjectIndicatorCompute> implements Serializable {
+public class ProjectIndicatorCompute  implements Serializable {
     private static final long serialVersionUID = 467957951700438996L;
 
     @ApiModelProperty("项目id")

+ 60 - 47
src/main/java/com/persagy/apm/diagnose/indicatorcompute/service/IProjectIndicatorComputeService.java

@@ -2,7 +2,10 @@ package com.persagy.apm.diagnose.indicatorcompute.service;
 
 import com.persagy.apm.diagnose.indicatorcompute.model.*;
 import com.persagy.apm.diagnose.indicatorcompute.model.dto.*;
+
 import java.util.List;
+import java.util.Map;
+
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -13,63 +16,73 @@ import io.swagger.annotations.ApiOperation;
  * @author lixing
  * @version V1.0 2021-09-21 13:32:54
  */
-public interface IProjectIndicatorComputeService  {
-    
+public interface IProjectIndicatorComputeService {
+
     /**
-    * 创建
-    *
-    * @param addProjectIndicatorComputeDTO addDTO
-    * @return 主键
-    * @author lixing
-    * @version V1.0 2021-09-21 13:32:54
-    */
+     * 创建
+     *
+     * @param addProjectIndicatorComputeDTO addDTO
+     * @return 主键
+     * @author lixing
+     * @version V1.0 2021-09-21 13:32:54
+     */
     public String createProjectIndicatorCompute(AddProjectIndicatorComputeDTO addProjectIndicatorComputeDTO);
-    
+
     /**
-    * 详情
-    *
-    * @param id 主键
-    * @return do对象
-    * @author lixing
-    * @version V1.0 2021-09-21 13:32:54
-    */
+     * 详情
+     *
+     * @param id 主键
+     * @return do对象
+     * @author lixing
+     * @version V1.0 2021-09-21 13:32:54
+     */
     public ProjectIndicatorCompute queryProjectIndicatorComputeDetail(String id);
-    
+
     /**
-    * 更新
-    *
-    * @param updateProjectIndicatorComputeDTO updateDTO
-    * @author lixing
-    * @version V1.0 2021-09-21 13:32:54
-    */
+     * 更新
+     *
+     * @param updateProjectIndicatorComputeDTO updateDTO
+     * @author lixing
+     * @version V1.0 2021-09-21 13:32:54
+     */
     public void updateProjectIndicatorCompute(UpdateProjectIndicatorComputeDTO updateProjectIndicatorComputeDTO);
-    
+
     /**
-    * 删除
-    *
-    * @param id 主键
-    * @author lixing
-    * @version V1.0 2021-09-21 13:32:54
-    */
+     * 删除
+     *
+     * @param id 主键
+     * @author lixing
+     * @version V1.0 2021-09-21 13:32:54
+     */
     public void deleteProjectIndicatorCompute(String id);
-    
+
     /**
-    * 查询
-    *
-    * @param queryProjectIndicatorComputeDTO queryDTO
-    * @return List<ProjectIndicatorCompute>
-    * @author lixing
-    * @version V1.0 2021-09-21 13:32:54
-    */
+     * 查询
+     *
+     * @param queryProjectIndicatorComputeDTO queryDTO
+     * @return List<ProjectIndicatorCompute>
+     * @author lixing
+     * @version V1.0 2021-09-21 13:32:54
+     */
     public List<ProjectIndicatorCompute> queryProjectIndicatorComputeList(QueryProjectIndicatorComputeDTO queryProjectIndicatorComputeDTO);
-    
+
     /**
-    * 分页查询
-    * 
-    * @param pageQueryProjectIndicatorComputeDTO pageQueryDTO
-    * @return IPage<ProjectIndicatorCompute>
-    * @author lixing
-    * @version V1.0 2021-09-21 13:32:54
-    */
+     * 分页查询
+     *
+     * @param pageQueryProjectIndicatorComputeDTO pageQueryDTO
+     * @return IPage<ProjectIndicatorCompute>
+     * @author lixing
+     * @version V1.0 2021-09-21 13:32:54
+     */
     public IPage<ProjectIndicatorCompute> pageQueryProjectIndicatorCompute(PageQueryProjectIndicatorComputeDTO pageQueryProjectIndicatorComputeDTO);
+
+    /**
+     * @title getProjectIdAndProjectCompute
+     * @description 获取map,key为项目id
+     * @author leifeng
+     * @updateTime 2021/9/21 14:28
+     * @return: java.util.Map<java.lang.String,com.persagy.apm.diagnose.indicatorcompute.model.ProjectIndicatorCompute>
+     * @throws
+     */
+    public Map<String, ProjectIndicatorCompute> getProjectIdAndProjectCompute();
 }

+ 12 - 25
src/main/java/com/persagy/apm/diagnose/indicatorcompute/service/impl/ProjectIndicatorComputeServiceImpl.java

@@ -11,6 +11,10 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.persagy.apm.diagnose.indicatorcompute.model.*;
 import com.persagy.apm.diagnose.indicatorcompute.model.dto.*;
 import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.google.common.base.CaseFormat;
@@ -36,25 +40,10 @@ public class ProjectIndicatorComputeServiceImpl extends ServiceImpl<ProjectIndic
     @Override
     public String createProjectIndicatorCompute(AddProjectIndicatorComputeDTO addProjectIndicatorComputeDTO) {
         ProjectIndicatorCompute projectIndicatorCompute = ConvertProjectIndicatorComputeTool.INSTANCE.convertAddDto2Entity(addProjectIndicatorComputeDTO);
-        // 设置默认值
-        setDefaultValue(projectIndicatorCompute);
         save(projectIndicatorCompute);
-        return projectIndicatorCompute.getId();
-    }
-    
-    /**
-     * 如果某些字段没有赋值,使用默认的值
-     *
-     * @param projectIndicatorCompute 实体
-     * @author lixing
-     * @version V1.0 2021/3/12 12:29 下午
-     */
-    private void setDefaultValue(ProjectIndicatorCompute projectIndicatorCompute) {
-        projectIndicatorCompute.setCreator(PoemsContext.getContext().getUserId());
-        // todo 其他默认的属性
-        
+        return null;
     }
-    
+
     /**
     * 详情
     * @param id 主键
@@ -80,7 +69,6 @@ public class ProjectIndicatorComputeServiceImpl extends ServiceImpl<ProjectIndic
     public void updateProjectIndicatorCompute(UpdateProjectIndicatorComputeDTO updateProjectIndicatorComputeDTO) {
         ProjectIndicatorCompute projectIndicatorCompute = getById(updateProjectIndicatorComputeDTO.getId());
         projectIndicatorCompute = ConvertProjectIndicatorComputeTool.INSTANCE.convertUpdateDto2Entity(projectIndicatorCompute, updateProjectIndicatorComputeDTO);
-        projectIndicatorCompute.setModifier(PoemsContext.getContext().getUserId());
         updateById(projectIndicatorCompute);
     }
     
@@ -116,8 +104,6 @@ public class ProjectIndicatorComputeServiceImpl extends ServiceImpl<ProjectIndic
     public void deleteProjectIndicatorCompute(String id) {
         // 校验是否可删除
         ProjectIndicatorCompute projectIndicatorCompute = checkDeletable(id);
-
-        projectIndicatorCompute.setValid(ValidEnum.FALSE.getType());
         updateById(projectIndicatorCompute);
     }
     
@@ -130,10 +116,7 @@ public class ProjectIndicatorComputeServiceImpl extends ServiceImpl<ProjectIndic
     @Override
     public List<ProjectIndicatorCompute> queryProjectIndicatorComputeList(QueryProjectIndicatorComputeDTO queryProjectIndicatorComputeDTO) {
         QueryWrapper<ProjectIndicatorCompute> queryWrapper = new QueryWrapper<>();
-        queryWrapper.eq(ProjectIndicatorCompute.PROP_VALID, ValidEnum.TRUE.getType());
         // 默认按创建时间倒序排序
-        queryWrapper.orderBy(true, false, ProjectIndicatorCompute.PROP_CREATIONTIME);
-        
         if (queryProjectIndicatorComputeDTO != null) {
                                 
             // todo 需判断使用like还是eq
@@ -163,13 +146,11 @@ public class ProjectIndicatorComputeServiceImpl extends ServiceImpl<ProjectIndic
     @Override
     public IPage<ProjectIndicatorCompute> pageQueryProjectIndicatorCompute(PageQueryProjectIndicatorComputeDTO pageQueryProjectIndicatorComputeDTO) {
         QueryWrapper<ProjectIndicatorCompute> queryWrapper = new QueryWrapper<>();
-        queryWrapper.eq(ProjectIndicatorCompute.PROP_VALID, ValidEnum.TRUE.getType());
         // 这里认为pageQueryDTO是经过校验的,肯定包含分页信息
         IPage<ProjectIndicatorCompute> pageParam = new Page<>(pageQueryProjectIndicatorComputeDTO.getPage(), pageQueryProjectIndicatorComputeDTO.getSize(),true);
         // 排序信息
         if(CollectionUtils.isEmpty(pageQueryProjectIndicatorComputeDTO.getOrders())){
             // 默认按创建时间倒序排序
-            queryWrapper.orderBy(true, false, ProjectIndicatorCompute.PROP_CREATIONTIME);
         }else {
             List<Sort> orders = pageQueryProjectIndicatorComputeDTO.getOrders();
             for(Sort sort: orders) {
@@ -194,4 +175,10 @@ public class ProjectIndicatorComputeServiceImpl extends ServiceImpl<ProjectIndic
                                     
         return getBaseMapper().selectPage(pageParam, queryWrapper);
     }
+
+    @Override
+    public Map<String, ProjectIndicatorCompute> getProjectIdAndProjectCompute() {
+        List<ProjectIndicatorCompute> projectIndicatorComputes = this.queryProjectIndicatorComputeList(new QueryProjectIndicatorComputeDTO());
+        return projectIndicatorComputes.stream().collect(Collectors.toMap(ProjectIndicatorCompute::getProjectId, Function.identity(),(key1, key2)->key2));
+    }
 }

+ 8 - 3
src/main/java/com/persagy/apm/diagnose/indicatorrecord/model/MonitorIndicatorRecord.java

@@ -1,5 +1,6 @@
 package com.persagy.apm.diagnose.indicatorrecord.model;
 
+import com.persagy.apm.common.model.entity.BaseEntity;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
@@ -13,14 +14,17 @@ import java.util.Date;
  * @author lixing
  * @version V1.0 2021-09-10 00:13:27
  */
-@EqualsAndHashCode(callSuper = true)
 @Data
 @ApiModel(description = "监测指标历史记录")
-public class MonitorIndicatorRecord extends AuditableEntity<MonitorIndicatorRecord> implements Serializable {
+public class MonitorIndicatorRecord implements Serializable {
     private static final long serialVersionUID = -42365400485581158L;
 
+
     @ApiModelProperty("对象id")
     private String objId;
+
+    @ApiModelProperty("项目id")
+    private String projectId;
     
     @ApiModelProperty("监测指标id")
     private String monitorIndicatorId;
@@ -29,12 +33,13 @@ public class MonitorIndicatorRecord extends AuditableEntity<MonitorIndicatorReco
     private Date date;
     
     @ApiModelProperty("值")
-    private String value;
+    private Double value;
     
 
     public static String PROP_OBJ_ID = "obj_id";
     public static String PROP_MONITOR_INDICATOR_ID = "monitor_indicator_id";
     public static String PROP_DATE = "date";
     public static String PROP_VALUE = "value";
+    public static String PROJECT_ID = "project_id";
 
 }

+ 31 - 0
src/main/java/com/persagy/apm/diagnose/indicatorrecord/service/IMonitorIndicatorRecordService.java

@@ -1,9 +1,14 @@
 package com.persagy.apm.diagnose.indicatorrecord.service;
 
+import com.persagy.apm.diagnose.indicatorcompute.model.ProjectIndicatorCompute;
 import com.persagy.apm.diagnose.indicatorrecord.model.*;
 import com.persagy.apm.diagnose.indicatorrecord.model.dto.*;
 import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Future;
+
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.persagy.apm.diagnose.service.dto.ProjectDTO;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 
@@ -72,4 +77,30 @@ public interface IMonitorIndicatorRecordService  {
     * @version V1.0 2021-09-10 00:13:27
     */
     public IPage<MonitorIndicatorRecord> pageQueryMonitorIndicatorRecord(PageQueryMonitorIndicatorRecordDTO pageQueryMonitorIndicatorRecordDTO);
+
+
+    /**
+     * @title computeIndicatorData
+     * @description 异步计算项目指标数据
+     * @author leifeng 
+     * @param: projectDTO
+     * @param: projectIndicatorCompute
+     * @param: latch
+     * @updateTime 2021/9/21 14:31 
+     * @return: java.util.concurrent.Future<java.lang.String>
+     * @throws 
+     */
+    Future<String> computeIndicatorData(ProjectDTO projectDTO, ProjectIndicatorCompute projectIndicatorCompute, CountDownLatch latch) throws Exception;
+
+    /**
+     * @title sendIndicatorData
+     * @description 异步发送指标数据
+     * @author leifeng
+     * @param: projectDTO
+     * @param: latch
+     * @updateTime 2021/9/25 16:32
+     * @return: java.util.concurrent.Future<java.lang.String>
+     * @throws
+     */
+    Future<String> sendIndicatorData(ProjectDTO projectDTO, CountDownLatch latch) throws Exception;
 }

+ 650 - 80
src/main/java/com/persagy/apm/diagnose/indicatorrecord/service/impl/MonitorIndicatorRecordServiceImpl.java

@@ -1,67 +1,135 @@
 package com.persagy.apm.diagnose.indicatorrecord.service.impl;
 
-import com.persagy.apm.common.context.AppContext;
-import com.persagy.apm.diagnose.indicatorrecord.dao.MonitorIndicatorRecordMapper;
-import com.persagy.apm.diagnose.indicatorrecord.service.IMonitorIndicatorRecordService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.stereotype.Service;
-import org.apache.commons.lang.StringUtils;
-import com.persagy.apm.common.constant.enums.ValidEnum;
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.persagy.apm.diagnose.indicatorrecord.model.*;
-import com.persagy.apm.diagnose.indicatorrecord.model.dto.*;
-import java.util.List;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.google.common.base.CaseFormat;
 import com.persagy.apm.common.model.dto.Sort;
+import com.persagy.apm.diagnose.constant.EnumDataTimeType;
+import com.persagy.apm.diagnose.constant.EnumTimeType;
+import com.persagy.apm.diagnose.indicatorcompute.model.ProjectIndicatorCompute;
+import com.persagy.apm.diagnose.indicatorcompute.model.dto.AddProjectIndicatorComputeDTO;
+import com.persagy.apm.diagnose.indicatorcompute.model.dto.UpdateProjectIndicatorComputeDTO;
+import com.persagy.apm.diagnose.indicatorcompute.service.IProjectIndicatorComputeService;
+import com.persagy.apm.diagnose.indicatorrecord.dao.MonitorIndicatorRecordMapper;
+import com.persagy.apm.diagnose.indicatorrecord.model.ConvertMonitorIndicatorRecordTool;
+import com.persagy.apm.diagnose.indicatorrecord.model.MonitorIndicatorRecord;
+import com.persagy.apm.diagnose.indicatorrecord.model.dto.*;
+import com.persagy.apm.diagnose.indicatorrecord.service.IMonitorIndicatorRecordService;
+import com.persagy.apm.diagnose.service.CenterDataService;
+import com.persagy.apm.diagnose.service.EnergyAlarmServiceImpl;
+import com.persagy.apm.diagnose.service.dto.CalculateMethodDTO;
+import com.persagy.apm.diagnose.service.dto.MonitorIndicatorConfigDTO;
+import com.persagy.apm.diagnose.service.dto.ProjectDTO;
+import com.persagy.apm.diagnose.service.dto.TimeDataDTO;
+import com.persagy.apm.diagnose.timerecord.model.CalculateTimeRecord;
+import com.persagy.apm.diagnose.timerecord.service.ICalculateTimeRecordService;
+import com.persagy.apm.diagnose.utils.*;
+import com.persagy.apm.energyalarmstarter.alarmdata.feign.DmpResult;
+import com.persagy.apm.energyalarmstarter.alarmdata.model.dto.AlarmCondition;
+import com.persagy.apm.energyalarmstarter.alarmdata.model.dto.alarmconfig.QueryAlarmConfigDTO;
+import com.persagy.apm.energyalarmstarter.alarmdata.model.vo.AlarmConfigItem;
+import com.persagy.apm.energyalarmstarter.alarmdata.service.AlarmConfigServiceImpl;
+import com.persagy.apm.energyalarmstarter.collectdata.websocket.AlarmWebSocketServer;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.AsyncResult;
+import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 
+import java.math.BigDecimal;
+import java.util.*;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Future;
+import java.util.stream.Collectors;
+
 /**
  * 监测指标历史记录(MonitorIndicatorRecord) service层
  *
  * @author lixing
  * @version V1.0 2021-09-10 00:13:27
  */
+@Slf4j
 @Service
-public class MonitorIndicatorRecordServiceImpl extends ServiceImpl<MonitorIndicatorRecordMapper, MonitorIndicatorRecord> 
-    implements IMonitorIndicatorRecordService {
-    
-    /**
-    * 创建监测指标历史记录
-    * @return 监测指标历史记录主键
-    * @author lixing
-    * @version V1.0 2021-09-10 00:13:27
-    */
+public class MonitorIndicatorRecordServiceImpl extends ServiceImpl<MonitorIndicatorRecordMapper, MonitorIndicatorRecord>
+        implements IMonitorIndicatorRecordService {
+
+    @Autowired
+    private RedisLock lockUtil;
+
+    @Autowired
+    private ICalculateTimeRecordService calculateTimeRecordService;
+
+
+    @Autowired
+    private AlarmConfigServiceImpl alarmConfigService;
+
+    @Autowired
+    private RedisUtil redisUtil;
+
+    @Autowired
+    private EnergyAlarmServiceImpl energyAlarmService;
+
+
+    @Autowired
+    private CenterDataService centerDataService;
+
+
+    @Value(value = "${energy.eq.run.compute.round.days:1}")
+    private Integer roundDays;
+
+
+    @Value(value = "${energy.eq.run.send.hour:1}")
+    private Integer sendDataHour;
+
+    private final static Long SendDataTimeKeyTime = 24 * 60 * 60 * 1000L;
+
+
+    private final static Long ConfigItemKeyTime = 60 * 60 * 1000L;
+
+
+    @Autowired
+    private IProjectIndicatorComputeService projectIndicatorComputeService;
+
+    /**
+     * 创建监测指标历史记录
+     *
+     * @return 监测指标历史记录主键
+     * @author lixing
+     */
     @Override
     public String createMonitorIndicatorRecord(AddMonitorIndicatorRecordDTO addMonitorIndicatorRecordDTO) {
         MonitorIndicatorRecord monitorIndicatorRecord = ConvertMonitorIndicatorRecordTool.INSTANCE.convertAddDto2Entity(addMonitorIndicatorRecordDTO);
         // 设置默认值
         setDefaultValue(monitorIndicatorRecord);
         save(monitorIndicatorRecord);
-        return monitorIndicatorRecord.getId();
+        return null;
     }
-    
+
     /**
      * 如果某些字段没有赋值,使用默认的值
      *
      * @param monitorIndicatorRecord 监测指标历史记录实体
      * @author lixing
-     * @version V1.0 2021/3/12 12:29 下午
      */
     private void setDefaultValue(MonitorIndicatorRecord monitorIndicatorRecord) {
-        monitorIndicatorRecord.setCreator(AppContext.getContext().getAccountId());
         // todo 其他默认的属性
-        
+
     }
-    
+
     /**
-    * 监测指标历史记录详情
-    * @param id 主键
-    * @return 部门do类
-    * @author lixing
-    * @version V1.0 2021-09-10 00:13:27
-    */
+     * 监测指标历史记录详情
+     *
+     * @param id 主键
+     * @return 部门do类
+     * @author lixing
+     */
     @Override
     public MonitorIndicatorRecord queryMonitorIndicatorRecordDetail(String id) {
         MonitorIndicatorRecord monitorIndicatorRecord = getById(id);
@@ -70,27 +138,25 @@ public class MonitorIndicatorRecordServiceImpl extends ServiceImpl<MonitorIndica
         }
         return monitorIndicatorRecord;
     }
-    
+
     /**
-    * 更新监测指标历史记录
-    * @author lixing
-    * @version V1.0 2021-09-10 00:13:27
-    */
+     * 更新监测指标历史记录
+     *
+     * @author lixing
+     */
     @Override
     public void updateMonitorIndicatorRecord(UpdateMonitorIndicatorRecordDTO updateMonitorIndicatorRecordDTO) {
         MonitorIndicatorRecord monitorIndicatorRecord = getById(updateMonitorIndicatorRecordDTO.getId());
         monitorIndicatorRecord = ConvertMonitorIndicatorRecordTool.INSTANCE.convertUpdateDto2Entity(monitorIndicatorRecord, updateMonitorIndicatorRecordDTO);
-        monitorIndicatorRecord.setModifier(AppContext.getContext().getAccountId());
         updateById(monitorIndicatorRecord);
     }
-    
+
     /**
      * 校验监测指标历史记录是否可删除
      *
      * @param id 监测指标历史记录主键
      * @return 监测指标历史记录do类
      * @author lixing
-     * @version V1.0 2021-09-10 00:13:27
      */
     public MonitorIndicatorRecord checkDeletable(String id) {
         if (id == null) {
@@ -105,105 +171,609 @@ public class MonitorIndicatorRecordServiceImpl extends ServiceImpl<MonitorIndica
 
         return monitorIndicatorRecord;
     }
-    
+
     /**
-    * 删除监测指标历史记录
-    * @param id 主键
-    * @author lixing
-    * @version V1.0 2021-09-10 00:13:27
-    */
+     * 删除监测指标历史记录
+     *
+     * @param id 主键
+     * @author lixing
+     */
     @Override
     public void deleteMonitorIndicatorRecord(String id) {
         // 校验是否可删除
         MonitorIndicatorRecord monitorIndicatorRecord = checkDeletable(id);
-
-        monitorIndicatorRecord.setValid(ValidEnum.FALSE.getType());
         updateById(monitorIndicatorRecord);
     }
-    
+
     /**
-    * 查询监测指标历史记录
-    * @return List<MonitorIndicatorRecord>
-    * @author lixing
-    * @version V1.0 2021-09-10 00:13:27
-    */
+     * 查询监测指标历史记录
+     *
+     * @return List<MonitorIndicatorRecord>
+     * @author lixing
+     */
     @Override
     public List<MonitorIndicatorRecord> queryMonitorIndicatorRecordList(QueryMonitorIndicatorRecordDTO queryMonitorIndicatorRecordDTO) {
         QueryWrapper<MonitorIndicatorRecord> queryWrapper = new QueryWrapper<>();
-        queryWrapper.eq(MonitorIndicatorRecord.PROP_VALID, ValidEnum.TRUE.getType());
         // 默认按创建时间倒序排序
-        queryWrapper.orderBy(true, false, MonitorIndicatorRecord.PROP_CREATIONTIME);
-        
+        queryWrapper.orderBy(true, false, MonitorIndicatorRecord.PROP_DATE);
+
         if (queryMonitorIndicatorRecordDTO != null) {
-                                
+
             // todo 需判断使用like还是eq
             if (StringUtils.isNotEmpty(queryMonitorIndicatorRecordDTO.getObjId())) {
                 queryWrapper.like(MonitorIndicatorRecord.PROP_OBJ_ID, queryMonitorIndicatorRecordDTO.getObjId());
             }
-                                        
+
             // todo 需判断使用like还是eq
             if (StringUtils.isNotEmpty(queryMonitorIndicatorRecordDTO.getMonitorIndicatorId())) {
                 queryWrapper.like(MonitorIndicatorRecord.PROP_MONITOR_INDICATOR_ID, queryMonitorIndicatorRecordDTO.getMonitorIndicatorId());
             }
-                                            
+
             if (queryMonitorIndicatorRecordDTO.getDate() != null) {
                 queryWrapper.eq(MonitorIndicatorRecord.PROP_DATE, queryMonitorIndicatorRecordDTO.getDate());
             }
-                                        
+
             // todo 需判断使用like还是eq
             if (StringUtils.isNotEmpty(queryMonitorIndicatorRecordDTO.getValue())) {
                 queryWrapper.like(MonitorIndicatorRecord.PROP_VALUE, queryMonitorIndicatorRecordDTO.getValue());
             }
-                                            
+
         }
-        
+
         return list(queryWrapper);
     }
-    
+
     /**
-    * 分页查询监测指标历史记录
-    * @return IPage<MonitorIndicatorRecord>
-    * @author lixing
-    * @version V1.0 2021-09-10 00:13:27
-    */
+     * 分页查询监测指标历史记录
+     *
+     * @return IPage<MonitorIndicatorRecord>
+     * @author lixing
+     */
     @Override
     public IPage<MonitorIndicatorRecord> pageQueryMonitorIndicatorRecord(PageQueryMonitorIndicatorRecordDTO pageQueryMonitorIndicatorRecordDTO) {
         QueryWrapper<MonitorIndicatorRecord> queryWrapper = new QueryWrapper<>();
-        queryWrapper.eq(MonitorIndicatorRecord.PROP_VALID, ValidEnum.TRUE.getType());
         // 这里认为pageQueryDTO是经过校验的,肯定包含分页信息
-        IPage<MonitorIndicatorRecord> pageParam = new Page<>(pageQueryMonitorIndicatorRecordDTO.getPage(), pageQueryMonitorIndicatorRecordDTO.getSize(),true);
+        IPage<MonitorIndicatorRecord> pageParam = new Page<>(pageQueryMonitorIndicatorRecordDTO.getPage(), pageQueryMonitorIndicatorRecordDTO.getSize(), true);
         // 排序信息
-        if(CollectionUtils.isEmpty(pageQueryMonitorIndicatorRecordDTO.getOrders())){
+        if (CollectionUtils.isEmpty(pageQueryMonitorIndicatorRecordDTO.getOrders())) {
             // 默认按创建时间倒序排序
-            queryWrapper.orderBy(true, false, MonitorIndicatorRecord.PROP_CREATIONTIME);
-        }else {
+            queryWrapper.orderBy(true, false, MonitorIndicatorRecord.PROP_DATE);
+        } else {
             List<Sort> orders = pageQueryMonitorIndicatorRecordDTO.getOrders();
-            for(Sort sort: orders) {
+            for (Sort sort : orders) {
                 // 将驼峰转换为下划线格式
-                sort.setColumn(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE,sort.getColumn()));
+                sort.setColumn(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, sort.getColumn()));
                 queryWrapper.orderBy(true, sort.isAsc(), sort.getColumn());
             }
         }
-                
+
         // todo 需判断使用like还是eq
         if (StringUtils.isNotEmpty(pageQueryMonitorIndicatorRecordDTO.getObjId())) {
             queryWrapper.like(MonitorIndicatorRecord.PROP_OBJ_ID, pageQueryMonitorIndicatorRecordDTO.getObjId());
         }
-                            
+
         // todo 需判断使用like还是eq
         if (StringUtils.isNotEmpty(pageQueryMonitorIndicatorRecordDTO.getMonitorIndicatorId())) {
             queryWrapper.like(MonitorIndicatorRecord.PROP_MONITOR_INDICATOR_ID, pageQueryMonitorIndicatorRecordDTO.getMonitorIndicatorId());
         }
-                            
+
         if (pageQueryMonitorIndicatorRecordDTO.getDate() != null) {
             queryWrapper.eq(MonitorIndicatorRecord.PROP_DATE, pageQueryMonitorIndicatorRecordDTO.getDate());
         }
-                            
+
         // todo 需判断使用like还是eq
         if (StringUtils.isNotEmpty(pageQueryMonitorIndicatorRecordDTO.getValue())) {
             queryWrapper.like(MonitorIndicatorRecord.PROP_VALUE, pageQueryMonitorIndicatorRecordDTO.getValue());
         }
-                                    
         return getBaseMapper().selectPage(pageParam, queryWrapper);
     }
+
+    @Override
+    @Async("asyncComputeDataExecutor")
+    public Future<String> computeIndicatorData(ProjectDTO projectDTO, ProjectIndicatorCompute projectIndicatorCompute, CountDownLatch latch) throws Exception {
+        long time = System.currentTimeMillis() + (20 * 1000);
+        if (!lockUtil.lock(projectDTO.getProjectId(), String.valueOf(time))) {
+            // 获取不到锁,略过
+            return new AsyncResult<>("【监测指标数据计算线程】项目:" + projectDTO.getProjectId() + "被占用");
+        }
+        long start = System.currentTimeMillis();
+        AsyncResult<String> projectDTO1 = computeProjectIndicatorData(projectDTO, projectIndicatorCompute);
+        if (projectDTO1 != null) {
+            return projectDTO1;
+        }
+        // 释放锁
+        lockUtil.unlock(projectDTO.getProjectId(), String.valueOf(time));
+        latch.countDown();
+        long end = System.currentTimeMillis();
+        return new AsyncResult<>("【监测指标数据计算线程】计算项目指标数据用时:" + projectDTO.getProjectId() + ";" + (end - start));
+    }
+
+    private AsyncResult<String> computeProjectIndicatorData(ProjectDTO projectDTO, ProjectIndicatorCompute projectIndicatorCompute) throws Exception {
+        Object hget = redisUtil.hget(RedisUtil.TargetComputeTime, projectDTO.getProjectId());
+        if (hget != null && projectIndicatorCompute != null
+                && projectIndicatorCompute.getComputeRound() < Long.parseLong(hget.toString())) {
+            return new AsyncResult<>("【监测指标数据计算线程】当前项目:" + projectDTO.getProjectId() + "被占用");
+        }
+        //通过报警服务查询报警配置
+        List<AlarmConfigItem> configItemList = getAlarmConfigItemList(projectDTO.getProjectId());
+        if (CollectionUtils.isEmpty(configItemList)) {
+            return new AsyncResult<>("【监测指标数据计算线程】当前项目:" + projectDTO.getProjectId() + "为查询到报警条件");
+        }
+        Set<String> objIdSet = configItemList.stream().map(AlarmConfigItem::getObjId).collect(Collectors.toSet());
+
+        List<JSONObject> objectList = centerDataService.queryObjListByObjId(projectDTO.getProjectId(), new ArrayList<>(objIdSet));
+        if (CollectionUtils.isEmpty(objectList)) {
+            return new AsyncResult<>("【监测指标数据计算线程】当前项目:" + projectDTO.getProjectId() + "查询项目下无设备对象");
+        }
+        Map<String, JSONObject> objIdAndObj = new HashMap<>();
+        for (JSONObject obj : objectList) {
+            objIdAndObj.put(obj.getString("id"), obj);
+        }
+
+        Map<String, Date> objId_indicatorIdAndComputeTIme = getObjId_IndicatorIdAndComputeTIme(projectDTO);
+
+        Map<String, CalculateMethodDTO> methodIdAndMethodDTO = energyAlarmService.queryCalculateMethods();
+
+        Map<String, String> objId_IndicatorAndCaculateMethodId = getObjId_IndicatorAndCaculateMethodIdMap(projectDTO);
+
+
+        //根据报警条件查询监测对象
+        for (AlarmConfigItem configItem : configItemList) {
+            String objId = configItem.getObjId();
+            AlarmCondition condition = configItem.getCondition();
+            List<String> infoCodeList = condition.getInfoCode();
+            if (CollectionUtils.isEmpty(infoCodeList)) {
+                continue;
+            }
+            JSONObject obj = objIdAndObj.get(objId);
+            if (obj == null) {
+                continue;
+            }
+            //处理监控指标
+            for (String infocode : infoCodeList) {
+                if (!objId_IndicatorAndCaculateMethodId.containsKey(infocode)) {
+                    //监控指标未设置公式
+                    log.error("【监测指标数据计算线程】:监控指标未设置公式:" + infocode);
+                    continue;
+                }
+                String caculateMethodId = objId_IndicatorAndCaculateMethodId.get(infocode);
+                if (StringUtils.isEmpty(caculateMethodId)) {
+                    log.error("【监测指标数据计算线程】:监控指标未设置公式:" + infocode);
+                    continue;
+                }
+                CalculateMethodDTO calculateMethodDTO = methodIdAndMethodDTO.get(caculateMethodId);
+                if (calculateMethodDTO == null) {
+                    log.error("【监测指标数据计算线程】:监控指标未设置公式为null:" + infocode);
+                    continue;
+                }
+
+                Date lastComputeTime = objId_indicatorIdAndComputeTIme.get(infocode);
+                Date computeEndTime = DateUtils.addDays(lastComputeTime, roundDays);
+
+                String indicatorId = getIndicatorIdFromInfocode(infocode);
+                String formula = calculateMethodDTO.getFormula();
+                computeIndicatorData(projectDTO, obj, lastComputeTime, computeEndTime, indicatorId, formula);
+            }
+        }
+        // 更新缓存计算轮次
+        updateProjectComputeRound(projectDTO.getProjectId(), projectIndicatorCompute);
+        return null;
+    }
+
+    @Override
+    @Async("asyncSendDataExecutor")
+    public Future<String> sendIndicatorData(ProjectDTO projectDTO, CountDownLatch latch) throws Exception {
+        long time = System.currentTimeMillis() + (20 * 1000);
+        if (!lockUtil.lock(projectDTO.getProjectId() + "_sendData", String.valueOf(time))) {
+            // 获取不到锁,略过
+            return new AsyncResult<>("发送指标数据:项目:" + projectDTO.getProjectId() + "被占用");
+        }
+        sendIndicatorDataToAlarmServer(projectDTO);
+        // 释放锁
+        lockUtil.unlock(projectDTO.getProjectId() + "_sendData", String.valueOf(time));
+        latch.countDown();
+        return new AsyncResult<>("Task2 accomplished!");
+    }
+
+    private void sendIndicatorDataToAlarmServer(ProjectDTO projectDTO) throws Exception {
+        //通过报警服务查询报警配置
+        List<AlarmConfigItem> configItemList = getAlarmConfigItemList(projectDTO.getProjectId());
+        if (CollectionUtils.isEmpty(configItemList)) {
+            log.error("【发送监测指标数据线程】当前项目:" + projectDTO.getProjectId() + "为查询到报警条件");
+        }
+        for (AlarmConfigItem alarmConfigItem : configItemList) {
+            ConfigItemDataSendTimeDTO configItemSendTimeDTO = getConfigItemSendTimeDTO(projectDTO, alarmConfigItem);
+            Date lastSendTime = configItemSendTimeDTO.getLastSendTime();
+            AlarmCondition condition = alarmConfigItem.getCondition();
+            if (condition == null) {
+                continue;
+            }
+            List<String> infoCodes = condition.getInfoCode();
+            if (CollectionUtils.isEmpty(infoCodes)) {
+                continue;
+            }
+            Date endTime = getSendEndTiem(lastSendTime);
+            List<MonitorIndicatorRecord> list = getMonitorIndicatorRecordsGtLte(projectDTO, alarmConfigItem, lastSendTime, infoCodes, endTime);
+            if (CollectionUtils.isEmpty(list)) {
+                continue;
+            }
+
+
+            Map<Date, List<MonitorIndicatorRecord>> timeAndIndicatorDataList = list.stream().collect(Collectors.groupingBy(MonitorIndicatorRecord::getDate, Collectors.toList()));
+            for (Map.Entry<Date, List<MonitorIndicatorRecord>> dateListEntry : timeAndIndicatorDataList.entrySet()) {
+                List<MonitorIndicatorRecord> value = dateListEntry.getValue();
+                if (CollectionUtils.isEmpty(value) || value.size() != infoCodes.size()) {
+                    continue;
+                }
+                AlarmWebSocketServer.sendMsgToClients(projectDTO.getProjectId(), CollectDataUtil.buildSendParam(value));
+            }
+            configItemSendTimeDTO.setLastSendTime(endTime);
+            updateRedisConfigItemSendTimeDTO(projectDTO.getProjectId(), configItemSendTimeDTO);
+        }
+    }
+
+    private Date getSendEndTiem(Date lastSendTime) {
+        Date date = DateUtils.addHours(lastSendTime, sendDataHour);
+        if (date.getTime() > System.currentTimeMillis()) {//大于当前时间
+            return new Date();
+        }
+        return date;
+    }
+
+    /**
+     * @title getMonitorIndicatorRecordsGtLte
+     * @description 根据项目, 对象id, 指标id, 数据时间查询指标数据list
+     * @author leifeng
+     * @param: projectDTO
+     * @param: alarmConfigItem
+     * @param: lastSendTime
+     * @param: infoCodes
+     * @param: endTime
+     * @updateTime 2021/9/25 20:08
+     * @return: java.util.List<com.persagy.apm.diagnose.indicatorrecord.model.MonitorIndicatorRecord>
+     */
+    private List<MonitorIndicatorRecord> getMonitorIndicatorRecordsGtLte(ProjectDTO projectDTO, AlarmConfigItem alarmConfigItem, Date lastSendTime, List<String> infoCodes, Date endTime) {
+        QueryWrapper<MonitorIndicatorRecord> queryWrapper = new QueryWrapper<>();
+        queryWrapper.eq(MonitorIndicatorRecord.PROJECT_ID, projectDTO.getProjectId());
+        queryWrapper.eq(MonitorIndicatorRecord.PROP_OBJ_ID, alarmConfigItem.getObjId());
+        queryWrapper.in(MonitorIndicatorRecord.PROP_MONITOR_INDICATOR_ID, infoCodes);
+        queryWrapper.ge(MonitorIndicatorRecord.PROP_DATE, lastSendTime);
+        queryWrapper.lt(true, MonitorIndicatorRecord.PROP_DATE, endTime);
+        queryWrapper.orderByAsc(MonitorIndicatorRecord.PROP_DATE);
+        return list(queryWrapper);
+    }
+
+    /**
+     * @title getConfigItemSendTimeDTO
+     * @description redis中查询报警条件上次发数时间, 如果查询为空, 则初始化当前时间
+     * @author leifeng
+     * @param: projectDTO
+     * @param: alarmConfigItem
+     * @updateTime 2021/9/25 20:03
+     * @return: com.persagy.apm.diagnose.indicatorrecord.model.dto.ConfigItemDataSendTimeDTO
+     */
+    private ConfigItemDataSendTimeDTO getConfigItemSendTimeDTO(ProjectDTO projectDTO, AlarmConfigItem alarmConfigItem) throws Exception {
+        ConfigItemDataSendTimeDTO sendTimeDTO = (ConfigItemDataSendTimeDTO) redisUtil.hget(RedisUtil.PROJECT_ITEM_SEND_TIME + ":" + projectDTO.getProjectId(), alarmConfigItem.getId());
+        if (sendTimeDTO == null) {
+            //第一次发送
+            sendTimeDTO = ConfigItemDataSendTimeDTO.builder().objId(alarmConfigItem.getObjId()).configItemid(alarmConfigItem.getId()).lastSendTime(DateUtils.getStartTimeOfDay(new Date())).build();
+        }
+        return sendTimeDTO;
+    }
+
+    /**
+     * @title updateRedisConfigItemSendTimeDTO
+     * @description 更新缓存中报警配置发数时间
+     * @author leifeng
+     * @param: projectId
+     * @param: sendTimeDTO
+     * @updateTime 2021/9/25 20:05
+     */
+    private void updateRedisConfigItemSendTimeDTO(String projectId, ConfigItemDataSendTimeDTO sendTimeDTO) {
+        redisUtil.hset(RedisUtil.PROJECT_ITEM_SEND_TIME + ":" + projectId, sendTimeDTO.getConfigItemid(), sendTimeDTO, SendDataTimeKeyTime);
+    }
+
+    /**
+     * @title updateProjectComputeRound
+     * @description 更新项目计算轮次
+     * @author leifeng
+     * @param: projectId
+     * @param: projectCompute
+     * @updateTime 2021/9/25 20:08
+     */
+    private void updateProjectComputeRound(String projectId, ProjectIndicatorCompute projectCompute) {
+        Integer round = 1;
+        if (projectCompute == null) {
+            AddProjectIndicatorComputeDTO addProjectIndicatorComputeDTO = new AddProjectIndicatorComputeDTO();
+            addProjectIndicatorComputeDTO.setProjectId(projectId);
+            addProjectIndicatorComputeDTO.setComputeRound(1);
+            addProjectIndicatorComputeDTO.setComputeTime(new Date());
+            projectIndicatorComputeService.createProjectIndicatorCompute(addProjectIndicatorComputeDTO);
+        } else {
+            UpdateProjectIndicatorComputeDTO updateProjectIndicatorComputeDTO = new UpdateProjectIndicatorComputeDTO();
+            updateProjectIndicatorComputeDTO.setComputeRound(round = getComputeRound(projectCompute.getComputeRound()));
+            updateProjectIndicatorComputeDTO.setProjectId(projectCompute.getProjectId());
+            updateProjectIndicatorComputeDTO.setComputeTime(new Date());
+            projectIndicatorComputeService.updateProjectIndicatorCompute(updateProjectIndicatorComputeDTO);
+        }
+        redisUtil.hset(RedisUtil.TargetComputeTime, projectId, round.toString());
+    }
+
+
+    /**
+     * @title getComputeRound
+     * @description 获取计算轮次
+     * @author leifeng
+     * @param: computeRound
+     * @updateTime 2021/9/25 20:09
+     * @return: java.lang.Integer
+     */
+    private Integer getComputeRound(Integer computeRound) {
+        if (computeRound > 10000000) {
+            return 1;
+        }
+        return ++computeRound;
+    }
+
+
+    /**
+     * @title computeIndicatorData
+     * @description 计算指标数据
+     * @author leifeng
+     * @param: projectDTO
+     * @param: obj
+     * @param: lastComputeTime
+     * @param: computeEndTime
+     * @param: indicatorId
+     * @param: formula
+     * @updateTime 2021/9/25 20:11
+     */
+    private void computeIndicatorData(ProjectDTO projectDTO, JSONObject obj, Date lastComputeTime, Date computeEndTime, String indicatorId, String formula) throws Exception {
+        ComputeCalculateDTO computeCalculateDTO = new ComputeCalculateDTO();
+        computeCalculateDTO.setObj(obj);
+        computeCalculateDTO.setProjectId(projectDTO.getProjectId());
+        computeCalculateDTO.setTargetId(indicatorId);
+        Map<String, Double> timeDataMap = TimeDataUtil.getTimeDataMap(lastComputeTime, computeEndTime,
+                EnumTimeType.MIN15);
+        for (Map.Entry<String, Double> entry : timeDataMap.entrySet()) {
+            Double targetData;
+            Date dataTime = DateUtils.str2Date(entry.getKey(), DateUtils.SDF_SECOND);
+            if (dataTime.getTime() > System.currentTimeMillis()) {
+                break;
+            }
+            computeCalculateDTO.setDataTime(dataTime);
+            targetData = computeObjTargetDataByCalculate(computeCalculateDTO, formula);
+            if (targetData == null) {
+                break;
+            }
+            MonitorIndicatorRecord monitorIndicatorRecord = new MonitorIndicatorRecord();
+            monitorIndicatorRecord.setMonitorIndicatorId(indicatorId);
+            monitorIndicatorRecord.setDate(dataTime);
+            monitorIndicatorRecord.setObjId(obj.getString("id"));
+            monitorIndicatorRecord.setProjectId(projectDTO.getProjectId());
+            saveOrUpdate(monitorIndicatorRecord);
+        }
+    }
+
+    private String getIndicatorIdFromInfocode(String infocode) {
+        int lastIndex = infocode.lastIndexOf("_");
+        return infocode.substring(lastIndex);
+    }
+
+    /**
+     * @ClassName MonitorIndicatorRecordServiceImpl
+     * @author leifeng
+     * @Description 查询项目下对象指标计算时间
+     * @createTime 2021/9/24 11:22
+     */
+    private Map<String, Date> getObjId_IndicatorIdAndComputeTIme(ProjectDTO projectDTO) {
+        List<CalculateTimeRecord> calculateTimeRecords = calculateTimeRecordService.queryTimeRecordListByProjectId(projectDTO.getProjectId());
+        return calculateTimeRecords.stream().collect(Collectors.toMap(a -> a.getObjId() + "_" + a.getMonitorIndicatorId(), CalculateTimeRecord::getCalculateLastTime));
+    }
+
+    /**
+     * @title getObjId_IndicatorAndCaculateMethodIdMap
+     * @description 查询对象id与指标id的计算公式关系, key为objId_indicatorId, value为计算公式id
+     * @author leifeng
+     * @param: projectDTO
+     * @updateTime 2021/9/24 11:26
+     * @return: java.util.Map<java.lang.String, java.lang.String>
+     */
+    private Map<String, String> getObjId_IndicatorAndCaculateMethodIdMap(ProjectDTO projectDTO) throws Exception {
+        List<MonitorIndicatorConfigDTO> monitorIndicatorConfigDTOS = energyAlarmService.queryMonitorIndicatorConfigDTOList(projectDTO.getProjectId());
+        return monitorIndicatorConfigDTOS.stream().collect(Collectors.toMap(a -> a.getObjId() + "_" + a.getMonitorIndicatorId(), MonitorIndicatorConfigDTO::getCaculateMethodId));
+    }
+
+    /**
+     * @title getAlarmConfigItemList
+     * @description 从缓存中获取报警条件, 如果缓存不存在, 则查询报警服务, 报警条件配置
+     * @author leifeng
+     * @param: projectDTO
+     * @updateTime 2021/9/24 11:27
+     * @return: java.util.List<com.persagy.apm.energyalarmstarter.alarmdata.model.vo.AlarmConfigItem>
+     */
+    private List<AlarmConfigItem> getAlarmConfigItemList(String projectId) throws Exception {
+        List<AlarmConfigItem> itemList = (List<AlarmConfigItem>) redisUtil.hget(RedisUtil.PROJECT_ALARM_ITEM, projectId);
+        if (CollectionUtils.isEmpty(itemList)) {
+            QueryAlarmConfigDTO queryAlarmConfigDTO = new QueryAlarmConfigDTO();
+            queryAlarmConfigDTO.setProjectId(projectId);
+            queryAlarmConfigDTO.setGroupCode("WD");
+            queryAlarmConfigDTO.setCategory(Collections.singletonList("run"));
+            queryAlarmConfigDTO.setOpen(1);
+            DmpResult<List<AlarmConfigItem>> configItemResult = alarmConfigService.query(queryAlarmConfigDTO);
+            itemList = DmpResultUtil.getData(configItemResult);
+            redisUtil.hset(RedisUtil.PROJECT_ALARM_ITEM, projectId, itemList, ConfigItemKeyTime);
+        }
+        return itemList;
+    }
+
+
+    private Double computeObjTargetDataByCalculate(ComputeCalculateDTO computeCalculateDTO, String calculateStr)
+            throws Exception {
+        List<String> variables = CalculateUtil.getVariablesFromFormula(calculateStr);
+        Map<String, Double> variableAndData = new HashMap<>();
+        for (String variable : variables) {
+            String v = variable.substring(2, variable.length() - 1);// 获取${}中变量
+            // 解析变量
+            Double data = null;
+            if (v.startsWith(CalculateUtil.SUM)) {// 求和
+                v = v.substring(4, v.length() - 1);
+                computeCalculateDTO.setCalculateVariableDTO(CalculateVariableDTO.buildCalculateVariableDTO(v));
+                List<Double> dataList = analysisVariable(computeCalculateDTO);
+                data = getSumDataFromDataList(dataList);
+            } else if (v.startsWith(CalculateUtil.MIN)) {// 求最小值
+                v = v.substring(4, v.length() - 1);
+                computeCalculateDTO.setCalculateVariableDTO(CalculateVariableDTO.buildCalculateVariableDTO(v));
+                List<Double> analysisVariable = analysisVariable(computeCalculateDTO);
+
+                data = getMinDataFromDataList(analysisVariable);
+            } else {
+                computeCalculateDTO.setCalculateVariableDTO(CalculateVariableDTO.buildCalculateVariableDTO(v));
+                List<Double> analysisVariable = analysisVariable(computeCalculateDTO);
+                if (!CollectionUtils.isEmpty(analysisVariable)) {
+                    data = analysisVariable.get(0);
+                }
+            }
+            variableAndData.put(variable, data);
+            if (data == null) {
+                break;
+            }
+        }
+        for (Map.Entry<String, Double> entry : variableAndData.entrySet()) {
+            if (entry.getValue() == null) {
+                return null;
+            }
+            calculateStr = calculateStr.replace(entry.getKey(), variableAndData.get(entry.getKey()).toString());
+        }
+        BigDecimal result = new ComputeFormulaUtil(calculateStr).getResult();
+        if (result == null) {
+            log.error("【监测指标数据计算线程】:解析公式为空,projectId:" + computeCalculateDTO.getProjectId() + "对象id:"
+                    + computeCalculateDTO.getObj().getString("id") + ";指标id:" + computeCalculateDTO.getTargetId()
+                    + ";带入公式:" + calculateStr);
+            return null;
+        }
+        return result.doubleValue();
+    }
+
+    private Double getMinDataFromDataList(List<Double> analysisVariable) {
+        if (CollectionUtils.isEmpty(analysisVariable)) {
+            return null;
+        }
+        Double data = null;
+        for (Double double1 : analysisVariable) {
+            if (double1 == null) {
+                continue;
+            }
+            if (double1 == 0.0) {
+                continue;
+            }
+            data = data == null ? double1 : data > double1 ? double1 : data;
+        }
+        return data;
+    }
+
+    private Double getSumDataFromDataList(List<Double> dataList) {
+        double data = 0.0;
+        if (CollectionUtils.isEmpty(dataList)) {
+            return null;
+        }
+        for (Double double1 : dataList) {
+            if (double1 == null) {
+                return null;
+            }
+            data += double1;
+        }
+        return data;
+    }
+
+    private List<Double> analysisVariable(ComputeCalculateDTO computeCalculateDTO) throws Exception {
+        CalculateVariableDTO calculateVariableDTO = computeCalculateDTO.getCalculateVariableDTO();
+        if (calculateVariableDTO.getComputeObjType().equals(CalculateUtil.OBJTYPE)) {
+            // 当前对象
+            return computeObjDataByComputeCalculateDTO(computeCalculateDTO);
+        } else {
+            List<JSONObject> objList = centerDataService.queryObjRelationList(CenterDataUtil.getObjRelationDataDTO(
+                    computeCalculateDTO.getProjectId(), calculateVariableDTO.getComputeObjType(),
+                    computeCalculateDTO.getObj().getString("id"), null));
+            if (CollectionUtils.isEmpty(objList)) {
+                log.error("【指标计算线程】:查询数据中台子对象为空,projectId:" + computeCalculateDTO.getProjectId() + ";objId:"
+                        + computeCalculateDTO.getObj().getString("id") + ";子对象类型:"
+                        + calculateVariableDTO.getComputeObjType());
+                return null;
+            }
+            List<Double> list = new ArrayList<>();
+            for (JSONObject object : objList) {
+                ComputeCalculateDTO computeCalculateDTO2 = new ComputeCalculateDTO();
+                BeanUtils.copyProperties(computeCalculateDTO2, computeCalculateDTO);
+                computeCalculateDTO2.setObj(object);
+                List<Double> queryDataList = computeObjDataByComputeCalculateDTO(computeCalculateDTO2);
+                list.addAll(queryDataList);
+            }
+            return list;
+        }
+    }
+
+    private List<Double> computeObjDataByComputeCalculateDTO(ComputeCalculateDTO computeCalculateDTO) throws
+            Exception {
+        CalculateVariableDTO calculateVariableDTO = computeCalculateDTO.getCalculateVariableDTO();
+        String computeCode = calculateVariableDTO.getComputeCode();
+        String computeType = calculateVariableDTO.getComputeType();
+        String time = calculateVariableDTO.getTime();
+        String timeType = calculateVariableDTO.getTimeType();
+        Date startTime = CalculateUtil.getStartTime(time, computeCalculateDTO.getDataTime());
+        if (computeType.equals(CalculateUtil.InfoCode)) {
+            // 查询数据中台信息点数据
+            if (time.equals(CalculateUtil.invalidTime)) {
+                // 查询静态信息点
+                return getObjStaticDataFromCenterData(computeCalculateDTO.getObj(), computeCode);
+            } else {
+                assert startTime != null;
+                return getServiceDataFromCenterDataService(computeCalculateDTO.getProjectId(),
+                        computeCalculateDTO.getObj().getString("id"), computeCode, timeType, startTime,
+                        DateUtils.addMinutes(startTime, 1));
+            }
+        } else {
+            // 查询指标数据
+            List<Double> result = new ArrayList<>();
+            QueryWrapper<MonitorIndicatorRecord> queryWrapper = new QueryWrapper<>();
+            queryWrapper.eq(MonitorIndicatorRecord.PROJECT_ID, computeCalculateDTO.getProjectId());
+            queryWrapper.eq(MonitorIndicatorRecord.PROP_OBJ_ID, computeCalculateDTO.getObj().getString("id"));
+            queryWrapper.eq(MonitorIndicatorRecord.PROP_MONITOR_INDICATOR_ID, computeCode);
+            queryWrapper.eq(MonitorIndicatorRecord.PROP_DATE, startTime);
+            List<MonitorIndicatorRecord> list = list(queryWrapper);
+            if (CollectionUtils.isEmpty(list)) {
+                return result;
+            }
+            result.add(list.get(0).getValue());
+            return result;
+        }
+    }
+
+    private List<Double> getObjStaticDataFromCenterData(JSONObject obj, String computeCode) {
+        List<Double> arrayList = new ArrayList<>();
+        Double double1 = obj.getDouble(computeCode);
+        if (double1 == null) {
+            log.error("【指标数据计算线程】:查询数据中台对象静态数据为空,:objId:" + obj.getString("id") + ";信息点:" + computeCode);
+        }
+        arrayList.add(double1);
+        return arrayList;
+    }
+
+    private List<Double> getServiceDataFromCenterDataService(String projectId, String objId, String computeCode,
+                                                             String timeType, Date startTime, Date startTime2) throws Exception {
+        List<TimeDataDTO> dataList = centerDataService.queryObjTimeDataList(projectId, objId, computeCode, startTime,
+                startTime2, EnumDataTimeType.getEnumDataTimeType(timeType));
+        List<Double> result = new ArrayList<>();
+        if (!CollectionUtils.isEmpty(dataList)) {
+            for (TimeDataDTO data : dataList) {
+                result.add(data.getData());
+            }
+        }
+        if (CollectionUtils.isEmpty(result)) {
+            log.error("【指标计算线程】:查询数据中台对象历史数据为空,projectId:" + projectId + ";objId:" + objId + ";信息点:" + computeCode
+                    + ";时间:" + DateUtils.date2Str(startTime, DateUtils.SDF_SECOND) + "_"
+                    + DateUtils.date2Str(startTime2, DateUtils.SDF_SECOND));
+        }
+        return result;
+    }
 }

+ 4 - 1
src/main/java/com/persagy/apm/diagnose/timerecord/model/CalculateTimeRecord.java

@@ -19,6 +19,9 @@ import java.util.Date;
 public class CalculateTimeRecord extends AuditableEntity<CalculateTimeRecord> implements Serializable {
     private static final long serialVersionUID = -77453694266690779L;
 
+    @ApiModelProperty("项目id")
+    private String projectId;
+
     @ApiModelProperty("对象id")
     private String objId;
     
@@ -27,9 +30,9 @@ public class CalculateTimeRecord extends AuditableEntity<CalculateTimeRecord> im
     
     @ApiModelProperty("上次计算时间")
     private Date calculateLastTime;
-    
 
     public static String PROP_OBJ_ID = "obj_id";
+    public static String PROJECT_ID = "project_id";
     public static String PROP_MONITOR_INDICATOR_ID = "monitor_indicator_id";
     public static String PROP_CALCULATE_LAST_TIME = "calculate_last_time";
 

+ 4 - 0
src/main/java/com/persagy/apm/diagnose/timerecord/model/dto/QueryCalculateTimeRecordDTO.java

@@ -12,6 +12,10 @@ import java.util.Date;
 @Data
 @ApiModel(value = "查询监测指标计算时间入参")
 public class QueryCalculateTimeRecordDTO {
+
+    @ApiModelProperty(value = "项目id", required = true)
+    private String projectId;
+
     @ApiModelProperty(value = "对象id", required = true)
     private String objId;
     

+ 11 - 0
src/main/java/com/persagy/apm/diagnose/timerecord/service/ICalculateTimeRecordService.java

@@ -72,4 +72,15 @@ public interface ICalculateTimeRecordService  {
     * @version V1.0 2021-09-10 00:13:10
     */
     public IPage<CalculateTimeRecord> pageQueryCalculateTimeRecord(PageQueryCalculateTimeRecordDTO pageQueryCalculateTimeRecordDTO);
+
+/**
+ * @title queryTimeRecordListByProjectId
+ * @description 通过项目id查询项目下所有计算指标时间
+ * @author leifeng
+ * @param: projectId
+ * @updateTime 2021/9/21 14:48
+ * @return: java.util.List<CalculateTimeRecord>
+ * @throws
+ */
+    public List<CalculateTimeRecord> queryTimeRecordListByProjectId(String projectId);
 }

+ 7 - 0
src/main/java/com/persagy/apm/diagnose/timerecord/service/impl/CalculateTimeRecordServiceImpl.java

@@ -196,4 +196,11 @@ public class CalculateTimeRecordServiceImpl extends ServiceImpl<CalculateTimeRec
                                     
         return getBaseMapper().selectPage(pageParam, queryWrapper);
     }
+
+    @Override
+    public List<CalculateTimeRecord> queryTimeRecordListByProjectId(String projectId) {
+        QueryWrapper<CalculateTimeRecord> queryWrapper = new QueryWrapper<>();
+        queryWrapper.eq(CalculateTimeRecord.PROJECT_ID, projectId);
+        return list(queryWrapper);
+    }
 }

+ 1 - 1
src/main/resources/bootstrap.yml

@@ -1,6 +1,6 @@
 server:
   port:
-    9978
+    8080
 spring:
   application:
     name: energy_eq_run_diagnose