55 changed files with 2185 additions and 65 deletions
@ -0,0 +1,76 @@
|
||||
package com.mh.web.controller.monitor; |
||||
|
||||
import com.mh.common.core.controller.BaseController; |
||||
import com.mh.common.core.page.TableDataInfo; |
||||
import com.mh.system.service.overview.HomeService; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.web.bind.annotation.GetMapping; |
||||
import org.springframework.web.bind.annotation.RequestMapping; |
||||
import org.springframework.web.bind.annotation.RestController; |
||||
|
||||
/** |
||||
* @author LJF |
||||
* @version 1.0 |
||||
* @project EEMCS |
||||
* @description 新增首页监控 |
||||
* @date 2026-06-05 10:14:39 |
||||
*/ |
||||
@RestController |
||||
@RequestMapping("/home") |
||||
public class HomeController extends BaseController { |
||||
|
||||
@Autowired |
||||
HomeService homeService; |
||||
|
||||
/** |
||||
* 主界面图表 |
||||
* @return |
||||
*/ |
||||
@GetMapping("/charts") |
||||
public TableDataInfo getHomeCharts(){ |
||||
return homeService.getHomeCharts(); |
||||
} |
||||
|
||||
/** |
||||
* 查询日供冷量、月供冷量、年供冷量 |
||||
* 日、月、年、累计EER |
||||
* 累计供冷量 |
||||
* @return |
||||
*/ |
||||
@GetMapping("/statical") |
||||
public TableDataInfo getStatisticalData(){ |
||||
return homeService.getStatisticalData(); |
||||
} |
||||
|
||||
/** |
||||
* 查询能耗系数 |
||||
* @return |
||||
*/ |
||||
@GetMapping("/getCoe") |
||||
public TableDataInfo getCoe(){ |
||||
return homeService.getCoe(); |
||||
} |
||||
|
||||
/** |
||||
* 查询系统运行时长 |
||||
* @return |
||||
*/ |
||||
@GetMapping("/getRunTime") |
||||
public TableDataInfo getRunTime(){ |
||||
return homeService.getRunTime(); |
||||
} |
||||
|
||||
/** |
||||
* 获取实时功率 |
||||
* @return |
||||
*/ |
||||
@GetMapping("/getCurrentRate") |
||||
public TableDataInfo getCurrentRate(){ |
||||
return homeService.getCurrentRate(); |
||||
} |
||||
|
||||
@GetMapping("/getWeatherData") |
||||
public TableDataInfo getWeatherData() { |
||||
return homeService.getWeatherData(); |
||||
} |
||||
} |
||||
@ -0,0 +1,15 @@
|
||||
package com.mh.common.constant; |
||||
|
||||
import java.text.SimpleDateFormat; |
||||
|
||||
/** |
||||
* @Author : Rainbow |
||||
* @date : 2023/7/10 |
||||
*/ |
||||
public class DateConstant { |
||||
public final static SimpleDateFormat DAY_SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
||||
public final static SimpleDateFormat MONTH = new SimpleDateFormat("yyyy-MM"); |
||||
public final static SimpleDateFormat DAY = new SimpleDateFormat("yyyy-MM-dd"); |
||||
public final static SimpleDateFormat MONTH_SDF = new SimpleDateFormat("yyyy-MM-dd"); |
||||
public final static SimpleDateFormat YEAR_SDF = new SimpleDateFormat("yyyy"); |
||||
} |
||||
@ -0,0 +1,15 @@
|
||||
package com.mh.common.core.domain.entity; |
||||
|
||||
import lombok.Data; |
||||
|
||||
/** |
||||
* @Author : Rainbow |
||||
* @date : 2023/7/11 |
||||
*/ |
||||
@Data |
||||
public class HistoryEntity { |
||||
private int id; |
||||
private String name; |
||||
private String date; |
||||
private double value; |
||||
} |
||||
@ -0,0 +1,30 @@
|
||||
package com.mh.common.core.domain.entity.chart; |
||||
|
||||
import lombok.Getter; |
||||
import lombok.Setter; |
||||
|
||||
/** |
||||
* @author LJF |
||||
* @title : |
||||
* @description : |
||||
* @updateTime 2020-07-10 |
||||
* @throws : |
||||
*/ |
||||
@Setter |
||||
@Getter |
||||
public class AxisLine { |
||||
private boolean show; |
||||
private LineStyle lineStyle; |
||||
private String color = ""; |
||||
|
||||
public AxisLine(boolean show, LineStyle lineStyle) { |
||||
this.show = show; |
||||
this.lineStyle = lineStyle; |
||||
} |
||||
|
||||
public AxisLine(boolean show, LineStyle lineStyle, String color) { |
||||
this.show = show; |
||||
this.lineStyle = lineStyle; |
||||
this.color = color; |
||||
} |
||||
} |
||||
@ -0,0 +1,45 @@
|
||||
package com.mh.common.core.domain.entity.chart; |
||||
|
||||
import lombok.Getter; |
||||
import lombok.Setter; |
||||
|
||||
/** |
||||
* @author LJF |
||||
* @title : 基础数据获取实体类 |
||||
* @description : |
||||
* @updateTime 2020-07-13 |
||||
* @throws : |
||||
*/ |
||||
@Setter |
||||
@Getter |
||||
public class BaseChartEntity { |
||||
|
||||
private String chartTime; |
||||
private String indexName; |
||||
private String indexType; |
||||
private String displayType; |
||||
private int indexId; |
||||
private int width; |
||||
private String chartName; |
||||
private String timeName; |
||||
private int chartId; |
||||
private String unit; |
||||
private double data; |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "BaseChartEntity{" + |
||||
"chartTime='" + chartTime + '\'' + |
||||
", indexName='" + indexName + '\'' + |
||||
", indexType='" + indexType + '\'' + |
||||
", displayType='" + displayType + '\'' + |
||||
", indexId=" + indexId + |
||||
", width=" + width + |
||||
", chartName='" + chartName + '\'' + |
||||
", timeName='" + timeName + '\'' + |
||||
", chartId=" + chartId + |
||||
", unit='" + unit + '\'' + |
||||
", data=" + data + |
||||
'}'; |
||||
} |
||||
} |
||||
@ -0,0 +1,54 @@
|
||||
package com.mh.common.core.domain.entity.chart; |
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONType; |
||||
import lombok.Getter; |
||||
import lombok.Setter; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* @author LJF |
||||
* @title :图表实体类 |
||||
* @description : |
||||
* @updateTime 2020-07-10 |
||||
* @throws : |
||||
*/ |
||||
@Setter |
||||
@Getter |
||||
@JSONType(orders = {"title","feature","legend","xAxis","yAxis","series","timeName"}) |
||||
public class ChartEntity { |
||||
|
||||
private Title title; |
||||
private Feature feature; |
||||
private Legend legend; |
||||
private ToolTip toolTip; |
||||
private XAxis xAxis; |
||||
private List<YAxis> yAxis; |
||||
private List<Series> series; |
||||
|
||||
public ChartEntity() { |
||||
} |
||||
|
||||
public ChartEntity(Title title, Feature feature, Legend legend, XAxis xAxis, List<YAxis> yAxis, List<Series> series) { |
||||
this.title = title; |
||||
this.feature = feature; |
||||
this.legend = legend; |
||||
this.xAxis = xAxis; |
||||
this.yAxis = yAxis; |
||||
this.series = series; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "ChartEntity{" + |
||||
"title=" + title + |
||||
", feature=" + feature + |
||||
", legend=" + legend + |
||||
", xAxis=" + xAxis + |
||||
", yAxis=" + yAxis + |
||||
", series=" + series + |
||||
'}'; |
||||
} |
||||
} |
||||
|
||||
|
||||
@ -0,0 +1,17 @@
|
||||
package com.mh.common.core.domain.entity.chart; |
||||
|
||||
import lombok.Data; |
||||
|
||||
/** |
||||
* @author 铭汉科技——LJF |
||||
* @date 2023-03-23 15:25 |
||||
* @Description |
||||
*/ |
||||
@Data |
||||
public class ChartParams { |
||||
private String beginTime; |
||||
private String endTime; |
||||
private String dayType; |
||||
private String charType; |
||||
private String chooseId; |
||||
} |
||||
@ -0,0 +1,31 @@
|
||||
package com.mh.common.core.domain.entity.chart; |
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONType; |
||||
import lombok.Getter; |
||||
import lombok.Setter; |
||||
|
||||
/** |
||||
* @author LJF |
||||
* @title : |
||||
* @description : |
||||
* @updateTime 2020-07-10 |
||||
* @throws : |
||||
*/ |
||||
@Getter |
||||
@Setter |
||||
@JSONType(orders = {"state","tile","icon","name"}) |
||||
public class Feature { |
||||
private boolean[] state; |
||||
private String[] title; |
||||
private String[] icon; |
||||
private String[] name; |
||||
private String[] yAxisName; |
||||
|
||||
public Feature(boolean[] state, String[] title, String[] icon, String[] name, String[] yAxisName) { |
||||
this.state = state; |
||||
this.title = title; |
||||
this.icon = icon; |
||||
this.name = name; |
||||
this.yAxisName = yAxisName; |
||||
} |
||||
} |
||||
@ -0,0 +1,35 @@
|
||||
package com.mh.common.core.domain.entity.chart; |
||||
|
||||
import lombok.Getter; |
||||
import lombok.Setter; |
||||
|
||||
import java.util.Arrays; |
||||
|
||||
/** |
||||
* @author LJF |
||||
* @title : |
||||
* @description : |
||||
* @updateTime 2020-07-17 |
||||
* @throws : |
||||
*/ |
||||
@Setter |
||||
@Getter |
||||
public class GetChartParams { |
||||
|
||||
private int chartId; |
||||
private int[] chooseIndexId; |
||||
private String beginTime; |
||||
private String endTime; |
||||
private String type; // 'today' 'yesterday' 'twentyFourHour' 'thisWeek' 'fourWeek' 'twelveMonth' 'fourYear'
|
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "GetChartParams{" + |
||||
"chartId=" + chartId + |
||||
", chooseIndexId=" + Arrays.toString(chooseIndexId) + |
||||
", beginTime='" + beginTime + '\'' + |
||||
", endTime='" + endTime + '\'' + |
||||
", type='" + type + '\'' + |
||||
'}'; |
||||
} |
||||
} |
||||
@ -0,0 +1,30 @@
|
||||
package com.mh.common.core.domain.entity.chart; |
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONType; |
||||
import lombok.Getter; |
||||
import lombok.Setter; |
||||
|
||||
/** |
||||
* @author LJF |
||||
* @title : |
||||
* @description : |
||||
* @updateTime 2020-07-10 |
||||
* @throws : |
||||
*/ |
||||
@Setter |
||||
@Getter |
||||
@JSONType(orders = {"data","width","indexId"}) |
||||
public class Legend { |
||||
private String[] data; |
||||
private int width; |
||||
private int[] indexId; |
||||
|
||||
public Legend() { |
||||
} |
||||
|
||||
public Legend(String[] data, int width, int[] indexId) { |
||||
this.data = data; |
||||
this.width = width; |
||||
this.indexId = indexId; |
||||
} |
||||
} |
||||
@ -0,0 +1,21 @@
|
||||
package com.mh.common.core.domain.entity.chart; |
||||
|
||||
import lombok.Getter; |
||||
import lombok.Setter; |
||||
|
||||
/** |
||||
* @author LJF |
||||
* @title : |
||||
* @description : |
||||
* @updateTime 2020-07-10 |
||||
* @throws : |
||||
*/ |
||||
@Setter |
||||
@Getter |
||||
public class LineStyle { |
||||
private String color; |
||||
|
||||
public LineStyle(String color) { |
||||
this.color = color; |
||||
} |
||||
} |
||||
@ -0,0 +1,38 @@
|
||||
package com.mh.common.core.domain.entity.chart; |
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONType; |
||||
import lombok.Getter; |
||||
import lombok.Setter; |
||||
|
||||
/** |
||||
* @author LJF |
||||
* @title : |
||||
* @description : |
||||
* @updateTime 2020-07-10 |
||||
* @throws : |
||||
*/ |
||||
@Setter |
||||
@Getter |
||||
@JSONType(orders = {"name","type","yAxisIndex","data","sampling"}) |
||||
public class Series { |
||||
private String name; |
||||
private String type; |
||||
private int yAxisIndex = 0; |
||||
private Double[] data; |
||||
private String sampling = "average"; |
||||
|
||||
public Series(String name, String type, int yAxisIndex, Double[] data) { |
||||
this.name = name; |
||||
this.type = type; |
||||
this.yAxisIndex = yAxisIndex; |
||||
this.data = data; |
||||
} |
||||
|
||||
public Series(String name, String type, int yAxisIndex, Double[] data, String sampling) { |
||||
this.name = name; |
||||
this.type = type; |
||||
this.yAxisIndex = yAxisIndex; |
||||
this.data = data; |
||||
this.sampling = sampling; |
||||
} |
||||
} |
||||
@ -0,0 +1,21 @@
|
||||
package com.mh.common.core.domain.entity.chart; |
||||
|
||||
import lombok.Getter; |
||||
import lombok.Setter; |
||||
|
||||
/** |
||||
* @author LJF |
||||
* @title : |
||||
* @description : |
||||
* @updateTime 2020-07-10 |
||||
* @throws : |
||||
*/ |
||||
@Setter |
||||
@Getter |
||||
public class SplitLine { |
||||
private boolean show; |
||||
|
||||
public SplitLine(boolean show) { |
||||
this.show = show; |
||||
} |
||||
} |
||||
@ -0,0 +1,25 @@
|
||||
package com.mh.common.core.domain.entity.chart; |
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONType; |
||||
import lombok.Getter; |
||||
import lombok.Setter; |
||||
|
||||
/** |
||||
* @author LJF |
||||
* @title : |
||||
* @description : |
||||
* @updateTime 2020-07-10 |
||||
* @throws : |
||||
*/ |
||||
@Setter |
||||
@Getter |
||||
@JSONType(orders = {"state","name"}) |
||||
public class Title { |
||||
private boolean state; |
||||
private String name; |
||||
|
||||
public Title(boolean state, String name) { |
||||
this.state = state; |
||||
this.name = name; |
||||
} |
||||
} |
||||
@ -0,0 +1,16 @@
|
||||
package com.mh.common.core.domain.entity.chart; |
||||
|
||||
import lombok.Data; |
||||
|
||||
/** |
||||
* @Author : Rainbow |
||||
* @date : 2023/7/11 |
||||
*/ |
||||
@Data |
||||
public class ToolTip { |
||||
private String trigger; |
||||
|
||||
public ToolTip(String trigger) { |
||||
this.trigger = trigger; |
||||
} |
||||
} |
||||
@ -0,0 +1,37 @@
|
||||
package com.mh.common.core.domain.entity.chart; |
||||
|
||||
import lombok.Getter; |
||||
import lombok.Setter; |
||||
|
||||
/** |
||||
* @author LJF |
||||
* @title : |
||||
* @description :单位实体类 |
||||
* @updateTime 2020-07-13 |
||||
* @throws : |
||||
*/ |
||||
@Setter |
||||
@Getter |
||||
public class Unit { |
||||
|
||||
private int id; |
||||
private String unitName; |
||||
private String unit; |
||||
private String icon; |
||||
private String grade; |
||||
private String indexName; |
||||
private String otherName; |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "Unit{" + |
||||
"id=" + id + |
||||
", unitName='" + unitName + '\'' + |
||||
", unit='" + unit + '\'' + |
||||
", icon='" + icon + '\'' + |
||||
", grade='" + grade + '\'' + |
||||
", indexName='" + indexName + '\'' + |
||||
", otherName='" + otherName + '\'' + |
||||
'}'; |
||||
} |
||||
} |
||||
@ -0,0 +1,21 @@
|
||||
package com.mh.common.core.domain.entity.chart; |
||||
|
||||
import lombok.Getter; |
||||
import lombok.Setter; |
||||
|
||||
/** |
||||
* @author LJF |
||||
* @title : |
||||
* @description : |
||||
* @updateTime 2020-07-10 |
||||
* @throws : |
||||
*/ |
||||
@Setter |
||||
@Getter |
||||
public class XAxis { |
||||
private String[] data; |
||||
|
||||
public XAxis(String[] data) { |
||||
this.data = data; |
||||
} |
||||
} |
||||
@ -0,0 +1,31 @@
|
||||
package com.mh.common.core.domain.entity.chart; |
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONType; |
||||
import lombok.Getter; |
||||
import lombok.Setter; |
||||
|
||||
/** |
||||
* @author LJF |
||||
* @title : |
||||
* @description : |
||||
* @updateTime 2020-07-10 |
||||
* @throws : |
||||
*/ |
||||
@Setter |
||||
@Getter |
||||
@JSONType(orders = {"type","name","splitLine","axisLine","show"}) |
||||
public class YAxis { |
||||
private String type; |
||||
private String name; |
||||
private SplitLine splitLine; |
||||
private AxisLine axisLine; |
||||
private boolean show; |
||||
|
||||
public YAxis(String type, String name, SplitLine splitLine, AxisLine axisLine, boolean show) { |
||||
this.type = type; |
||||
this.name = name; |
||||
this.splitLine = splitLine; |
||||
this.axisLine = axisLine; |
||||
this.show = show; |
||||
} |
||||
} |
||||
@ -0,0 +1,79 @@
|
||||
package com.mh.common.utils; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* @Author : Rainbow |
||||
* @date : 2023/7/10 |
||||
*/ |
||||
public class TableUtils { |
||||
/** |
||||
* 主机 |
||||
*/ |
||||
public final static String CHILLER = "chiller"; |
||||
/** |
||||
* 电表等参数 |
||||
*/ |
||||
public final static String DEVICE = "device"; |
||||
|
||||
/** |
||||
* 返回表明列表 |
||||
* |
||||
* @param dateType 分钟、小时、日月年 |
||||
* @param dataType 主机参数、电表等参数 |
||||
* @param startTime 开始时间 |
||||
* @param endTime 结束时间 |
||||
* @return 表名集合 |
||||
*/ |
||||
public static List<String> getTableName(String dateType, String dataType, String startTime, String endTime) { |
||||
int start = Integer.parseInt(startTime.substring(0, 4)); |
||||
int end = Integer.parseInt(endTime.substring(0, 4)); |
||||
if (end < start) { |
||||
throw new RuntimeException("时间不正确"); |
||||
} |
||||
List<String> tabNames = new ArrayList<>(); |
||||
StringBuilder tableName = new StringBuilder(); |
||||
for (int i = start; i <= end; i++) { |
||||
//清空
|
||||
tableName.setLength(0); |
||||
switch (dataType){ |
||||
case CHILLER: |
||||
tableName.append("chillers_data_").append(dateType).append(i); |
||||
break; |
||||
case DEVICE: |
||||
tableName.append("data_").append(dateType).append(i); |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
tabNames.add(tableName.toString()); |
||||
} |
||||
return tabNames; |
||||
} |
||||
|
||||
/** |
||||
* 返回表名字 |
||||
* |
||||
* @param dateType 分钟、小时、日月年 |
||||
* @param dataType 主机参数、电表等参数 |
||||
* @param date 时间 |
||||
* @return 一个表名 |
||||
*/ |
||||
public static String getTableName(String dateType, String dataType, String date) { |
||||
StringBuilder tableName = new StringBuilder(); |
||||
switch (dataType) { |
||||
case CHILLER: |
||||
tableName.append("chillers_data_"); |
||||
break; |
||||
case DEVICE: |
||||
tableName.append("data_"); |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
|
||||
tableName.append(dateType).append(date.substring(0, 4)); |
||||
return tableName.toString(); |
||||
} |
||||
} |
||||
@ -0,0 +1,392 @@
|
||||
package com.mh.quartz.task; |
||||
|
||||
import com.alibaba.fastjson2.JSON; |
||||
import com.alibaba.fastjson2.JSONArray; |
||||
import com.alibaba.fastjson2.JSONObject; |
||||
import com.fasterxml.jackson.databind.ObjectMapper; |
||||
import com.mh.common.constant.Constants; |
||||
import com.mh.common.core.domain.entity.CollectionParamsManage; |
||||
import com.mh.common.model.request.AdvantechDatas; |
||||
import com.mh.common.model.request.AdvantechReceiver; |
||||
import com.mh.common.utils.DateUtils; |
||||
import com.mh.common.utils.http.HttpUtils; |
||||
import com.mh.framework.rabbitmq.producer.SendMsgByTopic; |
||||
import com.mh.system.service.device.ICollectionParamsManageService; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
import java.math.BigDecimal; |
||||
import java.util.ArrayList; |
||||
import java.util.Date; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.concurrent.CompletableFuture; |
||||
import java.util.concurrent.ExecutorService; |
||||
import java.util.concurrent.Executors; |
||||
import java.util.concurrent.TimeUnit; |
||||
|
||||
/** |
||||
* @author LJF |
||||
* @version 1.0 |
||||
* @project EEMCS |
||||
* @description 获取第三方数据定时任务 |
||||
* @date 2026-06-05 10:57:49 |
||||
*/ |
||||
@Slf4j |
||||
@Component("getOtherSysDataJob") |
||||
public class GetOtherSysDataJob { |
||||
|
||||
@Autowired |
||||
private ICollectionParamsManageService collectionParamsManageService; |
||||
|
||||
@Autowired |
||||
private ObjectMapper mapper; |
||||
|
||||
@Autowired |
||||
private SendMsgByTopic sendMsgByTopic; |
||||
|
||||
// 创建线程池用于并发请求
|
||||
private static final ExecutorService executor = Executors.newFixedThreadPool(2, r -> { |
||||
Thread thread = new Thread(r); |
||||
thread.setName("BSD-Data-Fetcher"); |
||||
thread.setDaemon(true); |
||||
return thread; |
||||
}); |
||||
|
||||
//TODO 机房总电表
|
||||
private final String[] totalMeters = new String[]{ |
||||
"Power", // 机房实时功率
|
||||
"PowerTotal" // 机房累计读数
|
||||
}; |
||||
|
||||
//TODO 主机总电表
|
||||
private final String[] powerMeters = new String[]{ |
||||
"ChPower", // 主机实时功率
|
||||
"PowerTotal_CH" // 主机累计读数
|
||||
}; |
||||
|
||||
//TODO 冷冻泵总电表
|
||||
private final String[] freezePumpMeters = new String[]{ |
||||
"PriChWPPower", // 冷冻泵实时功率
|
||||
"PowerTotal_ChWPump" // 冷冻泵累计读数
|
||||
}; |
||||
|
||||
//TODO 冷却泵总电表
|
||||
private final String[] coolPumpMeters = new String[]{ |
||||
"CWPPower", // 冷却泵实时功率
|
||||
"PowerTotal_CWPump" // 冷却泵累计读数
|
||||
}; |
||||
|
||||
//TODO 冷却塔总电表
|
||||
private final String[] towerMeters = new String[]{ |
||||
"CTPower", // 冷却塔实时功率
|
||||
"PowerTotal_CT" // 冷却塔累计读数
|
||||
}; |
||||
|
||||
public void getBSDData(String realUrl, String realValuesUrl) { |
||||
log.info("获取BSD数据"); |
||||
try { |
||||
// 获取实时读数\累计读数的所有点位
|
||||
HashMap<String, Object> params = new HashMap<>(); |
||||
params.put("systemType", "0"); |
||||
params.put("paramType", "16"); |
||||
List<CollectionParamsManage> collectionParamsManages = collectionParamsManageService.selectListByParams(params); |
||||
|
||||
// 分离grade=40(累计读数)和grade=140(实时功率)的点位
|
||||
List<String> cumulativeMtCodes = new ArrayList<>(); // grade=40
|
||||
List<String> powerMtCodes = new ArrayList<>(); // grade=140
|
||||
HashMap<String, String> mtCodeToOtherNameMap = new HashMap<>(); // mtCode到otherName的映射
|
||||
|
||||
for (CollectionParamsManage param : collectionParamsManages) { |
||||
if (param.getGrade() != null && param.getMtCode() != null) { |
||||
// 建立mtCode到otherName的映射关系
|
||||
if (param.getOtherName() != null && !param.getOtherName().isEmpty()) { |
||||
mtCodeToOtherNameMap.put(param.getMtCode(), param.getOtherName()); |
||||
} |
||||
// 判断如果等于totalMeters、powerMeters、freezePumpMeters、coolPumpMeters、towerMeters的点位,就下一个循环
|
||||
if (totalMeters[0].equals(param.getMtCode()) || totalMeters[1].equals(param.getMtCode()) || |
||||
powerMeters[0].equals(param.getMtCode()) || powerMeters[1].equals(param.getMtCode()) || |
||||
freezePumpMeters[0].equals(param.getMtCode()) || freezePumpMeters[1].equals(param.getMtCode()) || |
||||
coolPumpMeters[0].equals(param.getMtCode()) || coolPumpMeters[1].equals(param.getMtCode()) || |
||||
towerMeters[0].equals(param.getMtCode()) || towerMeters[1].equals(param.getMtCode())) { |
||||
continue; |
||||
} |
||||
|
||||
if (param.getGrade() == 40) { |
||||
cumulativeMtCodes.add(param.getMtCode()); |
||||
} else if (param.getGrade() == 140) { |
||||
powerMtCodes.add(param.getMtCode()); |
||||
} |
||||
} |
||||
} |
||||
|
||||
List<AdvantechDatas> allAdvantechDatas = new ArrayList<>(); |
||||
|
||||
// 使用CompletableFuture并发请求累计读数和功率读数
|
||||
CompletableFuture<List<AdvantechDatas>> cumulativeFuture = null; |
||||
CompletableFuture<List<AdvantechDatas>> powerFuture = null; |
||||
|
||||
// 并发请求累计读数 (grade=40)
|
||||
if (!cumulativeMtCodes.isEmpty()) { |
||||
final List<String> finalCumulativeMtCodes = new ArrayList<>(cumulativeMtCodes); |
||||
final HashMap<String, String> finalMtCodeToOtherNameMap = new HashMap<>(mtCodeToOtherNameMap); |
||||
cumulativeFuture = CompletableFuture.supplyAsync(() -> { |
||||
log.info("[线程-{}] 请求累计读数,点位数量: {}", Thread.currentThread().getName(), finalCumulativeMtCodes.size()); |
||||
// http://192.168.1.80:5002/data/get_real
|
||||
return fetchCumulativeData(finalCumulativeMtCodes, finalMtCodeToOtherNameMap, realUrl); |
||||
}, executor); |
||||
} |
||||
|
||||
// 并发请求功率读数 (grade=140)
|
||||
if (!powerMtCodes.isEmpty()) { |
||||
final List<String> finalPowerMtCodes = new ArrayList<>(powerMtCodes); |
||||
final HashMap<String, String> finalMtCodeToOtherNameMap = new HashMap<>(mtCodeToOtherNameMap); |
||||
powerFuture = CompletableFuture.supplyAsync(() -> { |
||||
log.info("[线程-{}] 请求功率读数,点位数量: {}", Thread.currentThread().getName(), finalPowerMtCodes.size()); |
||||
// http://192.168.1.80:5002/data/get_real_values
|
||||
return fetchPowerData(finalPowerMtCodes, finalMtCodeToOtherNameMap, realValuesUrl); |
||||
}, executor); |
||||
} |
||||
|
||||
// 等待两个任务完成并合并结果
|
||||
try { |
||||
if (cumulativeFuture != null) { |
||||
List<AdvantechDatas> cumulativeDatas = cumulativeFuture.get(30, TimeUnit.SECONDS); |
||||
// 累计读数
|
||||
// cumulativeDatas.遍历计算得出机房总累计读数、主机总累计读数、冷冻泵总累计读数、冷却泵总累计读数、冷却塔总累计读数
|
||||
// 新建一个主机总电表的AdvantechDatas对象,tag为mtCodeToOtherNameMap,key值为"PowerTotal_CH"的value值,quality为0,value为cumulativeDatas中tag包含"主机*累计读数"的value和值
|
||||
// 新建一个冷冻泵总电表的AdvantechDatas对象,tag为mtCodeToOtherNameMap,key值为"PowerTotal_ChWPump"的value值,quality为0,value为cumulativeDatas中tag包含"冷冻泵*累计读数"的value和值
|
||||
// 新建一个冷却泵总电表的AdvantechDatas对象,tag为mtCodeToOtherNameMap,key值为"PowerTotal_CWPump"的value值,quality为0,value为cumulativeDatas中tag包含"冷却泵*累计读数"的value和值
|
||||
// 新建一个冷却塔总电表的AdvantechDatas对象,tag为mtCodeToOtherNameMap,key值为"PowerTotal_CT"的value值,quality为0,value为cumulativeDatas中tag包含"冷却塔*累计读数"的value和值
|
||||
// 新建一个机房总电表的AdvantechDatas对象,tag为mtCodeToOtherNameMap,key值为"PowerTotal"的value值,quality为0,value为cumulativeDatas中tag包含"累计读数"的value和值
|
||||
// 瞬时功率
|
||||
// cumulativeDatas.遍历计算得出机房总瞬时功率、主机总瞬时功率、冷冻泵总瞬时功率、冷却泵总瞬时功率、冷却塔总瞬时功率
|
||||
// 新建一个主机总电表的AdvantechDatas对象,tag为mtCodeToOtherNameMap,key值为"ChPower"的value值,quality为0,value为cumulativeDatas中tag包含"主机*瞬时功率"的value和值
|
||||
// 新建一个冷冻泵总电表的AdvantechDatas对象,tag为mtCodeToOtherNameMap,key值为"PriChWPPower"的value值,quality为0,value为cumulativeDatas中tag包含"冷冻泵*瞬时功率"的value和值
|
||||
// 新建一个冷却泵总电表的AdvantechDatas对象,tag为mtCodeToOtherNameMap,key值为"CWPPower"的value值,quality为0,value为cumulativeDatas中tag包含"冷却泵*瞬时功率"的value和值
|
||||
// 新建一个冷却塔总电表的AdvantechDatas对象,tag为mtCodeToOtherNameMap,key值为"CTPower"的value值,quality为0,value为cumulativeDatas中tag包含"冷却塔*瞬时功率"的value和值
|
||||
// 新建一个机房总电表的AdvantechDatas对象,tag为mtCodeToOtherNameMap,key值为"Power"的value值,quality为0,value为cumulativeDatas中tag包含"瞬时功率"的value和值
|
||||
// 再插入到cumulativeDatas中
|
||||
|
||||
try { |
||||
// 计算汇总数据并添加到cumulativeDatas
|
||||
calculateAndAddSummaryData(cumulativeDatas, mtCodeToOtherNameMap); |
||||
} catch (Exception e) { |
||||
log.error("累计读数汇总计算异常,但不影响后续流程", e); |
||||
} |
||||
|
||||
allAdvantechDatas.addAll(cumulativeDatas); |
||||
log.info("累计读数获取完成,数据点数: {}", cumulativeDatas.size()); |
||||
} |
||||
|
||||
if (powerFuture != null) { |
||||
List<AdvantechDatas> powerDatas = powerFuture.get(30, TimeUnit.SECONDS); |
||||
allAdvantechDatas.addAll(powerDatas); |
||||
// 实时功率
|
||||
log.info("功率读数获取完成,数据点数: {}", powerDatas.size()); |
||||
} |
||||
} catch (Exception e) { |
||||
log.error("等待异步任务完成时异常", e); |
||||
} |
||||
|
||||
// 封装成研华网关格式并发送到消息队列
|
||||
if (!allAdvantechDatas.isEmpty()) { |
||||
AdvantechReceiver advantechReceiver = new AdvantechReceiver(); |
||||
advantechReceiver.setTs(DateUtils.dateToString(new Date(), Constants.DATE_FORMAT)); |
||||
advantechReceiver.setD(allAdvantechDatas); |
||||
|
||||
String message = JSONObject.toJSONString(advantechReceiver); |
||||
log.info("发送BSD数据到消息队列,数据点数: {}", allAdvantechDatas.size()); |
||||
sendMsgByTopic.sendToDeviceMQ(message); |
||||
log.info("BSD数据发送成功"); |
||||
} else { |
||||
log.warn("没有获取到任何BSD数据"); |
||||
} |
||||
|
||||
} catch (Exception e) { |
||||
log.error("获取BSD数据异常", e); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 计算并添加汇总数据到cumulativeDatas |
||||
* @param cumulativeDatas 累计读数数据列表 |
||||
* @param mtCodeToOtherNameMap mtCode到otherName的映射关系 |
||||
*/ |
||||
private void calculateAndAddSummaryData(List<AdvantechDatas> cumulativeDatas, HashMap<String, String> mtCodeToOtherNameMap) { |
||||
// 定义汇总类型枚举
|
||||
enum SummaryType { |
||||
CH_CUMULATIVE("主机", "累计读数", "PowerTotal_CH", "主机总累计读数"), |
||||
CHWP_CUMULATIVE("冷冻泵", "累计读数", "PowerTotal_ChWPump", "冷冻泵总累计读数"), |
||||
CWP_CUMULATIVE("冷却泵", "累计读数", "PowerTotal_CWPump", "冷却泵总累计读数"), |
||||
CT_CUMULATIVE("冷却塔", "累计读数", "PowerTotal_CT", "冷却塔总累计读数"), |
||||
ALL_CUMULATIVE(null, "累计读数", "PowerTotal", "机房总累计读数"), |
||||
CH_POWER("主机", "瞬时功率", "ChPower", "主机总瞬时功率"), |
||||
CHWP_POWER("冷冻泵", "瞬时功率", "PriChWPPower", "冷冻泵总瞬时功率"), |
||||
CWP_POWER("冷却泵", "瞬时功率", "CWPPower", "冷却泵总瞬时功率"), |
||||
CT_POWER("冷却塔", "瞬时功率", "CTPower", "冷却塔总瞬时功率"), |
||||
ALL_POWER(null, "瞬时功率", "Power", "机房总瞬时功率"); |
||||
|
||||
private final String deviceKeyword; |
||||
private final String dataKeyword; |
||||
private final String mtCode; |
||||
private final String description; |
||||
|
||||
SummaryType(String deviceKeyword, String dataKeyword, String mtCode, String description) { |
||||
this.deviceKeyword = deviceKeyword; |
||||
this.dataKeyword = dataKeyword; |
||||
this.mtCode = mtCode; |
||||
this.description = description; |
||||
} |
||||
} |
||||
|
||||
// 一次性遍历cumulativeDatas,分类累加各类型数据
|
||||
Map<SummaryType, BigDecimal> summaryMap = new HashMap<>(); |
||||
// 初始化所有汇总类型
|
||||
for (SummaryType type : SummaryType.values()) { |
||||
summaryMap.put(type, BigDecimal.ZERO); |
||||
} |
||||
|
||||
for (AdvantechDatas data : cumulativeDatas) { |
||||
if (data.getTag() == null || data.getValue() == null) { |
||||
continue; |
||||
} |
||||
String tag = data.getTag(); |
||||
BigDecimal value = new BigDecimal(data.getValue().toString()); |
||||
|
||||
// 遍历所有汇总类型进行匹配
|
||||
for (SummaryType type : SummaryType.values()) { |
||||
boolean matchesDataKeyword = tag.contains(type.dataKeyword); |
||||
boolean matchesDeviceKeyword = type.deviceKeyword == null || tag.contains(type.deviceKeyword); |
||||
|
||||
if (matchesDataKeyword && matchesDeviceKeyword) { |
||||
summaryMap.merge(type, value, BigDecimal::add); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// 创建并添加汇总数据点
|
||||
int successCount = 0; |
||||
for (SummaryType type : SummaryType.values()) { |
||||
try { |
||||
String targetTag = mtCodeToOtherNameMap.get(type.mtCode); |
||||
if (targetTag != null && !targetTag.isEmpty()) { |
||||
AdvantechDatas summaryData = new AdvantechDatas(); |
||||
summaryData.setTag(targetTag); |
||||
summaryData.setValue(summaryMap.get(type)); |
||||
summaryData.setQuality(0); |
||||
cumulativeDatas.add(summaryData); |
||||
log.debug("添加{}: {} = {}", type.description, targetTag, summaryMap.get(type)); |
||||
successCount++; |
||||
} |
||||
} catch (Exception e) { |
||||
log.error("添加{}失败", type.description, e); |
||||
} |
||||
} |
||||
|
||||
log.info("累计读数汇总完成,成功添加{}/{}个汇总数据点", successCount, SummaryType.values().length); |
||||
} |
||||
|
||||
/** |
||||
* 获取累计读数数据 |
||||
* @param mtCodes 点位编码列表 |
||||
* @param mtCodeToOtherNameMap mtCode到otherName的映射关系 |
||||
* @param realUrl 请求URL |
||||
* @return 解析后的数据列表 |
||||
*/ |
||||
private List<AdvantechDatas> fetchCumulativeData(List<String> mtCodes, HashMap<String, String> mtCodeToOtherNameMap, String realUrl) { |
||||
List<AdvantechDatas> dataList = new ArrayList<>(); |
||||
try { |
||||
JSONObject cumulativeRequest = new JSONObject(); |
||||
cumulativeRequest.put("names", mtCodes); |
||||
JSONArray pointProperty = new JSONArray(); |
||||
pointProperty.add("point_value"); |
||||
cumulativeRequest.put("point_property", pointProperty); |
||||
cumulativeRequest.put("proj_id", "1"); |
||||
|
||||
String cumulativeResponse = HttpUtils.sendPost(realUrl, cumulativeRequest.toJSONString()); |
||||
log.info("[线程-{}] 累计读数响应长度: {}", Thread.currentThread().getName(), |
||||
cumulativeResponse != null ? cumulativeResponse.length() : 0); |
||||
|
||||
if (cumulativeResponse != null && !cumulativeResponse.isEmpty()) { |
||||
JSONObject cumulativeJson = JSON.parseObject(cumulativeResponse); |
||||
if (cumulativeJson.getBooleanValue("success") && cumulativeJson.containsKey("data")) { |
||||
JSONObject dataObj = cumulativeJson.getJSONObject("data"); |
||||
for (String mtCode : mtCodes) { |
||||
if (dataObj.containsKey(mtCode)) { |
||||
JSONArray valueArray = dataObj.getJSONArray(mtCode); |
||||
if (valueArray != null && !valueArray.isEmpty()) { |
||||
String valueStr = valueArray.getString(0); |
||||
try { |
||||
BigDecimal value = new BigDecimal(valueStr); |
||||
AdvantechDatas datas = new AdvantechDatas(); |
||||
// 使用otherName作为tag,如果不存在则使用mtCode
|
||||
String tag = mtCodeToOtherNameMap.getOrDefault(mtCode, mtCode); |
||||
datas.setTag(tag); |
||||
datas.setValue(value); |
||||
datas.setQuality(0); |
||||
dataList.add(datas); |
||||
} catch (NumberFormatException e) { |
||||
log.error("解析累计读数失败,mtCode: {}, value: {}", mtCode, valueStr, e); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} catch (Exception e) { |
||||
log.error("获取累计读数异常", e); |
||||
} |
||||
return dataList; |
||||
} |
||||
|
||||
/** |
||||
* 获取功率读数数据 |
||||
* |
||||
* @param mtCodes 点位编码列表 |
||||
* @param mtCodeToOtherNameMap mtCode到otherName的映射关系 |
||||
* @param realValuesUrl 请求URL |
||||
* @return 解析后的数据列表 |
||||
*/ |
||||
private List<AdvantechDatas> fetchPowerData(List<String> mtCodes, HashMap<String, String> mtCodeToOtherNameMap, String realValuesUrl) { |
||||
List<AdvantechDatas> dataList = new ArrayList<>(); |
||||
try { |
||||
JSONObject powerRequest = new JSONObject(); |
||||
powerRequest.put("expresss", mtCodes); |
||||
powerRequest.put("proj_id", "1"); |
||||
|
||||
String powerResponse = HttpUtils.sendPost(realValuesUrl, powerRequest.toJSONString()); |
||||
log.info("[线程-{}] 功率读数响应长度: {}", Thread.currentThread().getName(), |
||||
powerResponse != null ? powerResponse.length() : 0); |
||||
|
||||
if (powerResponse != null && !powerResponse.isEmpty()) { |
||||
JSONObject powerJson = JSON.parseObject(powerResponse); |
||||
if (powerJson.getBooleanValue("success") && powerJson.containsKey("data")) { |
||||
JSONObject dataObj = powerJson.getJSONObject("data"); |
||||
for (String mtCode : mtCodes) { |
||||
if (dataObj.containsKey(mtCode)) { |
||||
String valueStr = dataObj.getString(mtCode); |
||||
try { |
||||
BigDecimal value = new BigDecimal(valueStr); |
||||
AdvantechDatas datas = new AdvantechDatas(); |
||||
// 使用otherName作为tag,如果不存在则使用mtCode
|
||||
String tag = mtCodeToOtherNameMap.getOrDefault(mtCode, mtCode); |
||||
datas.setTag(tag); |
||||
datas.setValue(value); |
||||
datas.setQuality(0); |
||||
dataList.add(datas); |
||||
} catch (NumberFormatException e) { |
||||
log.error("解析功率读数失败,mtCode: {}, value: {}", mtCode, valueStr, e); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} catch (Exception e) { |
||||
log.error("获取功率读数异常", e); |
||||
} |
||||
return dataList; |
||||
} |
||||
} |
||||
@ -0,0 +1,278 @@
|
||||
package com.mh.system.mapper.overview; |
||||
|
||||
import com.mh.common.core.domain.ColumnFilter; |
||||
import com.mh.common.core.domain.entity.HistoryEntity; |
||||
import org.apache.ibatis.annotations.Mapper; |
||||
import org.apache.ibatis.annotations.Param; |
||||
import org.apache.ibatis.annotations.Result; |
||||
import org.apache.ibatis.annotations.Results; |
||||
import org.apache.ibatis.annotations.Select; |
||||
|
||||
import java.math.BigDecimal; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* 首页数据 Mapper |
||||
* <p> |
||||
* 基于 collection_params_manage.mt_num = data_min.device_code 的关联查询。 |
||||
* <p> |
||||
* grade 仅有两个值:40=累计值,140=瞬时值; |
||||
* 设备类型通过 other_name 前缀或 mt_num 前缀区分。 |
||||
* |
||||
* @Author : Rainbow |
||||
* @date : 2023/7/11 |
||||
*/ |
||||
@Mapper |
||||
public interface HomeMapper { |
||||
|
||||
// ==================== 基础元数据查询 ====================
|
||||
|
||||
/** |
||||
* 获取天气温湿度 |
||||
*/ |
||||
@Select("select wd.temperature, wd.humidity from weather_data wd where wd.report_time between #{startTime}::timestamp and #{endTime}::timestamp order by wd.report_time desc limit 1") |
||||
Map<String, Integer> selectWeatherData(@Param("startTime") String startTime, @Param("endTime") String endTime); |
||||
|
||||
/** |
||||
* 查询系统运行时长(从2024-03-05起算) |
||||
*/ |
||||
@Select("SELECT EXTRACT(DAY FROM (CURRENT_DATE - DATE '2024-03-05'))::bigint") |
||||
long selectRunTime(); |
||||
|
||||
/** |
||||
* 根据 grade 查询 mt_num 列表(所有在用设备) |
||||
* |
||||
* @param grade 40=累计值, 140=瞬时值 |
||||
* @return mt_num 列表 |
||||
*/ |
||||
@Select("SELECT mt_num FROM collection_params_manage WHERE grade = #{grade} AND is_use = 0") |
||||
List<String> queryMtNumsByGrade(@Param("grade") Integer grade); |
||||
|
||||
/** |
||||
* 根据 grade 和 other_name 前缀查询 mt_num 列表 |
||||
* <p> |
||||
* 用于按设备分类查询,如: |
||||
* PowerTotal → 累计用电量设备 |
||||
* ChPower → 主机瞬时功率 |
||||
* |
||||
* @param grade 40=累计值, 140=瞬时值 |
||||
* @param otherNamePrefix other_name 前缀 |
||||
* @return mt_num 列表 |
||||
*/ |
||||
@Select("SELECT mt_code FROM collection_params_manage WHERE grade = #{grade} AND mt_num LIKE CONCAT(#{otherNamePrefix}, '%') AND is_use = 0") |
||||
List<String> queryMtNumsByGradeAndOtherNamePrefix(@Param("grade") Integer grade, |
||||
@Param("otherNamePrefix") String otherNamePrefix); |
||||
|
||||
/** |
||||
* 根据 grade 和 mt_num 前缀查询 mt_num 列表(用于冷量表) |
||||
* |
||||
* @param grade 40=累计值, 140=瞬时值 |
||||
* @param mtNumPrefix mt_num 前缀(如 3900) |
||||
* @return mt_num 列表 |
||||
*/ |
||||
@Select("SELECT mt_num FROM collection_params_manage WHERE grade = #{grade} AND mt_num LIKE CONCAT(#{mtNumPrefix}, '%') AND is_use = 0") |
||||
List<String> queryMtNumsByGradeAndMtNumPrefix(@Param("grade") Integer grade, |
||||
@Param("mtNumPrefix") String mtNumPrefix); |
||||
|
||||
/** |
||||
* 根据 grade、排除指定 mt_num 前缀查询 mt_num 列表 |
||||
* <p> |
||||
* 用于获取"非冷量表"的电力设备,如 grade=40 且 mt_num 不以 3900 开头 |
||||
* |
||||
* @param grade grade 值 |
||||
* @param excludePrefix 需要排除的 mt_num 前缀 |
||||
* @return mt_num 列表 |
||||
*/ |
||||
@Select("SELECT mt_num FROM collection_params_manage WHERE grade = #{grade} AND mt_num NOT LIKE CONCAT(#{excludePrefix}, '%') AND is_use = 0") |
||||
List<String> queryMtNumsByGradeExcludeMtNumPrefix(@Param("grade") Integer grade, |
||||
@Param("excludePrefix") String excludePrefix); |
||||
|
||||
/** |
||||
* 根据 grade 和 param_type 查询 mt_code 列表 |
||||
* |
||||
* @param grade 40=累计值 |
||||
* @param paramType 参数类型(如 "2"=产冷量) |
||||
* @return mt_num 列表 |
||||
*/ |
||||
@Select("SELECT mt_code FROM collection_params_manage WHERE grade = #{grade} AND param_type = #{paramType} AND is_use = 0") |
||||
List<String> queryMtNumsByGradeAndParamType(@Param("grade") Integer grade, |
||||
@Param("paramType") String paramType); |
||||
|
||||
// ==================== 图表曲线数据查询 ====================
|
||||
|
||||
/** |
||||
* 多个 mt_num 汇总后的当日曲线(SUM calc_value,用于总用电量、瞬时功率等累加指标) |
||||
* |
||||
* @param tableName 动态表名 |
||||
* @param mtNums mt_num 列表 |
||||
* @return 时间-汇总值列表 |
||||
*/ |
||||
@Select("<script>" + |
||||
"SELECT to_char(cur_time, 'YYYY-MM-DD HH24:MI:SS') AS date, COALESCE(SUM(calc_value), 0) AS value " + |
||||
"FROM ${tableName} " + |
||||
"WHERE device_code IN " + |
||||
"<foreach collection='mtNums' item='item' open='(' separator=',' close=')'>#{item}</foreach> " + |
||||
"AND cur_time::date = CURRENT_DATE " + |
||||
"GROUP BY cur_time ORDER BY cur_time" + |
||||
"</script>") |
||||
@Results({ |
||||
@Result(column = "date", property = "date"), |
||||
@Result(column = "value", property = "value") |
||||
}) |
||||
List<HistoryEntity> querySumHistoryByMtNums(@Param("tableName") String tableName, |
||||
@Param("mtNums") List<String> mtNums); |
||||
|
||||
/** |
||||
* 单个 device_code 的当日曲线(cur_value 字段,用于温度等直接读取类参数) |
||||
* |
||||
* @param tableName 动态表名 |
||||
* @param deviceCode 设备编码(= mt_num) |
||||
* @return 时间-值列表 |
||||
*/ |
||||
@Select("SELECT to_char(cur_time, 'YYYY-MM-DD HH24:MI:SS') AS date, cur_value AS value " + |
||||
"FROM ${tableName} WHERE device_code = #{deviceCode} AND cur_time::date = CURRENT_DATE ORDER BY cur_time") |
||||
@Results({ |
||||
@Result(column = "date", property = "date"), |
||||
@Result(column = "value", property = "value") |
||||
}) |
||||
List<HistoryEntity> queryCurValueByDeviceCode(@Param("tableName") String tableName, |
||||
@Param("deviceCode") String deviceCode); |
||||
|
||||
/** |
||||
* 单个 device_code 的当日曲线(calc_value 字段,用于功率/冷量等累计差值参数) |
||||
* |
||||
* @param tableName 动态表名 |
||||
* @param deviceCode 设备编码(= mt_num) |
||||
* @return 时间-值列表 |
||||
*/ |
||||
@Select("SELECT to_char(cur_time, 'YYYY-MM-DD HH24:MI:SS') AS date, calc_value AS value " + |
||||
"FROM ${tableName} WHERE device_code = #{deviceCode} AND cur_time::date = CURRENT_DATE ORDER BY cur_time") |
||||
@Results({ |
||||
@Result(column = "date", property = "date"), |
||||
@Result(column = "value", property = "value") |
||||
}) |
||||
List<HistoryEntity> queryCalcValueByDeviceCode(@Param("tableName") String tableName, |
||||
@Param("deviceCode") String deviceCode); |
||||
|
||||
// ==================== 能耗系数查询 ====================
|
||||
|
||||
/** |
||||
* 查询当日所有瞬时用电量设备的最新 calc_value 与 other_name |
||||
* <p> |
||||
* 用于 getCoe() 中按 other_name 前缀分类累加各子系统瞬时功率 |
||||
* |
||||
* @param tableName 动态表名 |
||||
* @param grade 140=瞬时值 |
||||
* @return other_name 和 calc_value 列表 |
||||
*/ |
||||
@Select("<script>" + |
||||
"SELECT DISTINCT ON (c.mt_num) c.mt_num, m.calc_value " + |
||||
"FROM ${tableName} m " + |
||||
"INNER JOIN collection_params_manage c ON m.device_code = c.mt_num " + |
||||
"WHERE c.grade = #{grade} AND c.is_use = 0 " + |
||||
"AND m.cur_time::date = CURRENT_DATE " + |
||||
"ORDER BY c.mt_num, m.cur_time DESC" + |
||||
"</script>") |
||||
List<Map<String, Object>> selectInstantEleWithOtherName(@Param("tableName") String tableName, |
||||
@Param("grade") Integer grade); |
||||
|
||||
// ==================== 数据统计查询 ====================
|
||||
|
||||
/** |
||||
* 产冷量统计(日、月、年累计 calc_value 求和) |
||||
* |
||||
* @param tableName 动态表名 |
||||
* @param mtNums mt_num 列表 |
||||
* @return dayCap, monthCap, yearCap |
||||
*/ |
||||
@Select("<script>" + |
||||
"SELECT " + |
||||
"COALESCE(SUM(CASE WHEN cur_time::date = CURRENT_DATE THEN calc_value ELSE 0 END), 0) AS dayCap, " + |
||||
"COALESCE(SUM(CASE WHEN date_trunc('month', cur_time) = date_trunc('month', CURRENT_DATE) THEN calc_value ELSE 0 END), 0) AS monthCap, " + |
||||
"COALESCE(SUM(CASE WHEN date_trunc('year', cur_time) = date_trunc('year', CURRENT_DATE) THEN calc_value ELSE 0 END), 0) AS yearCap " + |
||||
"FROM ${tableName} WHERE device_code IN " + |
||||
"<foreach collection='mtNums' item='item' open='(' separator=',' close=')'>#{item}</foreach>" + |
||||
"</script>") |
||||
Map<String, BigDecimal> selectAllTypeCap(@Param("tableName") String tableName, |
||||
@Param("mtNums") List<String> mtNums); |
||||
|
||||
/** |
||||
* 用电量统计(日、月、年累计 calc_value 求和) |
||||
* |
||||
* @param tableName 动态表名 |
||||
* @param mtNums mt_num 列表 |
||||
* @return dayEle, monthEle, yearEle |
||||
*/ |
||||
@Select("<script>" + |
||||
"SELECT " + |
||||
"COALESCE(SUM(CASE WHEN cur_time::date = CURRENT_DATE THEN calc_value ELSE 0 END), 0) AS dayEle, " + |
||||
"COALESCE(SUM(CASE WHEN date_trunc('month', cur_time) = date_trunc('month', CURRENT_DATE) THEN calc_value ELSE 0 END), 0) AS monthEle, " + |
||||
"COALESCE(SUM(CASE WHEN date_trunc('year', cur_time) = date_trunc('year', CURRENT_DATE) THEN calc_value ELSE 0 END), 0) AS yearEle " + |
||||
"FROM ${tableName} WHERE device_code IN " + |
||||
"<foreach collection='mtNums' item='item' open='(' separator=',' close=')'>#{item}</foreach>" + |
||||
"</script>") |
||||
Map<String, BigDecimal> selectAllTypeEle(@Param("tableName") String tableName, |
||||
@Param("mtNums") List<String> mtNums); |
||||
|
||||
/** |
||||
* 累计总用电量(全部历史 calc_value 求和) |
||||
* |
||||
* @param tableName 动态表名 |
||||
* @param mtNums mt_num 列表 |
||||
* @return 累计用电量 |
||||
*/ |
||||
@Select("<script>" + |
||||
"SELECT COALESCE(SUM(calc_value), 0) FROM ${tableName} WHERE device_code IN " + |
||||
"<foreach collection='mtNums' item='item' open='(' separator=',' close=')'>#{item}</foreach>" + |
||||
"</script>") |
||||
BigDecimal selectTotalEle(@Param("tableName") String tableName, |
||||
@Param("mtNums") List<String> mtNums); |
||||
|
||||
/** |
||||
* 累计总产冷量(最新 cur_value - 初始值 mt_init_value) |
||||
* |
||||
* @param tableName 动态表名 |
||||
* @param deviceCode 设备编码(总冷量计读数 mt_num) |
||||
* @return 累计产冷量 |
||||
*/ |
||||
@Select("<script>" + |
||||
"SELECT COALESCE((" + |
||||
"SELECT cur_value FROM ${tableName} WHERE device_code = #{deviceCode} ORDER BY cur_time DESC LIMIT 1" + |
||||
") - c.mt_init_value, 0) " + |
||||
"FROM collection_params_manage c WHERE c.mt_code = #{deviceCode} AND c.is_use = 0 LIMIT 1" + |
||||
"</script>") |
||||
BigDecimal selectTotalCap(@Param("tableName") String tableName, |
||||
@Param("deviceCode") String deviceCode); |
||||
|
||||
// ==================== 实时数据查询 ====================
|
||||
|
||||
/** |
||||
* 最新总瞬时功率(各 device_code 最新 calc_value 之和) |
||||
* |
||||
* @param tableName 动态表名 |
||||
* @param mtNums mt_num 列表 |
||||
* @return 瞬时功率总和 |
||||
*/ |
||||
@Select("<script>" + |
||||
"SELECT COALESCE(SUM(t1.calc_value), 0) FROM (" + |
||||
" SELECT DISTINCT ON (device_code) calc_value " + |
||||
" FROM ${tableName} WHERE device_code IN " + |
||||
"<foreach collection='mtNums' item='item' open='(' separator=',' close=')'>#{item}</foreach> " + |
||||
" ORDER BY device_code, cur_time DESC" + |
||||
") t1" + |
||||
"</script>") |
||||
double selectLastEle(@Param("tableName") String tableName, |
||||
@Param("mtNums") List<String> mtNums); |
||||
|
||||
/** |
||||
* 最新瞬时产冷量 / 功率值(按 mt_num 查最新一条 calc_value) |
||||
* |
||||
* @param tableName 动态表名 |
||||
* @param deviceCode 设备编码 |
||||
* @return 最新 calc_value |
||||
*/ |
||||
@Select("SELECT calc_value FROM ${tableName} WHERE device_code = #{deviceCode} ORDER BY cur_time DESC LIMIT 1") |
||||
BigDecimal selectLastCalcValueByMtNum(@Param("tableName") String tableName, |
||||
@Param("deviceCode") String deviceCode); |
||||
} |
||||
@ -0,0 +1,147 @@
|
||||
package com.mh.system.mapper.overview; |
||||
|
||||
import com.mh.common.core.domain.entity.HistoryEntity; |
||||
import org.apache.ibatis.annotations.*; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
import java.math.BigDecimal; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* @author LJF |
||||
* @title :查询报表功能 |
||||
* @description : |
||||
* @updateTime 2020-07-03 |
||||
* @throws : |
||||
*/ |
||||
@Mapper |
||||
@Component |
||||
public interface ReportMapper { |
||||
|
||||
/** |
||||
* 单表查询当日记录 |
||||
* |
||||
* @param tableName |
||||
* @param id |
||||
* @return |
||||
*/ |
||||
@Select("select cur_time,cur_value from ${tableName} where register_id = #{id} AND DateDiff(dd,cur_time,getdate())=0 order by cur_time asc ") |
||||
@Results({@Result(column = "cur_time", property = "date"), |
||||
@Result(column = "cur_value", property = "value")}) |
||||
List<HistoryEntity> queryHistoryByTable(@Param("tableName") String tableName, @Param("id") int id); |
||||
|
||||
/** |
||||
* 查询当日用电量图表 |
||||
* @param tableName |
||||
* @return |
||||
*/ |
||||
@Select("SELECT T1.cur_time,(T1.calc_value + t2.calc_value) 'value' from \n" + |
||||
"(SELECT cur_time,calc_value from ${tableName} where device_num = #{deviceNum1})T1\n" + |
||||
"FULL JOIN\n" + |
||||
"(SELECT cur_time,calc_value from ${tableName} where device_num = #{deviceNum2})T2\n" + |
||||
"ON T1.cur_time = T2.cur_time where DATEDIFF(dd,T1.cur_time,getdate()) = 0 order by T1.cur_time asc") |
||||
@Results({@Result(column = "cur_time", property = "date"), |
||||
@Result(column = "value", property = "value")}) |
||||
List<HistoryEntity> queryCurDateEleUsed(@Param("tableName") String tableName, @Param("deviceNum1") String deviceNum1, @Param("deviceNum2") String deviceNum2); |
||||
|
||||
/** |
||||
* 查询当日用电量图表 |
||||
* @param tableName |
||||
* @return |
||||
*/ |
||||
@Select("SELECT cur_time,calc_value from ${tableName} where device_num = #{deviceNum1} and DATEDIFF(dd,cur_time,getdate()) = 0 order by cur_time asc") |
||||
@Results({@Result(column = "cur_time", property = "date"), |
||||
@Result(column = "calc_value", property = "value")}) |
||||
List<HistoryEntity> queryCurDateEleUsedOne(@Param("tableName") String tableName, @Param("deviceNum1") String deviceNum1); |
||||
|
||||
/** |
||||
* 查询COP历史纪录 |
||||
* |
||||
* @return |
||||
*/ |
||||
@Select("select cur_time,cur_value from data_min_cop where " + |
||||
" DateDiff(dd,cur_time,getdate())=0 order by cur_time asc") |
||||
@Results({@Result(column = "cur_time", property = "date"), |
||||
@Result(column = "cur_value", property = "value")}) |
||||
List<HistoryEntity> selectCopHistory(); |
||||
|
||||
/** |
||||
* 查询冷冻水日平均温度 |
||||
* @param type |
||||
* @param curDate |
||||
* @param tableName |
||||
* @return |
||||
*/ |
||||
@Select("select avg(cur_value) from ${tableName} where id in(51,70) and DATEDIFF(dd,cur_time,#{curDate}) = 0") |
||||
BigDecimal selectAvgTempDD(@Param("type") String type,@Param("curDate") String curDate,@Param("tableName") String tableName); |
||||
|
||||
/** |
||||
* 查询月平均温度 |
||||
* @param type |
||||
* @param curDate |
||||
* @param tableName |
||||
* @return |
||||
*/ |
||||
BigDecimal selectAvgTempMM(@Param("type") String type,@Param("curDate") String curDate,@Param("tableName") String tableName); |
||||
|
||||
/** |
||||
* 查询瞬时功率 |
||||
* @param tableName |
||||
* @return |
||||
*/ |
||||
@Select("select cur_time,calc_value from ${tableName} where device_num = '3077' AND DateDiff(dd,cur_time,getdate())=0 order by cur_time asc ") |
||||
@Results({@Result(column = "cur_time", property = "date"), |
||||
@Result(column = "calc_value", property = "value")}) |
||||
List<HistoryEntity> queryRateCold(String tableName); |
||||
|
||||
@Select("<script>" + |
||||
// "<if test='len != null and len == 10 '>" +
|
||||
" SELECT " + |
||||
" convert(numeric(24,2),isnull(max(cur_value),0)) as maxTemp ," + |
||||
" convert(numeric(24,2),isnull(min(cur_value),0)) as minTemp FROM ${tableName} " + |
||||
" where register_address = '11' and convert(varchar(${len}),cur_time,120) = #{curDate}" + |
||||
// "</if>" +
|
||||
// "<if test='len != null and len == 7 '>" +
|
||||
// "select " +
|
||||
// " convert(numeric(24,2),avg(minTemp)) as minTemp, " +
|
||||
// " convert(numeric(24,2),avg(maxTemp)) as maxTemp " +
|
||||
// "from " +
|
||||
// " ( " +
|
||||
// " SELECT " +
|
||||
// " isnull(max(cur_value), " +
|
||||
// " 0) as maxTemp , " +
|
||||
// " isnull(min(cur_value), " +
|
||||
// " 0) as minTemp " +
|
||||
// " FROM " +
|
||||
// " ${tableName} " +
|
||||
// " where " +
|
||||
// " register_address = '11' " +
|
||||
// " and convert(varchar(${len}), " +
|
||||
// " cur_time, " +
|
||||
// " 120) = #{curDate} " +
|
||||
// " group by " +
|
||||
// " convert(varchar(10), " +
|
||||
// " cur_time, " +
|
||||
// " 120) " +
|
||||
// " ) T" +
|
||||
// "</if>" +
|
||||
"</script>") |
||||
@ResultType(Map.class) |
||||
Map<String, Object> selectTemp(@Param("type") String type, @Param("curDate") String curDate, @Param("tableName") String tableName, @Param("len") int len); |
||||
|
||||
@Select("<script>" + |
||||
"<if test ='type != null and type == \"day\".toString()'>" + |
||||
" select isnull(max(isnull(cur_value,0))-min(isnull(cur_value,0)),0) from ${tableName} " + |
||||
" where cur_time >= concat(#{curDate}, ' 00:00:00') and cur_time <= concat(#{curDate},' 23:59:59') and register_address = #{registerAddr} " + |
||||
"</if>" + |
||||
"<if test ='type != null and type == \"month\".toString()'>" + |
||||
" select isnull(max(isnull(cur_value,0))-min(isnull(cur_value,0)),0) from ${tableName} " + |
||||
" where convert(varchar(7),cur_time,120) = #{curDate} and register_address = #{registerAddr} " + |
||||
"</if>" + |
||||
"</script>") |
||||
String selectRuntimes(@Param("type") String type, |
||||
@Param("curDate") String curDate, |
||||
@Param("tableName") String dataTable, |
||||
@Param("registerAddr") String registerAddr); |
||||
} |
||||
@ -0,0 +1,55 @@
|
||||
package com.mh.system.service.overview; |
||||
|
||||
|
||||
import com.mh.common.core.page.TableDataInfo; |
||||
|
||||
/** |
||||
* 首页数据服务接口 |
||||
* |
||||
* @Author : Rainbow |
||||
* @date : 2023/7/11 |
||||
*/ |
||||
public interface HomeService { |
||||
|
||||
/** |
||||
* 主界面charts图表数据 |
||||
* |
||||
* @return 图表数据 |
||||
*/ |
||||
TableDataInfo getHomeCharts(); |
||||
|
||||
/** |
||||
* 查询统计数据(日/月/年产冷量、用电量、EER) |
||||
* |
||||
* @return 统计数据 |
||||
*/ |
||||
TableDataInfo getStatisticalData(); |
||||
|
||||
/** |
||||
* 查询能耗系数(系统能效系数、主机能效、冷冻泵/冷却泵/冷却塔输送系数) |
||||
* |
||||
* @return 能耗系数 |
||||
*/ |
||||
TableDataInfo getCoe(); |
||||
|
||||
/** |
||||
* 查询系统运行时长 |
||||
* |
||||
* @return 运行天数 |
||||
*/ |
||||
TableDataInfo getRunTime(); |
||||
|
||||
/** |
||||
* 查询实时功率与产冷量 |
||||
* |
||||
* @return 实时功率数据 |
||||
*/ |
||||
TableDataInfo getCurrentRate(); |
||||
|
||||
/** |
||||
* 获取天气数据(温度、湿度) |
||||
* |
||||
* @return 天气数据 |
||||
*/ |
||||
TableDataInfo getWeatherData(); |
||||
} |
||||
@ -0,0 +1,446 @@
|
||||
package com.mh.system.service.overview.impl; |
||||
|
||||
import com.mh.common.constant.DateConstant; |
||||
import com.mh.common.core.domain.entity.HistoryEntity; |
||||
import com.mh.common.core.domain.entity.chart.*; |
||||
import com.mh.common.core.page.TableDataInfo; |
||||
import com.mh.common.utils.DateUtils; |
||||
import com.mh.common.utils.TableUtils; |
||||
import com.mh.system.mapper.overview.HomeMapper; |
||||
import com.mh.system.service.overview.HomeService; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.stereotype.Service; |
||||
import org.springframework.util.CollectionUtils; |
||||
|
||||
import java.math.BigDecimal; |
||||
import java.math.RoundingMode; |
||||
import java.util.*; |
||||
import java.util.function.Supplier; |
||||
|
||||
/** |
||||
* 首页数据服务实现 |
||||
* <p> |
||||
* 基于 data_min(动态年表)和 collection_params_manage 的关联查询, |
||||
* 其中 collection_params_manage.mt_num = data_min.device_code。 |
||||
* <p> |
||||
* grade 仅有两个值:40=累计值,140=瞬时值; |
||||
* 设备类型通过 other_name 前缀区分,冷量表通过 mt_num 前缀(3900)识别。 |
||||
* |
||||
* @Author : Rainbow |
||||
* @date : 2023/7/11 |
||||
*/ |
||||
@Service |
||||
@Slf4j |
||||
public class HomeServiceImpl implements HomeService { |
||||
|
||||
@Autowired |
||||
private HomeMapper homeMapper; |
||||
|
||||
// ==================== grade 常量 ====================
|
||||
|
||||
/** 累计值 */ |
||||
private static final int GRADE_CUMULATIVE = 40; |
||||
/** 瞬时值 */ |
||||
private static final int GRADE_INSTANT = 140; |
||||
|
||||
// ==================== 冷量表 mt_num 常量 ====================
|
||||
|
||||
/** 总冷量计读数(累计) */ |
||||
private static final String MT_COLD_READING = "39001700"; |
||||
/** 总冷量计供水温度 */ |
||||
private static final String MT_COLD_SUPPLY_TEMP = "39001620"; |
||||
/** 总冷量计回水温度 */ |
||||
private static final String MT_COLD_RETURN_TEMP = "39001660"; |
||||
/** 系统总冷量计瞬时冷量 */ |
||||
private static final String MT_SYS_COLD_INSTANT = "39001580"; |
||||
/** 冷量表 mt_num 前缀 */ |
||||
private static final String MT_COLD_PREFIX = "3900"; |
||||
|
||||
// ==================== 电力设备 other_name 前缀常量 ====================
|
||||
|
||||
/** 累计用电量总表(格数:PowerTotal_xxx) */ |
||||
private static final String ON_POWER_CUMULATIVE_PREFIX = "PowerTotal"; |
||||
/** 机房总瞬时功率 */ |
||||
private static final String ON_SYSTEM_POWER = "Power"; |
||||
/** 主机瞬时功率(格数:ChPower, ChPower01~04) */ |
||||
private static final String ON_CHILLER_POWER_PREFIX = "ChPower"; |
||||
/** 冷冻泵瞬时功率(格数:PriChWPPower, PriChWPPower01~05) */ |
||||
private static final String ON_CHILL_PUMP_POWER_PREFIX = "PriChWPPower"; |
||||
/** 冷却泵瞬时功率(格数:CWPPower, CWPPower01~05) */ |
||||
private static final String ON_COOL_PUMP_POWER_PREFIX = "CWPPower"; |
||||
/** 冷却塔瞬时功率(格数:CTPower, CTPower01~07) */ |
||||
private static final String ON_TOWER_POWER_PREFIX = "CTPower"; |
||||
|
||||
/** 产冷量参数类型 */ |
||||
private static final String PARAM_TYPE_COLD = "17"; |
||||
|
||||
// 总表的device_num
|
||||
private static final List<String> totalMeter = Arrays.asList( |
||||
"PowerTotal_CH", |
||||
"PowerTotal_ChWPump", |
||||
"PowerTotal_CWPump", |
||||
"PowerTotal_CT", |
||||
"PowerTotal" |
||||
); |
||||
|
||||
@Override |
||||
public TableDataInfo getHomeCharts() { |
||||
String date = DateConstant.DAY_SDF.format(new Date()); |
||||
String tableName = TableUtils.getTableName("min", TableUtils.DEVICE, date); |
||||
Map<String, ChartEntity> resultMap = new LinkedHashMap<>(8); |
||||
|
||||
try { |
||||
// 1)设备总用电量:累计值(grade=40)所有非冷量表的电力设备
|
||||
List<String> eleMtNums = safeList( |
||||
homeMapper.queryMtNumsByGradeAndOtherNamePrefix(GRADE_CUMULATIVE, ON_POWER_CUMULATIVE_PREFIX)); |
||||
// 过滤掉数组totalMeter的值
|
||||
eleMtNums.removeAll(totalMeter); |
||||
List<HistoryEntity> eleHistory = queryOrEmpty(() -> |
||||
homeMapper.querySumHistoryByMtNums(tableName, eleMtNums)); |
||||
resultMap.put("eleChart", buildSingleChart("设备总用电量", eleHistory)); |
||||
|
||||
// 2)冷冻水供/回水温度走势图(只展示总管)
|
||||
List<HistoryEntity> coldOutHistory = queryOrEmpty(() -> |
||||
homeMapper.queryCurValueByDeviceCode(tableName, MT_COLD_SUPPLY_TEMP)); |
||||
List<HistoryEntity> coldInHistory = queryOrEmpty(() -> |
||||
homeMapper.queryCurValueByDeviceCode(tableName, MT_COLD_RETURN_TEMP)); |
||||
|
||||
List<Map<String, Object>> tempHistoryList = new ArrayList<>(); |
||||
tempHistoryList.add(wrapSeriesData("冷冻供水温度", coldOutHistory)); |
||||
tempHistoryList.add(wrapSeriesData("冷冻回水温度", coldInHistory)); |
||||
resultMap.put("tempChart", buildChart(tempHistoryList)); |
||||
|
||||
// 3)设备瞬时功率:瞬时值(grade=140)所有非冷量表的电力设备汇总
|
||||
List<String> powerMtNums = safeList( |
||||
homeMapper.queryMtNumsByGradeExcludeMtNumPrefix(GRADE_INSTANT, MT_COLD_PREFIX)); |
||||
List<HistoryEntity> powerHistory = queryOrEmpty(() -> |
||||
homeMapper.querySumHistoryByMtNums(tableName, powerMtNums)); |
||||
resultMap.put("eleRateChart", buildSingleChart("设备瞬时功率", powerHistory)); |
||||
|
||||
// 4)冷量表瞬时冷量
|
||||
List<HistoryEntity> rateColdHis = queryOrEmpty(() -> |
||||
homeMapper.queryCalcValueByDeviceCode(tableName, MT_SYS_COLD_INSTANT)); |
||||
resultMap.put("cloudChart", buildSingleChart("冷量表瞬时冷量", rateColdHis)); |
||||
|
||||
// 5)瞬时 EER = 冷量瞬时值 / 功率瞬时值(时间对齐)
|
||||
List<HistoryEntity> dividedResultList = calcInstantEER(powerHistory, rateColdHis); |
||||
resultMap.put("copChart", buildSingleChart("系统EER", dividedResultList)); |
||||
} catch (Exception e) { |
||||
log.error("getHomeCharts 查询异常", e); |
||||
} |
||||
|
||||
return TableDataInfo.ok(resultMap); |
||||
} |
||||
|
||||
@Override |
||||
public TableDataInfo getStatisticalData() { |
||||
String date = DateConstant.DAY_SDF.format(new Date()); |
||||
String year = date.substring(0, 4); |
||||
String dayTable = "data_min" + year; |
||||
Map<String, String> resultMap = new LinkedHashMap<>(16); |
||||
|
||||
try { |
||||
// 产冷量 mt_num:累计值(grade=40)中 param_type=2 的冷量表
|
||||
List<String> coldMtNums = safeList( |
||||
homeMapper.queryMtNumsByGradeAndParamType(GRADE_CUMULATIVE, PARAM_TYPE_COLD)); |
||||
// 用电量 mt_num:累计值(grade=40)中所有电力设备(other_name 以 PowerTotal 开头)
|
||||
List<String> eleMtNums = safeList( |
||||
homeMapper.queryMtNumsByGradeAndOtherNamePrefix(GRADE_CUMULATIVE, ON_POWER_CUMULATIVE_PREFIX)); |
||||
// 过滤掉数组totalMeter的值
|
||||
eleMtNums.removeAll(totalMeter); |
||||
|
||||
Map<String, BigDecimal> allCap = homeMapper.selectAllTypeCap(dayTable, coldMtNums); |
||||
Map<String, BigDecimal> allEle = homeMapper.selectAllTypeEle(dayTable, eleMtNums); |
||||
BigDecimal totalCap = homeMapper.selectTotalCap(dayTable, MT_COLD_READING); |
||||
BigDecimal totalEle = homeMapper.selectTotalEle(dayTable, eleMtNums); |
||||
|
||||
BigDecimal dayColdCap = getOrDefault(allCap, "daycap"); |
||||
BigDecimal monthColdCap = getOrDefault(allCap, "monthcap"); |
||||
BigDecimal yearColdCap = getOrDefault(allCap, "yearcap"); |
||||
|
||||
BigDecimal dayEle = getOrDefault(allEle, "dayele"); |
||||
BigDecimal monthEle = getOrDefault(allEle, "monthele"); |
||||
BigDecimal yearEle = getOrDefault(allEle, "yearele"); |
||||
|
||||
resultMap.put("dayColdCap", String.valueOf(dayColdCap)); |
||||
resultMap.put("monthColdCap", String.valueOf(monthColdCap)); |
||||
resultMap.put("yearColdCap", String.valueOf(yearColdCap)); |
||||
resultMap.put("totalColdCap", String.valueOf(totalCap != null ? totalCap : BigDecimal.ZERO)); |
||||
|
||||
resultMap.put("dayEER", calcEER(dayColdCap, dayEle).toString()); |
||||
resultMap.put("monthEER", calcEER(monthColdCap, monthEle).toString()); |
||||
resultMap.put("yearEER", calcEER(yearColdCap, yearEle).toString()); |
||||
resultMap.put("totalEER", calcEER(totalCap, totalEle).toString()); |
||||
} catch (Exception e) { |
||||
log.error("getStatisticalData 计算出现异常", e); |
||||
} |
||||
|
||||
return TableDataInfo.ok(resultMap); |
||||
} |
||||
|
||||
@Override |
||||
public TableDataInfo getCoe() { |
||||
Calendar calendar = Calendar.getInstance(); |
||||
int year = calendar.get(Calendar.YEAR); |
||||
String tableName = "data_min" + year; |
||||
|
||||
// 系统能效系数、主机能效、冷冻泵输送系数、冷却泵输送系数、冷却塔输送系数
|
||||
// 瞬时冷量:mt_num = 39001580(系统总冷量计瞬时冷量)
|
||||
BigDecimal cap = homeMapper.selectLastCalcValueByMtNum(tableName, MT_SYS_COLD_INSTANT); |
||||
// 瞬时用电量:grade=140 所有电力设备,带 other_name 用于分类
|
||||
List<Map<String, Object>> eleList = homeMapper.selectInstantEleWithOtherName(tableName, GRADE_INSTANT); |
||||
|
||||
// 按 other_name 前缀归类
|
||||
BigDecimal sysEle = BigDecimal.ZERO; |
||||
BigDecimal chillerEle = BigDecimal.ZERO; |
||||
BigDecimal chillPumpEle = BigDecimal.ZERO; |
||||
BigDecimal coolPumpEle = BigDecimal.ZERO; |
||||
BigDecimal towerEle = BigDecimal.ZERO; |
||||
|
||||
for (Map<String, Object> ele : eleList) { |
||||
String otherName = (String) ele.get("mt_num"); |
||||
BigDecimal value = (BigDecimal) ele.get("calc_value"); |
||||
if (otherName == null || value == null) { |
||||
continue; |
||||
} |
||||
if (otherName.equals(ON_SYSTEM_POWER)) { |
||||
sysEle = sysEle.add(value); |
||||
} else if (otherName.startsWith(ON_CHILLER_POWER_PREFIX)) { |
||||
chillerEle = chillerEle.add(value); |
||||
} else if (otherName.startsWith(ON_CHILL_PUMP_POWER_PREFIX)) { |
||||
chillPumpEle = chillPumpEle.add(value); |
||||
} else if (otherName.startsWith(ON_COOL_PUMP_POWER_PREFIX)) { |
||||
coolPumpEle = coolPumpEle.add(value); |
||||
} else if (otherName.startsWith(ON_TOWER_POWER_PREFIX)) { |
||||
towerEle = towerEle.add(value); |
||||
} |
||||
} |
||||
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>(8); |
||||
if (cap == null) { |
||||
resultMap.put("sysCoe", null); |
||||
resultMap.put("chillerCoe", null); |
||||
resultMap.put("chillPumpCoe", null); |
||||
resultMap.put("coolPumpCoe", null); |
||||
resultMap.put("towerCoe", null); |
||||
return TableDataInfo.ok(resultMap); |
||||
} |
||||
|
||||
resultMap.put("sysCoe", safeDivide(cap, sysEle)); |
||||
resultMap.put("chillerCoe", safeDivide(cap, chillerEle)); |
||||
resultMap.put("chillPumpCoe", safeDivide(cap, chillPumpEle)); |
||||
resultMap.put("coolPumpCoe", safeDivide(cap, coolPumpEle)); |
||||
resultMap.put("towerCoe", safeDivide(cap, towerEle)); |
||||
|
||||
return TableDataInfo.ok(resultMap); |
||||
} |
||||
|
||||
@Override |
||||
public TableDataInfo getRunTime() { |
||||
// 从运行时长的表中读取系统运行时长的数据
|
||||
long runTime = homeMapper.selectRunTime(); |
||||
return TableDataInfo.ok(runTime); |
||||
} |
||||
|
||||
@Override |
||||
public TableDataInfo getCurrentRate() { |
||||
Calendar calendar = Calendar.getInstance(); |
||||
int year = calendar.get(Calendar.YEAR); |
||||
String tableName = "data_min" + year; |
||||
|
||||
// 实时总用电量:瞬时值(grade=140)所有电力设备最新 calc_value 之和
|
||||
List<String> powerMtNums = safeList( |
||||
homeMapper.queryMtNumsByGradeExcludeMtNumPrefix(GRADE_INSTANT, MT_COLD_PREFIX)); |
||||
double eleUsed = homeMapper.selectLastEle(tableName, powerMtNums); |
||||
BigDecimal power = BigDecimal.valueOf(eleUsed).setScale(2, RoundingMode.HALF_UP); |
||||
|
||||
// 实时产冷量:瞬时冷量表最新值
|
||||
BigDecimal capPower = homeMapper.selectLastCalcValueByMtNum(tableName, MT_SYS_COLD_INSTANT); |
||||
|
||||
Map<String, String> resultMap = new LinkedHashMap<>(4); |
||||
resultMap.put("totalEle", power.toString()); |
||||
resultMap.put("totalCap", capPower != null |
||||
? capPower.setScale(2, RoundingMode.HALF_UP).toString() : "0"); |
||||
|
||||
return TableDataInfo.ok(resultMap); |
||||
} |
||||
|
||||
@Override |
||||
public TableDataInfo getWeatherData() { |
||||
// 获取今天的日期,格式为 yyyy-MM-dd
|
||||
String date = DateUtils.getDate(); |
||||
Map<String, Integer> values = homeMapper.selectWeatherData(date + " 00:00:00", date + " 23:59:59"); |
||||
if (values == null) { |
||||
return TableDataInfo.ok(); |
||||
} |
||||
Map<String, String> result = new LinkedHashMap<>(2); |
||||
result.putIfAbsent("temperature", |
||||
String.valueOf(values.get("temperature"))); |
||||
result.putIfAbsent("humidity", |
||||
String.valueOf(values.get("humidity"))); |
||||
return TableDataInfo.ok(result); |
||||
} |
||||
|
||||
// ==================== 私有辅助方法 ====================
|
||||
|
||||
/** |
||||
* null → 空列表 |
||||
*/ |
||||
private <T> List<T> safeList(List<T> list) { |
||||
return list != null ? list : Collections.emptyList(); |
||||
} |
||||
|
||||
/** |
||||
* 从 Map 安全取值 |
||||
*/ |
||||
private BigDecimal getOrDefault(Map<String, BigDecimal> map, String key) { |
||||
if (map == null) { |
||||
return BigDecimal.ZERO; |
||||
} |
||||
BigDecimal val = map.get(key); |
||||
return val != null ? val : BigDecimal.ZERO; |
||||
} |
||||
|
||||
/** |
||||
* 安全查询,异常时返回空列表 |
||||
*/ |
||||
private List<HistoryEntity> queryOrEmpty(Supplier<List<HistoryEntity>> query) { |
||||
try { |
||||
List<HistoryEntity> result = query.get(); |
||||
return result != null ? result : Collections.emptyList(); |
||||
} catch (Exception e) { |
||||
log.warn("数据查询返回空", e); |
||||
return Collections.emptyList(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 构建单系列图表 |
||||
*/ |
||||
private ChartEntity buildSingleChart(String name, List<HistoryEntity> historyList) { |
||||
if (CollectionUtils.isEmpty(historyList)) { |
||||
return null; |
||||
} |
||||
List<Map<String, Object>> dataList = new ArrayList<>(); |
||||
dataList.add(wrapSeriesData(name, historyList)); |
||||
return buildChart(dataList); |
||||
} |
||||
|
||||
/** |
||||
* 封装单系列数据 |
||||
*/ |
||||
private Map<String, Object> wrapSeriesData(String name, List<HistoryEntity> historyList) { |
||||
Map<String, Object> map = new HashMap<>(4); |
||||
map.put("name", name); |
||||
map.put("value", historyList != null ? historyList : Collections.emptyList()); |
||||
return map; |
||||
} |
||||
|
||||
/** |
||||
* 计算瞬时 EER = 冷量 / 功率(时间对齐) |
||||
*/ |
||||
private List<HistoryEntity> calcInstantEER(List<HistoryEntity> powerHistory, List<HistoryEntity> coldHistory) { |
||||
if (CollectionUtils.isEmpty(powerHistory) || CollectionUtils.isEmpty(coldHistory)) { |
||||
return Collections.emptyList(); |
||||
} |
||||
|
||||
List<HistoryEntity> result = new ArrayList<>(); |
||||
List<HistoryEntity> powerSorted = new ArrayList<>(powerHistory); |
||||
List<HistoryEntity> coldSorted = new ArrayList<>(coldHistory); |
||||
|
||||
powerSorted.sort(Comparator.comparing(HistoryEntity::getDate)); |
||||
coldSorted.sort(Comparator.comparing(HistoryEntity::getDate)); |
||||
|
||||
Iterator<HistoryEntity> powerIt = powerSorted.iterator(); |
||||
Iterator<HistoryEntity> coldIt = coldSorted.iterator(); |
||||
|
||||
HistoryEntity powerItem = powerIt.hasNext() ? powerIt.next() : null; |
||||
HistoryEntity coldItem = coldIt.hasNext() ? coldIt.next() : null; |
||||
|
||||
while (powerItem != null && coldItem != null) { |
||||
int timeCompare = powerItem.getDate().compareTo(coldItem.getDate()); |
||||
if (timeCompare == 0) { |
||||
double divideValue = 0; |
||||
if (powerItem.getValue() > 0 && coldItem.getValue() >= 0) { |
||||
divideValue = coldItem.getValue() / powerItem.getValue(); |
||||
} |
||||
divideValue = BigDecimal.valueOf(divideValue) |
||||
.setScale(2, RoundingMode.HALF_UP).doubleValue(); |
||||
|
||||
HistoryEntity entity = new HistoryEntity(); |
||||
entity.setDate(powerItem.getDate()); |
||||
entity.setValue(divideValue); |
||||
result.add(entity); |
||||
|
||||
powerItem = powerIt.hasNext() ? powerIt.next() : null; |
||||
coldItem = coldIt.hasNext() ? coldIt.next() : null; |
||||
} else if (timeCompare < 0) { |
||||
powerItem = powerIt.hasNext() ? powerIt.next() : null; |
||||
} else { |
||||
coldItem = coldIt.hasNext() ? coldIt.next() : null; |
||||
} |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* 计算 EER 系数 |
||||
*/ |
||||
private BigDecimal calcEER(BigDecimal cap, BigDecimal ele) { |
||||
if (cap == null || ele == null |
||||
|| cap.compareTo(BigDecimal.ZERO) == 0 |
||||
|| ele.compareTo(BigDecimal.ZERO) == 0) { |
||||
return BigDecimal.ZERO; |
||||
} |
||||
return cap.divide(ele, 2, RoundingMode.HALF_UP); |
||||
} |
||||
|
||||
/** |
||||
* 安全除法,分子或除数为0/null时返回null |
||||
*/ |
||||
private BigDecimal safeDivide(BigDecimal numerator, BigDecimal denominator) { |
||||
if (numerator == null || denominator == null |
||||
|| denominator.compareTo(BigDecimal.ZERO) == 0) { |
||||
return null; |
||||
} |
||||
return numerator.divide(denominator, 2, RoundingMode.HALF_UP); |
||||
} |
||||
|
||||
/** |
||||
* 构建 chart 图表数据 |
||||
* |
||||
* @param dealDatas 图表数据列表,每个元素包含 name 和 value |
||||
* @return ChartEntity 图表实体 |
||||
*/ |
||||
private ChartEntity buildChart(List<Map<String, Object>> dealDatas) { |
||||
if (CollectionUtils.isEmpty(dealDatas)) { |
||||
return null; |
||||
} |
||||
|
||||
ChartEntity chartEntity = new ChartEntity(); |
||||
chartEntity.setToolTip(new ToolTip("axis")); |
||||
chartEntity.setLegend(new Legend()); |
||||
List<Series> seriesList = new ArrayList<>(); |
||||
|
||||
for (Map<String, Object> dealData : dealDatas) { |
||||
if (CollectionUtils.isEmpty(dealData)) { |
||||
continue; |
||||
} |
||||
String name = (String) dealData.get("name"); |
||||
@SuppressWarnings("unchecked") |
||||
List<HistoryEntity> data = (List<HistoryEntity>) dealData.get("value"); |
||||
if (CollectionUtils.isEmpty(data)) { |
||||
continue; |
||||
} |
||||
Double[] values = data.stream() |
||||
.map(HistoryEntity::getValue).toArray(Double[]::new); |
||||
Series series = new Series(name, "line", 0, values, "average"); |
||||
chartEntity.setXAxis(new XAxis(data.stream() |
||||
.map(HistoryEntity::getDate).toArray(String[]::new))); |
||||
seriesList.add(series); |
||||
} |
||||
chartEntity.setSeries(seriesList); |
||||
return chartEntity; |
||||
} |
||||
} |
||||
Loading…
Reference in new issue