|
|
|
|
@ -28,6 +28,7 @@ import javax.annotation.Resource;
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
|
|
import java.nio.charset.StandardCharsets;
|
|
|
|
|
import java.text.DecimalFormat;
|
|
|
|
|
import java.text.SimpleDateFormat;
|
|
|
|
|
import java.time.LocalDateTime;
|
|
|
|
|
import java.util.*;
|
|
|
|
|
|
|
|
|
|
@ -253,8 +254,14 @@ public class EnergyDeviceServiceImpl implements EnergyDeviceService {
|
|
|
|
|
List<EnergyDeviceRespVO> result = new ArrayList<>();
|
|
|
|
|
List<EnergyDeviceDO> energyDeviceDO = energyDeviceMapper.selectList(
|
|
|
|
|
Wrappers.<EnergyDeviceDO>lambdaQuery()
|
|
|
|
|
.in(StringUtils.isNotBlank(deviceConsumptionReqVO.getIds()),
|
|
|
|
|
EnergyDeviceDO::getId,
|
|
|
|
|
StringUtils.isNotBlank(deviceConsumptionReqVO.getIds())
|
|
|
|
|
? Arrays.asList(deviceConsumptionReqVO.getIds().split(","))
|
|
|
|
|
: null)
|
|
|
|
|
.like(StringUtils.isNotBlank(deviceConsumptionReqVO.getName()), EnergyDeviceDO::getName, deviceConsumptionReqVO.getName())
|
|
|
|
|
.eq(deviceConsumptionReqVO.getOrgId() != null, EnergyDeviceDO::getOrgId, deviceConsumptionReqVO.getOrgId()));
|
|
|
|
|
.eq(deviceConsumptionReqVO.getOrgId() != null, EnergyDeviceDO::getOrgId, deviceConsumptionReqVO.getOrgId())
|
|
|
|
|
.orderByDesc(EnergyDeviceDO::getCreateTime));
|
|
|
|
|
|
|
|
|
|
if (energyDeviceDO == null || energyDeviceDO.isEmpty()) {
|
|
|
|
|
throw exception(ENERGY_LIST_NOT_EXISTS);
|
|
|
|
|
@ -330,13 +337,127 @@ public class EnergyDeviceServiceImpl implements EnergyDeviceService {
|
|
|
|
|
respVO.setEnergyConsumption("0.0");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置每个点位参数的差值,key为点位参数名称
|
|
|
|
|
Map<String, String> operationRulesVOMap = buildPointDifferenceMap(calculationResult, deviceDO, rules);
|
|
|
|
|
respVO.setOperationRulesVOMap(operationRulesVOMap);
|
|
|
|
|
// 设置最新和最晚数据时间
|
|
|
|
|
if (StringUtils.isNotBlank(startTime)) {
|
|
|
|
|
respVO.setEarliestDataTime(formatDateTime(startTime, "yyyy-MM-dd HH:mm"));
|
|
|
|
|
}
|
|
|
|
|
if (StringUtils.isNotBlank(endTime)) {
|
|
|
|
|
respVO.setLatestDataTime(formatDateTime(endTime, "yyyy-MM-dd HH:mm"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 构建点位详情列表
|
|
|
|
|
List<PointDetailVO> pointDetails = buildPointDetails(calculationResult, deviceDO, rules);
|
|
|
|
|
respVO.setPointDetails(pointDetails);
|
|
|
|
|
|
|
|
|
|
return respVO;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 格式化时间为指定格式
|
|
|
|
|
*/
|
|
|
|
|
private String formatDateTime(String time, String pattern) {
|
|
|
|
|
if (StringUtils.isBlank(time)) {
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// 常见时间格式列表
|
|
|
|
|
String[] possiblePatterns = {
|
|
|
|
|
"yyyy-MM-dd HH:mm:ss",
|
|
|
|
|
"yyyy-MM-dd HH:mm:ss.SSS",
|
|
|
|
|
"yyyy-MM-dd'T'HH:mm:ss",
|
|
|
|
|
"yyyy-MM-dd'T'HH:mm:ss.SSS",
|
|
|
|
|
"yyyy/MM/dd HH:mm:ss",
|
|
|
|
|
"yyyy-MM-dd HH:mm"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
for (String possiblePattern : possiblePatterns) {
|
|
|
|
|
try {
|
|
|
|
|
SimpleDateFormat sdf = new SimpleDateFormat(possiblePattern);
|
|
|
|
|
Date date = sdf.parse(time);
|
|
|
|
|
SimpleDateFormat targetFormat = new SimpleDateFormat(pattern);
|
|
|
|
|
return targetFormat.format(date);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果解析失败,尝试简单截取
|
|
|
|
|
if (time.length() >= 16) {
|
|
|
|
|
return time.substring(0, 16);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.warn("时间格式化失败: {}", time, e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return time;
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* 从数据中获取时间
|
|
|
|
|
*/
|
|
|
|
|
/**
|
|
|
|
|
* 从数据中获取时间,格式化为 yyyy-MM-dd HH:mm:ss
|
|
|
|
|
*/
|
|
|
|
|
private String getTimeFromData(Map<String, Object> calculationResult, String dataKey) {
|
|
|
|
|
if (calculationResult == null || dataKey == null) {
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Map<String, Object> timeData = (Map<String, Object>) calculationResult.get(dataKey);
|
|
|
|
|
if (timeData == null) {
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Object timestamp = timeData.get("timestamp");
|
|
|
|
|
if (timestamp == null) {
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String timeStr = timestamp.toString();
|
|
|
|
|
|
|
|
|
|
// 如果已经是目标格式的长度,直接返回
|
|
|
|
|
if (timeStr.length() == 19) { // yyyy-MM-dd HH:mm:ss
|
|
|
|
|
return timeStr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果有毫秒部分,截取前19位
|
|
|
|
|
if (timeStr.length() > 19 && timeStr.charAt(19) == '.') {
|
|
|
|
|
return timeStr.substring(0, 19);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果是其他格式,尝试解析
|
|
|
|
|
try {
|
|
|
|
|
// 移除毫秒部分
|
|
|
|
|
if (timeStr.contains(".")) {
|
|
|
|
|
timeStr = timeStr.substring(0, timeStr.indexOf("."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 确保格式正确
|
|
|
|
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
|
|
|
|
SimpleDateFormat originalSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// 尝试用带毫秒的格式解析
|
|
|
|
|
Date date = originalSdf.parse(timeStr);
|
|
|
|
|
return sdf.format(date);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
// 尝试不带毫秒解析
|
|
|
|
|
try {
|
|
|
|
|
Date date = sdf.parse(timeStr);
|
|
|
|
|
return sdf.format(date);
|
|
|
|
|
} catch (Exception e2) {
|
|
|
|
|
// 如果不是标准格式,只做简单截取
|
|
|
|
|
if (timeStr.length() > 19) {
|
|
|
|
|
return timeStr.substring(0, Math.min(19, timeStr.length()));
|
|
|
|
|
}
|
|
|
|
|
return timeStr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
return timeStr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 从查询结果中提取特定点位的数据
|
|
|
|
|
@ -357,8 +478,8 @@ public class EnergyDeviceServiceImpl implements EnergyDeviceService {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 处理编码问题
|
|
|
|
|
queryData = fixEncoding(queryData);
|
|
|
|
|
// // 处理编码问题
|
|
|
|
|
// queryData = fixEncoding(queryData);
|
|
|
|
|
|
|
|
|
|
// 解析JSON数组
|
|
|
|
|
JSONArray jsonArray = JSON.parseArray(queryData);
|
|
|
|
|
@ -475,6 +596,10 @@ public class EnergyDeviceServiceImpl implements EnergyDeviceService {
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 提取实际采集时间
|
|
|
|
|
String latestTime = extractTimestamp(latestData);
|
|
|
|
|
String earliestTime = extractTimestamp(earliestData);
|
|
|
|
|
|
|
|
|
|
// 使用相同的规则计算两个时间点的总值
|
|
|
|
|
Double latestTotal = calculateTotalByRules(latestData, rules);
|
|
|
|
|
Double earliestTotal = calculateTotalByRules(earliestData, rules);
|
|
|
|
|
@ -484,6 +609,8 @@ public class EnergyDeviceServiceImpl implements EnergyDeviceService {
|
|
|
|
|
|
|
|
|
|
result.put("latestData", latestData);
|
|
|
|
|
result.put("earliestData", earliestData);
|
|
|
|
|
result.put("latestTime", latestTime);
|
|
|
|
|
result.put("earliestTime", earliestTime);
|
|
|
|
|
result.put("latestTotal", latestTotal != null ? latestTotal : 0.0);
|
|
|
|
|
result.put("earliestTotal", earliestTotal != null ? earliestTotal : 0.0);
|
|
|
|
|
result.put("totalDifference", (latestTotal != null && earliestTotal != null) ?
|
|
|
|
|
@ -497,6 +624,22 @@ public class EnergyDeviceServiceImpl implements EnergyDeviceService {
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 从数据中提取时间戳
|
|
|
|
|
*/
|
|
|
|
|
private String extractTimestamp(Map<String, Object> timePointData) {
|
|
|
|
|
if (timePointData == null) {
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Object timestamp = timePointData.get("timestamp");
|
|
|
|
|
if (timestamp != null) {
|
|
|
|
|
return timestamp.toString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 从设备数据中获取点位值
|
|
|
|
|
*/
|
|
|
|
|
@ -754,12 +897,13 @@ public class EnergyDeviceServiceImpl implements EnergyDeviceService {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 优化:批量构建点位差值Map
|
|
|
|
|
* 构建点位详情列表
|
|
|
|
|
* 包含:点位名称、最早值、最晚值、相差值、时间、单位等信息
|
|
|
|
|
*/
|
|
|
|
|
private Map<String, String> buildPointDifferenceMap(Map<String, Object> calculationResult,
|
|
|
|
|
EnergyDeviceDO deviceDO,
|
|
|
|
|
List<OperationRulesVO> originalRules) {
|
|
|
|
|
Map<String, String> result = new HashMap<>();
|
|
|
|
|
private List<PointDetailVO> buildPointDetails(Map<String, Object> calculationResult,
|
|
|
|
|
EnergyDeviceDO deviceDO,
|
|
|
|
|
List<OperationRulesVO> originalRules) {
|
|
|
|
|
List<PointDetailVO> result = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
if (calculationResult == null || originalRules == null || originalRules.isEmpty()) {
|
|
|
|
|
return result;
|
|
|
|
|
@ -770,8 +914,8 @@ public class EnergyDeviceServiceImpl implements EnergyDeviceService {
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取最新数据用于获取点位名称
|
|
|
|
|
Map<String, Object> latestData = (Map<String, Object>) calculationResult.get("latestData");
|
|
|
|
|
Map<String, Object> earliestData = (Map<String, Object>) calculationResult.get("earliestData");
|
|
|
|
|
|
|
|
|
|
// 收集所有点位ID
|
|
|
|
|
List<Long> allPointIds = new ArrayList<>();
|
|
|
|
|
@ -782,37 +926,300 @@ public class EnergyDeviceServiceImpl implements EnergyDeviceService {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 批量从本地数据库获取点位名称
|
|
|
|
|
Map<Long, String> pointNameMap = batchGetPointNamesFromLocalDB(allPointIds);
|
|
|
|
|
// 批量从本地数据库获取点位信息
|
|
|
|
|
Map<Long, DeviceContactModelDO> pointInfoMap = batchGetPointInfoFromLocalDB(allPointIds);
|
|
|
|
|
|
|
|
|
|
for (Map<String, Object> pointDiff : pointDifferences) {
|
|
|
|
|
Long pointId = (Long) pointDiff.get("pointId");
|
|
|
|
|
Long deviceId = (Long) pointDiff.get("deviceId");
|
|
|
|
|
|
|
|
|
|
if (pointId == null) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取点位名称
|
|
|
|
|
String pointName = null;
|
|
|
|
|
// 获取点位详细信息
|
|
|
|
|
PointDetailVO pointDetail = new PointDetailVO();
|
|
|
|
|
pointDetail.setPointId(pointId);
|
|
|
|
|
pointDetail.setDeviceId(deviceId);
|
|
|
|
|
|
|
|
|
|
// 设置运算符
|
|
|
|
|
String operator = (String) pointDiff.get("operator");
|
|
|
|
|
pointDetail.setOperator(operator != null ? operator : "");
|
|
|
|
|
|
|
|
|
|
// 1. 尝试从TD数据库获取
|
|
|
|
|
pointName = getPointNameFromTDData(latestData, pointId, pointDiff);
|
|
|
|
|
// 从TD数据获取点位信息和实际采集时间
|
|
|
|
|
setPointDataFromTD(pointDetail, latestData, earliestData, pointId, deviceId, pointDiff);
|
|
|
|
|
|
|
|
|
|
// 2. 如果TD数据库没有,从本地数据库获取
|
|
|
|
|
if (StringUtils.isBlank(pointName)) {
|
|
|
|
|
pointName = pointNameMap.get(pointId);
|
|
|
|
|
// 如果没有从TD数据获取到点位名称,从本地数据库获取
|
|
|
|
|
if (StringUtils.isBlank(pointDetail.getPointName())) {
|
|
|
|
|
setPointInfoFromLocalDB(pointDetail, pointInfoMap.get(pointId));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取差值
|
|
|
|
|
// 如果没有单位,尝试从本地数据库获取
|
|
|
|
|
if (StringUtils.isBlank(pointDetail.getUnit())) {
|
|
|
|
|
setPointUnitFromLocalDB(pointDetail, pointInfoMap.get(pointId));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置数值
|
|
|
|
|
Double earliestValue = (Double) pointDiff.get("earliestValue");
|
|
|
|
|
Double latestValue = (Double) pointDiff.get("latestValue");
|
|
|
|
|
Double difference = (Double) pointDiff.get("difference");
|
|
|
|
|
String differenceStr = formatDouble(difference != null ? difference : 0.0);
|
|
|
|
|
|
|
|
|
|
// 以点位名称为key,差值为value
|
|
|
|
|
if (StringUtils.isNotBlank(pointName)) {
|
|
|
|
|
result.put(pointName, differenceStr);
|
|
|
|
|
pointDetail.setEarliestValue(formatDouble(earliestValue != null ? earliestValue : 0.0));
|
|
|
|
|
pointDetail.setLatestValue(formatDouble(latestValue != null ? latestValue : 0.0));
|
|
|
|
|
pointDetail.setDifference(formatDouble(difference != null ? difference : 0.0));
|
|
|
|
|
|
|
|
|
|
result.add(pointDetail);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 从TD数据库数据中获取点位详细信息
|
|
|
|
|
*/
|
|
|
|
|
private void setPointDataFromTD(PointDetailVO pointDetail,
|
|
|
|
|
Map<String, Object> latestData,
|
|
|
|
|
Map<String, Object> earliestData,
|
|
|
|
|
Long pointId,
|
|
|
|
|
Long deviceId,
|
|
|
|
|
Map<String, Object> pointDiff) {
|
|
|
|
|
|
|
|
|
|
// 获取最新数据的时间
|
|
|
|
|
if (latestData != null) {
|
|
|
|
|
String deviceKey = "device_" + deviceId;
|
|
|
|
|
Map<String, Object> deviceData = (Map<String, Object>) latestData.get(deviceKey);
|
|
|
|
|
if (deviceData != null) {
|
|
|
|
|
Object timestamp = deviceData.get("timestamp");
|
|
|
|
|
if (timestamp != null) {
|
|
|
|
|
pointDetail.setLatestTime(formatToFullTime(timestamp.toString()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取最早数据的时间
|
|
|
|
|
if (earliestData != null) {
|
|
|
|
|
String deviceKey = "device_" + deviceId;
|
|
|
|
|
Map<String, Object> deviceData = (Map<String, Object>) earliestData.get(deviceKey);
|
|
|
|
|
if (deviceData != null) {
|
|
|
|
|
Object timestamp = deviceData.get("timestamp");
|
|
|
|
|
if (timestamp != null) {
|
|
|
|
|
pointDetail.setEarliestTime(formatToFullTime(timestamp.toString()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 从最新数据获取点位名称和单位
|
|
|
|
|
if (latestData != null) {
|
|
|
|
|
String deviceKey = "device_" + deviceId;
|
|
|
|
|
Map<String, Object> deviceData = (Map<String, Object>) latestData.get(deviceKey);
|
|
|
|
|
if (deviceData != null) {
|
|
|
|
|
Map<String, Object> pointData = getPointData(deviceData, pointId);
|
|
|
|
|
if (pointData != null) {
|
|
|
|
|
// 获取点位名称
|
|
|
|
|
String pointName = (String) pointData.get("attributeName");
|
|
|
|
|
if (StringUtils.isNotBlank(pointName)) {
|
|
|
|
|
pointDetail.setPointName(pointName);
|
|
|
|
|
} else {
|
|
|
|
|
pointName = (String) pointData.get("attributeCode");
|
|
|
|
|
if (StringUtils.isNotBlank(pointName)) {
|
|
|
|
|
pointDetail.setPointName(pointName);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取单位
|
|
|
|
|
String unit = (String) pointData.get("dataUnit");
|
|
|
|
|
if (StringUtils.isNotBlank(unit)) {
|
|
|
|
|
pointDetail.setUnit(unit);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 格式化为完整时间 yyyy-MM-dd HH:mm:ss
|
|
|
|
|
*/
|
|
|
|
|
private String formatToFullTime(String time) {
|
|
|
|
|
if (StringUtils.isBlank(time)) {
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
String timeStr = time.trim();
|
|
|
|
|
|
|
|
|
|
// 1. 如果已经是 yyyy-MM-dd HH:mm:ss 格式
|
|
|
|
|
if (timeStr.length() >= 19 && timeStr.charAt(4) == '-' && timeStr.charAt(10) == ' ') {
|
|
|
|
|
if (timeStr.length() == 19) {
|
|
|
|
|
return timeStr; // 直接返回
|
|
|
|
|
} else {
|
|
|
|
|
return timeStr.substring(0, 19); // 截取前19位
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2. ISO格式: 2024-01-15T14:30:00.000+08:00
|
|
|
|
|
if (timeStr.contains("T")) {
|
|
|
|
|
timeStr = timeStr.replace("T", " ");
|
|
|
|
|
int dotIndex = timeStr.indexOf(".");
|
|
|
|
|
if (dotIndex > 0) {
|
|
|
|
|
timeStr = timeStr.substring(0, dotIndex);
|
|
|
|
|
} else {
|
|
|
|
|
int plusIndex = Math.min(timeStr.indexOf("+"), timeStr.indexOf("-", 11));
|
|
|
|
|
if (plusIndex > 0) {
|
|
|
|
|
timeStr = timeStr.substring(0, plusIndex);
|
|
|
|
|
} else if (timeStr.contains("Z")) {
|
|
|
|
|
timeStr = timeStr.substring(0, timeStr.indexOf("Z"));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return timeStr.length() >= 19 ? timeStr.substring(0, 19) : timeStr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 3. 尝试解析
|
|
|
|
|
String[] patterns = {
|
|
|
|
|
"yyyy-MM-dd HH:mm:ss",
|
|
|
|
|
"yyyy-MM-dd HH:mm:ss.SSS",
|
|
|
|
|
"yyyy-MM-dd'T'HH:mm:ss",
|
|
|
|
|
"yyyy-MM-dd'T'HH:mm:ss.SSS",
|
|
|
|
|
"yyyy/MM/dd HH:mm:ss",
|
|
|
|
|
"yyyy/MM/dd HH:mm:ss.SSS"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
for (String pattern : patterns) {
|
|
|
|
|
try {
|
|
|
|
|
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
|
|
|
|
|
Date date = sdf.parse(timeStr);
|
|
|
|
|
SimpleDateFormat targetFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
|
|
|
|
return targetFormat.format(date);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.warn("时间格式化失败: {}", time, e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return time;
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* 从时间戳中提取时分秒
|
|
|
|
|
*/
|
|
|
|
|
private String extractHMSFromTimestamp(String timestamp) {
|
|
|
|
|
if (StringUtils.isBlank(timestamp)) {
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
String timeStr = timestamp.trim();
|
|
|
|
|
|
|
|
|
|
// 处理多种格式
|
|
|
|
|
// 1. 标准格式: yyyy-MM-dd HH:mm:ss
|
|
|
|
|
if (timeStr.length() >= 19) {
|
|
|
|
|
return timeStr.substring(11, 19); // 提取 HH:mm:ss
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2. ISO格式: 2024-01-15T14:30:00.000+08:00
|
|
|
|
|
if (timeStr.contains("T")) {
|
|
|
|
|
int tIndex = timeStr.indexOf("T");
|
|
|
|
|
int dotIndex = timeStr.indexOf(".");
|
|
|
|
|
if (dotIndex > tIndex) {
|
|
|
|
|
return timeStr.substring(tIndex + 1, dotIndex);
|
|
|
|
|
} else {
|
|
|
|
|
int plusIndex = timeStr.indexOf("+");
|
|
|
|
|
if (plusIndex > tIndex) {
|
|
|
|
|
return timeStr.substring(tIndex + 1, plusIndex);
|
|
|
|
|
} else if (timeStr.contains("Z") && timeStr.indexOf("Z") > tIndex) {
|
|
|
|
|
int zIndex = timeStr.indexOf("Z");
|
|
|
|
|
return timeStr.substring(tIndex + 1, zIndex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 3. 如果是 HH:mm:ss 格式
|
|
|
|
|
if (timeStr.matches("\\d{1,2}:\\d{1,2}:\\d{1,2}")) {
|
|
|
|
|
return timeStr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 4. 尝试解析
|
|
|
|
|
try {
|
|
|
|
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
|
|
|
|
Date date = sdf.parse(timeStr);
|
|
|
|
|
SimpleDateFormat hmsFormat = new SimpleDateFormat("HH:mm:ss");
|
|
|
|
|
return hmsFormat.format(date);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
// 继续尝试其他格式
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
|
|
|
|
Date date = sdf.parse(timeStr);
|
|
|
|
|
SimpleDateFormat hmsFormat = new SimpleDateFormat("HH:mm:ss");
|
|
|
|
|
return hmsFormat.format(date);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
// 解析失败
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.warn("时间格式解析失败: {}", timestamp, e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return timestamp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 从本地数据库获取点位信息
|
|
|
|
|
*/
|
|
|
|
|
private void setPointInfoFromLocalDB(PointDetailVO pointDetail, DeviceContactModelDO pointInfo) {
|
|
|
|
|
if (pointDetail == null || pointInfo == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (StringUtils.isBlank(pointDetail.getPointName())) {
|
|
|
|
|
if (StringUtils.isNotBlank(pointInfo.getAttributeName())) {
|
|
|
|
|
pointDetail.setPointName(pointInfo.getAttributeName());
|
|
|
|
|
} else if (StringUtils.isNotBlank(pointInfo.getAttributeCode())) {
|
|
|
|
|
pointDetail.setPointName(pointInfo.getAttributeCode());
|
|
|
|
|
} else {
|
|
|
|
|
// 如果还没有点位名称,使用点位ID作为key
|
|
|
|
|
result.put("点位" + pointId, differenceStr);
|
|
|
|
|
pointDetail.setPointName("点位" + pointDetail.getPointId());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 从本地数据库获取点位单位
|
|
|
|
|
*/
|
|
|
|
|
private void setPointUnitFromLocalDB(PointDetailVO pointDetail, DeviceContactModelDO pointInfo) {
|
|
|
|
|
if (pointDetail == null || pointInfo == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (StringUtils.isBlank(pointDetail.getUnit())) {
|
|
|
|
|
if (StringUtils.isNotBlank(pointInfo.getDataUnit())) {
|
|
|
|
|
pointDetail.setUnit(pointInfo.getDataUnit());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 批量获取点位信息(优化性能)
|
|
|
|
|
*/
|
|
|
|
|
private Map<Long, DeviceContactModelDO> batchGetPointInfoFromLocalDB(List<Long> pointIds) {
|
|
|
|
|
Map<Long, DeviceContactModelDO> result = new HashMap<>();
|
|
|
|
|
|
|
|
|
|
if (pointIds == null || pointIds.isEmpty()) {
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
List<DeviceContactModelDO> deviceContacts = deviceContactModelMapper.selectBatchIds(pointIds);
|
|
|
|
|
if (deviceContacts != null && !deviceContacts.isEmpty()) {
|
|
|
|
|
for (DeviceContactModelDO deviceContact : deviceContacts) {
|
|
|
|
|
if (deviceContact != null && deviceContact.getId() != null) {
|
|
|
|
|
result.put(deviceContact.getId(), deviceContact);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.error("批量查询点位信息失败, pointIds: {}", pointIds, e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|