|
@@ -1,6 +1,7 @@
|
|
|
package com.usky.vpp.service.impl;
|
|
package com.usky.vpp.service.impl;
|
|
|
|
|
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
|
|
+import com.usky.common.core.exception.BusinessException;
|
|
|
import com.usky.common.security.utils.SecurityUtils;
|
|
import com.usky.common.security.utils.SecurityUtils;
|
|
|
import com.usky.vpp.constant.VppTsdbConstants;
|
|
import com.usky.vpp.constant.VppTsdbConstants;
|
|
|
import com.usky.vpp.domain.VppDevice;
|
|
import com.usky.vpp.domain.VppDevice;
|
|
@@ -11,6 +12,9 @@ import com.usky.vpp.service.VppResourceOverviewService;
|
|
|
import com.usky.vpp.service.VppTsdbQueryService;
|
|
import com.usky.vpp.service.VppTsdbQueryService;
|
|
|
import com.usky.vpp.service.vo.AlarmLevelStatVO;
|
|
import com.usky.vpp.service.vo.AlarmLevelStatVO;
|
|
|
import com.usky.vpp.service.vo.EnergyTodayVO;
|
|
import com.usky.vpp.service.vo.EnergyTodayVO;
|
|
|
|
|
+import com.usky.vpp.service.vo.ResourceCurvePointVO;
|
|
|
|
|
+import com.usky.vpp.service.vo.ResourceCurveSeriesVO;
|
|
|
|
|
+import com.usky.vpp.service.vo.ResourceOverviewRealtimeCurveVO;
|
|
|
import com.usky.vpp.service.vo.ResourceTypeStatVO;
|
|
import com.usky.vpp.service.vo.ResourceTypeStatVO;
|
|
|
import com.usky.vpp.util.VppAuditHelper;
|
|
import com.usky.vpp.util.VppAuditHelper;
|
|
|
import com.usky.vpp.util.VppResourceMockHelper;
|
|
import com.usky.vpp.util.VppResourceMockHelper;
|
|
@@ -23,9 +27,13 @@ import java.math.BigDecimal;
|
|
|
import java.math.RoundingMode;
|
|
import java.math.RoundingMode;
|
|
|
import java.time.LocalDate;
|
|
import java.time.LocalDate;
|
|
|
import java.time.LocalDateTime;
|
|
import java.time.LocalDateTime;
|
|
|
|
|
+import java.time.format.DateTimeFormatter;
|
|
|
|
|
+import java.time.format.DateTimeParseException;
|
|
|
|
|
+import java.time.temporal.ChronoUnit;
|
|
|
import java.util.ArrayList;
|
|
import java.util.ArrayList;
|
|
|
import java.util.Arrays;
|
|
import java.util.Arrays;
|
|
|
import java.util.Collections;
|
|
import java.util.Collections;
|
|
|
|
|
+import java.util.HashMap;
|
|
|
import java.util.LinkedHashMap;
|
|
import java.util.LinkedHashMap;
|
|
|
import java.util.LinkedHashSet;
|
|
import java.util.LinkedHashSet;
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
@@ -39,6 +47,8 @@ import java.util.stream.Collectors;
|
|
|
public class VppResourceOverviewServiceImpl implements VppResourceOverviewService {
|
|
public class VppResourceOverviewServiceImpl implements VppResourceOverviewService {
|
|
|
|
|
|
|
|
private static final List<String> RESOURCE_TYPES = Arrays.asList("PV", "ESS", "EVCS", "IND_LOAD", "COM_BLDG");
|
|
private static final List<String> RESOURCE_TYPES = Arrays.asList("PV", "ESS", "EVCS", "IND_LOAD", "COM_BLDG");
|
|
|
|
|
+ private static final DateTimeFormatter TIME_HH_MM = DateTimeFormatter.ofPattern("HH:mm");
|
|
|
|
|
+ private static final DateTimeFormatter TSDB_TIME = DateTimeFormatter.ofPattern(VppTsdbConstants.TIME_FORMAT);
|
|
|
|
|
|
|
|
@Autowired
|
|
@Autowired
|
|
|
private VppResourcePointMapper resourcePointMapper;
|
|
private VppResourcePointMapper resourcePointMapper;
|
|
@@ -64,6 +74,27 @@ public class VppResourceOverviewServiceImpl implements VppResourceOverviewServic
|
|
|
return buildAlarmStatsMock();
|
|
return buildAlarmStatsMock();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public ResourceOverviewRealtimeCurveVO getRealtimeCurves(String startTime, String endTime) {
|
|
|
|
|
+ LocalDateTime end = parseDateTime(endTime, LocalDateTime.now());
|
|
|
|
|
+ LocalDateTime start = parseDateTime(startTime, LocalDate.now().atStartOfDay());
|
|
|
|
|
+ if (start.isAfter(end)) {
|
|
|
|
|
+ throw new BusinessException("开始时间不能晚于结束时间");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ List<VppDevice> devices = listActiveDevices();
|
|
|
|
|
+ Map<Long, String> deviceResourceTypeMap = buildDeviceResourceTypeMap();
|
|
|
|
|
+ List<String> allDeviceUuids = resolveDeviceUuids(devices);
|
|
|
|
|
+ List<String> pvDeviceUuids = resolveDeviceUuidsByResourceType(devices, deviceResourceTypeMap, "PV");
|
|
|
|
|
+ List<String> essDeviceUuids = resolveDeviceUuidsByResourceType(devices, deviceResourceTypeMap, "ESS");
|
|
|
|
|
+
|
|
|
|
|
+ ResourceOverviewRealtimeCurveVO curve = new ResourceOverviewRealtimeCurveVO();
|
|
|
|
|
+ curve.setLoadCurve(buildPowerCurveSeries("实时负荷曲线", "kW", allDeviceUuids, start, end));
|
|
|
|
|
+ curve.setPvOutputCurve(buildPowerCurveSeries("光伏出力曲线", "kW", pvDeviceUuids, start, end));
|
|
|
|
|
+ curve.setEssSocCurve(buildSocCurveSeries("储能SOC曲线", essDeviceUuids, start, end));
|
|
|
|
|
+ return curve;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private List<VppResourcePoint> listActiveResources() {
|
|
private List<VppResourcePoint> listActiveResources() {
|
|
|
return resourcePointMapper.selectList(
|
|
return resourcePointMapper.selectList(
|
|
|
new LambdaQueryWrapper<VppResourcePoint>()
|
|
new LambdaQueryWrapper<VppResourcePoint>()
|
|
@@ -71,6 +102,176 @@ public class VppResourceOverviewServiceImpl implements VppResourceOverviewServic
|
|
|
.eq(VppResourcePoint::getTenantId, SecurityUtils.getTenantId()));
|
|
.eq(VppResourcePoint::getTenantId, SecurityUtils.getTenantId()));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ private List<VppDevice> listActiveDevices() {
|
|
|
|
|
+ return deviceMapper.selectList(
|
|
|
|
|
+ new LambdaQueryWrapper<VppDevice>()
|
|
|
|
|
+ .eq(VppDevice::getDeleteFlag, VppAuditHelper.NOT_DELETED)
|
|
|
|
|
+ .eq(VppDevice::getTenantId, SecurityUtils.getTenantId()));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private Map<Long, String> buildDeviceResourceTypeMap() {
|
|
|
|
|
+ Map<Long, String> deviceResourceTypeMap = new HashMap<>();
|
|
|
|
|
+ for (VppResourcePoint resource : listActiveResources()) {
|
|
|
|
|
+ if (resource.getDeviceId() == null || !StringUtils.hasText(resource.getResourceType())) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ deviceResourceTypeMap.putIfAbsent(resource.getDeviceId(), resource.getResourceType().toUpperCase());
|
|
|
|
|
+ }
|
|
|
|
|
+ return deviceResourceTypeMap;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private ResourceCurveSeriesVO buildPowerCurveSeries(String name, String unit, List<String> deviceUuids,
|
|
|
|
|
+ LocalDateTime start, LocalDateTime end) {
|
|
|
|
|
+ Map<LocalDateTime, BigDecimal> aggregated = queryAggregatedSum(deviceUuids, start, end,
|
|
|
|
|
+ Collections.singletonList(VppTsdbConstants.METRIC_P));
|
|
|
|
|
+ return toCurveSeries(name, unit, aggregated);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private ResourceCurveSeriesVO buildSocCurveSeries(String name, List<String> deviceUuids,
|
|
|
|
|
+ LocalDateTime start, LocalDateTime end) {
|
|
|
|
|
+ Map<LocalDateTime, BigDecimal> aggregated = queryAggregatedAverage(deviceUuids, start, end,
|
|
|
|
|
+ Collections.singletonList(VppTsdbConstants.METRIC_SOC));
|
|
|
|
|
+ return toCurveSeries(name, "%", aggregated);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private Map<LocalDateTime, BigDecimal> queryAggregatedSum(List<String> deviceUuids, LocalDateTime start,
|
|
|
|
|
+ LocalDateTime end, List<String> metrics) {
|
|
|
|
|
+ if (CollectionUtils.isEmpty(deviceUuids)) {
|
|
|
|
|
+ return Collections.emptyMap();
|
|
|
|
|
+ }
|
|
|
|
|
+ Map<String, Map<String, TreeMap<LocalDateTime, BigDecimal>>> history =
|
|
|
|
|
+ vppTsdbQueryService.queryDeviceMetricHistory(deviceUuids, start, end, metrics);
|
|
|
|
|
+ return aggregateSumByTime(history, metrics.get(0));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private Map<LocalDateTime, BigDecimal> queryAggregatedAverage(List<String> deviceUuids, LocalDateTime start,
|
|
|
|
|
+ LocalDateTime end, List<String> metrics) {
|
|
|
|
|
+ if (CollectionUtils.isEmpty(deviceUuids)) {
|
|
|
|
|
+ return Collections.emptyMap();
|
|
|
|
|
+ }
|
|
|
|
|
+ Map<String, Map<String, TreeMap<LocalDateTime, BigDecimal>>> history =
|
|
|
|
|
+ vppTsdbQueryService.queryDeviceMetricHistory(deviceUuids, start, end, metrics);
|
|
|
|
|
+ return aggregateAverageByTime(history, metrics.get(0));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private Map<LocalDateTime, BigDecimal> aggregateSumByTime(
|
|
|
|
|
+ Map<String, Map<String, TreeMap<LocalDateTime, BigDecimal>>> history, String metric) {
|
|
|
|
|
+ if (CollectionUtils.isEmpty(history)) {
|
|
|
|
|
+ return Collections.emptyMap();
|
|
|
|
|
+ }
|
|
|
|
|
+ Map<LocalDateTime, BigDecimal> result = new TreeMap<>();
|
|
|
|
|
+ for (Map<String, TreeMap<LocalDateTime, BigDecimal>> deviceMetrics : history.values()) {
|
|
|
|
|
+ TreeMap<LocalDateTime, BigDecimal> series = deviceMetrics.get(metric);
|
|
|
|
|
+ if (series == null || series.isEmpty()) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ for (Map.Entry<LocalDateTime, BigDecimal> entry : series.entrySet()) {
|
|
|
|
|
+ result.merge(entry.getKey(), entry.getValue(), BigDecimal::add);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private Map<LocalDateTime, BigDecimal> aggregateAverageByTime(
|
|
|
|
|
+ Map<String, Map<String, TreeMap<LocalDateTime, BigDecimal>>> history, String metric) {
|
|
|
|
|
+ if (CollectionUtils.isEmpty(history)) {
|
|
|
|
|
+ return Collections.emptyMap();
|
|
|
|
|
+ }
|
|
|
|
|
+ Map<LocalDateTime, List<BigDecimal>> samples = new TreeMap<>();
|
|
|
|
|
+ for (Map<String, TreeMap<LocalDateTime, BigDecimal>> deviceMetrics : history.values()) {
|
|
|
|
|
+ TreeMap<LocalDateTime, BigDecimal> series = deviceMetrics.get(metric);
|
|
|
|
|
+ if (series == null || series.isEmpty()) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ for (Map.Entry<LocalDateTime, BigDecimal> entry : series.entrySet()) {
|
|
|
|
|
+ samples.computeIfAbsent(entry.getKey(), key -> new ArrayList<>()).add(entry.getValue());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ Map<LocalDateTime, BigDecimal> result = new TreeMap<>();
|
|
|
|
|
+ samples.forEach((timestamp, values) -> {
|
|
|
|
|
+ BigDecimal avg = averageValues(values);
|
|
|
|
|
+ if (avg != null) {
|
|
|
|
|
+ result.put(timestamp, avg);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private BigDecimal averageValues(List<BigDecimal> values) {
|
|
|
|
|
+ if (CollectionUtils.isEmpty(values)) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ List<BigDecimal> nonNullValues = values.stream()
|
|
|
|
|
+ .filter(Objects::nonNull)
|
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
|
+ if (nonNullValues.isEmpty()) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ BigDecimal sum = nonNullValues.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
|
|
+ return sum.divide(BigDecimal.valueOf(nonNullValues.size()), 4, RoundingMode.HALF_UP);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private ResourceCurveSeriesVO toCurveSeries(String name, String unit, Map<LocalDateTime, BigDecimal> aggregated) {
|
|
|
|
|
+ ResourceCurveSeriesVO series = new ResourceCurveSeriesVO();
|
|
|
|
|
+ series.setName(name);
|
|
|
|
|
+ series.setUnit(unit);
|
|
|
|
|
+ List<ResourceCurvePointVO> points = new ArrayList<>();
|
|
|
|
|
+ for (Map.Entry<LocalDateTime, BigDecimal> entry : aggregated.entrySet()) {
|
|
|
|
|
+ ResourceCurvePointVO point = new ResourceCurvePointVO();
|
|
|
|
|
+ point.setTime(entry.getKey().format(TIME_HH_MM));
|
|
|
|
|
+ point.setValue(entry.getValue().setScale(2, RoundingMode.HALF_UP));
|
|
|
|
|
+ points.add(point);
|
|
|
|
|
+ }
|
|
|
|
|
+ series.setPoints(points);
|
|
|
|
|
+ series.setCurrentValue(aggregated.entrySet().stream()
|
|
|
|
|
+ .max(Map.Entry.comparingByKey())
|
|
|
|
|
+ .map(entry -> entry.getValue().setScale(2, RoundingMode.HALF_UP))
|
|
|
|
|
+ .orElse(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP)));
|
|
|
|
|
+ return series;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private List<String> resolveDeviceUuids(List<VppDevice> devices) {
|
|
|
|
|
+ if (CollectionUtils.isEmpty(devices)) {
|
|
|
|
|
+ return Collections.emptyList();
|
|
|
|
|
+ }
|
|
|
|
|
+ return devices.stream()
|
|
|
|
|
+ .map(VppDevice::getDeviceUuid)
|
|
|
|
|
+ .filter(StringUtils::hasText)
|
|
|
|
|
+ .map(String::trim)
|
|
|
|
|
+ .distinct()
|
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private List<String> resolveDeviceUuidsByResourceType(List<VppDevice> devices,
|
|
|
|
|
+ Map<Long, String> deviceResourceTypeMap,
|
|
|
|
|
+ String resourceType) {
|
|
|
|
|
+ if (CollectionUtils.isEmpty(devices) || !StringUtils.hasText(resourceType)) {
|
|
|
|
|
+ return Collections.emptyList();
|
|
|
|
|
+ }
|
|
|
|
|
+ String targetType = resourceType.toUpperCase();
|
|
|
|
|
+ Set<String> uuids = new LinkedHashSet<>();
|
|
|
|
|
+ for (VppDevice device : devices) {
|
|
|
|
|
+ if (device.getId() == null || !StringUtils.hasText(device.getDeviceUuid())) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (targetType.equals(deviceResourceTypeMap.get(device.getId()))) {
|
|
|
|
|
+ uuids.add(device.getDeviceUuid().trim());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return new ArrayList<>(uuids);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private LocalDateTime parseDateTime(String value, LocalDateTime defaultValue) {
|
|
|
|
|
+ if (!StringUtils.hasText(value)) {
|
|
|
|
|
+ return defaultValue;
|
|
|
|
|
+ }
|
|
|
|
|
+ try {
|
|
|
|
|
+ return LocalDateTime.parse(value.trim(), TSDB_TIME);
|
|
|
|
|
+ } catch (DateTimeParseException ex) {
|
|
|
|
|
+ throw new BusinessException("时间格式无效,请使用 yyyy-MM-dd HH:mm:ss");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private List<ResourceTypeStatVO> buildTypeStats(List<VppResourcePoint> resources) {
|
|
private List<ResourceTypeStatVO> buildTypeStats(List<VppResourcePoint> resources) {
|
|
|
Map<String, ResourceTypeStatVO> statMap = new LinkedHashMap<>();
|
|
Map<String, ResourceTypeStatVO> statMap = new LinkedHashMap<>();
|
|
|
for (String type : RESOURCE_TYPES) {
|
|
for (String type : RESOURCE_TYPES) {
|
|
@@ -114,28 +315,59 @@ public class VppResourceOverviewServiceImpl implements VppResourceOverviewServic
|
|
|
List<String> pvDeviceUuids = resolveDeviceUuids(pvResources, deviceMap);
|
|
List<String> pvDeviceUuids = resolveDeviceUuids(pvResources, deviceMap);
|
|
|
List<String> loadDeviceUuids = resolveDeviceUuids(loadResources, deviceMap);
|
|
List<String> loadDeviceUuids = resolveDeviceUuids(loadResources, deviceMap);
|
|
|
|
|
|
|
|
- LocalDateTime startTime = LocalDate.now().atStartOfDay();
|
|
|
|
|
- LocalDateTime endTime = LocalDateTime.now();
|
|
|
|
|
|
|
+ LocalDateTime todayStart = LocalDate.now().atStartOfDay();
|
|
|
|
|
+ LocalDateTime now = LocalDateTime.now();
|
|
|
|
|
+ LocalDateTime yesterdayStart = todayStart.minusDays(1);
|
|
|
|
|
+ LocalDateTime yesterdayEnd = yesterdayStart.plus(ChronoUnit.MINUTES.between(todayStart, now), ChronoUnit.MINUTES);
|
|
|
|
|
|
|
|
- BigDecimal totalGeneration = queryTodayEnergy(pvDeviceUuids, startTime, endTime,
|
|
|
|
|
|
|
+ BigDecimal totalGeneration = queryTodayEnergy(pvDeviceUuids, todayStart, now,
|
|
|
|
|
+ Collections.singletonList(VppTsdbConstants.METRIC_EDAY), true);
|
|
|
|
|
+ BigDecimal totalConsumption = queryTodayEnergy(loadDeviceUuids, todayStart, now,
|
|
|
|
|
+ Collections.singletonList(VppTsdbConstants.METRIC_EPP), false);
|
|
|
|
|
+ BigDecimal yesterdayGeneration = queryTodayEnergy(pvDeviceUuids, yesterdayStart, yesterdayEnd,
|
|
|
Collections.singletonList(VppTsdbConstants.METRIC_EDAY), true);
|
|
Collections.singletonList(VppTsdbConstants.METRIC_EDAY), true);
|
|
|
- BigDecimal totalConsumption = queryTodayEnergy(loadDeviceUuids, startTime, endTime,
|
|
|
|
|
|
|
+ BigDecimal yesterdayConsumption = queryTodayEnergy(loadDeviceUuids, yesterdayStart, yesterdayEnd,
|
|
|
Collections.singletonList(VppTsdbConstants.METRIC_EPP), false);
|
|
Collections.singletonList(VppTsdbConstants.METRIC_EPP), false);
|
|
|
|
|
|
|
|
|
|
+ BigDecimal totalGenerationScaled = totalGeneration.setScale(2, RoundingMode.HALF_UP);
|
|
|
|
|
+ BigDecimal totalConsumptionScaled = totalConsumption.setScale(2, RoundingMode.HALF_UP);
|
|
|
|
|
+ BigDecimal greenEnergyRatio = calculateGreenEnergyRatio(totalGenerationScaled, totalConsumptionScaled);
|
|
|
|
|
+ BigDecimal yesterdayGreenEnergyRatio = calculateGreenEnergyRatio(
|
|
|
|
|
+ yesterdayGeneration.setScale(2, RoundingMode.HALF_UP),
|
|
|
|
|
+ yesterdayConsumption.setScale(2, RoundingMode.HALF_UP));
|
|
|
|
|
+
|
|
|
EnergyTodayVO energy = new EnergyTodayVO();
|
|
EnergyTodayVO energy = new EnergyTodayVO();
|
|
|
- energy.setTotalGenerationKwh(totalGeneration.setScale(2, RoundingMode.HALF_UP));
|
|
|
|
|
- energy.setTotalConsumptionKwh(totalConsumption.setScale(2, RoundingMode.HALF_UP));
|
|
|
|
|
- if (energy.getTotalConsumptionKwh().compareTo(BigDecimal.ZERO) > 0) {
|
|
|
|
|
- BigDecimal ratio = energy.getTotalGenerationKwh()
|
|
|
|
|
- .multiply(BigDecimal.valueOf(100))
|
|
|
|
|
- .divide(energy.getTotalConsumptionKwh(), 2, RoundingMode.HALF_UP);
|
|
|
|
|
- energy.setGreenEnergyRatioPercent(ratio.min(BigDecimal.valueOf(100)));
|
|
|
|
|
- } else {
|
|
|
|
|
- energy.setGreenEnergyRatioPercent(BigDecimal.ZERO);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ energy.setTotalGenerationKwh(totalGenerationScaled);
|
|
|
|
|
+ energy.setTotalGenerationKwhRingRatio(calculateRingRatio(totalGeneration, yesterdayGeneration));
|
|
|
|
|
+ energy.setTotalConsumptionKwh(totalConsumptionScaled);
|
|
|
|
|
+ energy.setTotalConsumptionKwhRingRatio(calculateRingRatio(totalConsumption, yesterdayConsumption));
|
|
|
|
|
+ energy.setGreenEnergyRatioPercent(greenEnergyRatio);
|
|
|
|
|
+ energy.setGreenEnergyRatioPercentRingRatio(calculateRingRatio(greenEnergyRatio, yesterdayGreenEnergyRatio));
|
|
|
return energy;
|
|
return energy;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ private BigDecimal calculateGreenEnergyRatio(BigDecimal generationKwh, BigDecimal consumptionKwh) {
|
|
|
|
|
+ if (consumptionKwh == null || consumptionKwh.compareTo(BigDecimal.ZERO) <= 0) {
|
|
|
|
|
+ return BigDecimal.ZERO;
|
|
|
|
|
+ }
|
|
|
|
|
+ BigDecimal generation = generationKwh != null ? generationKwh : BigDecimal.ZERO;
|
|
|
|
|
+ return generation.multiply(BigDecimal.valueOf(100))
|
|
|
|
|
+ .divide(consumptionKwh, 2, RoundingMode.HALF_UP)
|
|
|
|
|
+ .min(BigDecimal.valueOf(100));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private BigDecimal calculateRingRatio(BigDecimal current, BigDecimal previous) {
|
|
|
|
|
+ if (current == null) {
|
|
|
|
|
+ current = BigDecimal.ZERO;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (previous == null || previous.compareTo(BigDecimal.ZERO) == 0) {
|
|
|
|
|
+ return BigDecimal.ZERO;
|
|
|
|
|
+ }
|
|
|
|
|
+ return current.subtract(previous)
|
|
|
|
|
+ .multiply(BigDecimal.valueOf(100))
|
|
|
|
|
+ .divide(previous, 2, RoundingMode.HALF_UP);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private BigDecimal queryTodayEnergy(List<String> deviceUuids, LocalDateTime startTime, LocalDateTime endTime,
|
|
private BigDecimal queryTodayEnergy(List<String> deviceUuids, LocalDateTime startTime, LocalDateTime endTime,
|
|
|
List<String> metrics, boolean useLatestValue) {
|
|
List<String> metrics, boolean useLatestValue) {
|
|
|
if (CollectionUtils.isEmpty(deviceUuids)) {
|
|
if (CollectionUtils.isEmpty(deviceUuids)) {
|