高效能源监控管理系统
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

392 lines
21 KiB

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;
}
}