|
@@ -26,6 +26,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
import java.time.LocalDateTime;
|
|
import java.time.LocalDateTime;
|
|
|
|
+import java.time.format.DateTimeFormatter;
|
|
|
|
+import java.time.format.DateTimeParseException;
|
|
import java.util.*;
|
|
import java.util.*;
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.Stream;
|
|
import java.util.stream.Stream;
|
|
@@ -63,6 +65,8 @@ public class SiteServiceImpl extends AbstractCrudService<SiteMapper, Site> imple
|
|
private HtAnalogDataService htAnalogDataService;
|
|
private HtAnalogDataService htAnalogDataService;
|
|
@Autowired
|
|
@Autowired
|
|
private ElectricityRateConfigMapper electricityRateConfigMapper;
|
|
private ElectricityRateConfigMapper electricityRateConfigMapper;
|
|
|
|
+ @Autowired
|
|
|
|
+ private RtAnalogDataService rtAnalogDataService;
|
|
|
|
|
|
@Override
|
|
@Override
|
|
public DeviceCountVO selectCount() {
|
|
public DeviceCountVO selectCount() {
|
|
@@ -372,150 +376,131 @@ public class SiteServiceImpl extends AbstractCrudService<SiteMapper, Site> imple
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
- public List<SiteLoadAnalysisVO> siteLoadAnalysis(Integer siteId) {
|
|
|
|
- List<SiteLoadAnalysisVO> records = new ArrayList<>();
|
|
|
|
- LambdaQueryWrapper<Site> siteQuery = Wrappers.lambdaQuery();
|
|
|
|
- siteQuery.eq(Site::getId, siteId);
|
|
|
|
- Site site = baseMapper.selectOne(siteQuery);
|
|
|
|
- log.info("站点信息:{}", site);
|
|
|
|
- if (site == null) {
|
|
|
|
- return records;
|
|
|
|
|
|
+ public List<SiteLoadAnalysisVO> siteLoadAnalysis(Integer siteId,
|
|
|
|
+ String startTime,
|
|
|
|
+ String endTime) {
|
|
|
|
+
|
|
|
|
+ /* ---------- 1. 站点&动态属性 ---------- */
|
|
|
|
+ Site site = Optional.ofNullable(
|
|
|
|
+ baseMapper.selectById(siteId))
|
|
|
|
+ .orElseGet(() -> {
|
|
|
|
+ log.warn("站点 {} 不存在", siteId);
|
|
|
|
+ return null;
|
|
|
|
+ });
|
|
|
|
+ if (site == null) return Collections.emptyList();
|
|
|
|
+
|
|
|
|
+ SiteDynamicProperties sdp = siteDynamicPropertiesService.lambdaQuery()
|
|
|
|
+ .eq(SiteDynamicProperties::getSiteId, siteId)
|
|
|
|
+ .one();
|
|
|
|
+ if (sdp == null) log.warn("站点 {} 动态属性缺失", siteId);
|
|
|
|
+
|
|
|
|
+ /* ---------- 2. 设备 ---------- */
|
|
|
|
+ List<DeviceList> devices = deviceService.deviceList(String.valueOf(siteId));
|
|
|
|
+ if (CollectionUtils.isEmpty(devices)) {
|
|
|
|
+ log.warn("站点 {} 无设备", siteId);
|
|
|
|
+ return Collections.emptyList();
|
|
}
|
|
}
|
|
|
|
|
|
- // 站点动态属性查询
|
|
|
|
- LambdaQueryWrapper<SiteDynamicProperties> siteDynamicPropertiesQuery = Wrappers.lambdaQuery();
|
|
|
|
- siteDynamicPropertiesQuery.eq(SiteDynamicProperties::getSiteId, siteId);
|
|
|
|
- SiteDynamicProperties siteDynamicProperties = siteDynamicPropertiesService.getOne(siteDynamicPropertiesQuery);
|
|
|
|
- log.info("站点动态属性信息:{}", siteDynamicProperties);
|
|
|
|
- if (siteDynamicProperties == null) {
|
|
|
|
- log.error("站点{}动态属性不存在", siteId);
|
|
|
|
- }
|
|
|
|
|
|
+ // 提前过滤并分组
|
|
|
|
+ Map<Boolean, List<DeviceList>> group = devices.stream()
|
|
|
|
+ .collect(Collectors.partitioningBy(d -> "1".equals(d.getDeviceType())));
|
|
|
|
+ List<DeviceList> typeOneDevices = group.get(true);
|
|
|
|
+ List<DeviceList> typeOtherDevices = group.get(false).stream()
|
|
|
|
+ .filter(d -> !"2".equals(d.getDeviceType()))
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
|
|
- // 存入接口返回
|
|
|
|
- SiteLoadAnalysisVO siteLoadAnalysisVO = new SiteLoadAnalysisVO();
|
|
|
|
- siteLoadAnalysisVO.setId(site.getId());
|
|
|
|
- siteLoadAnalysisVO.setName(site.getSiteName());
|
|
|
|
- // 额定容量=装机容量
|
|
|
|
- siteLoadAnalysisVO.setRatedCapacity(Double.valueOf(site.getInstalledCapacity()));
|
|
|
|
- // 额定电压
|
|
|
|
- try {
|
|
|
|
- assert siteDynamicProperties != null;
|
|
|
|
- siteLoadAnalysisVO.setRatedVoltage(StringUtils.isBlank(siteDynamicProperties.getVoltageLevel()) ? 0.0 : Double.parseDouble(siteDynamicProperties.getVoltageLevel()) / 1000.0);
|
|
|
|
- } catch (NumberFormatException e) {
|
|
|
|
- log.error("站点{} 电压等级(单位:V)格式转换错误{} ,已重置为0.0", siteDynamicProperties.getSiteId(), e);
|
|
|
|
- siteLoadAnalysisVO.setRatedVoltage(0.0);
|
|
|
|
- }
|
|
|
|
- // 先插入部分站点信息
|
|
|
|
- records.add(0, siteLoadAnalysisVO);
|
|
|
|
-
|
|
|
|
- List<DeviceList> deviceList = deviceService.deviceList(String.valueOf(siteId));
|
|
|
|
- log.info("设备信息list:{}", deviceList);
|
|
|
|
-
|
|
|
|
- // 类型为1的设备为站点的有功功率(总和)
|
|
|
|
- List<DeviceList> typeOneDevices = new ArrayList<>();
|
|
|
|
- List<DeviceList> typeOtherDevices = new ArrayList<>();
|
|
|
|
- List<String> deviceCodeList = new ArrayList<>();
|
|
|
|
- // Map<String, Double> pMap = new HashMap<>();
|
|
|
|
- double p = 0.0;
|
|
|
|
-
|
|
|
|
- if (!deviceList.isEmpty()) {
|
|
|
|
- for (DeviceList device : deviceList) {
|
|
|
|
- String deviceType = device.getDeviceType();
|
|
|
|
- if ("1".equals(deviceType)) {
|
|
|
|
- typeOneDevices.add(device);
|
|
|
|
- } else if (!"2".equals(deviceType)) {
|
|
|
|
- typeOtherDevices.add(device);
|
|
|
|
- }
|
|
|
|
- deviceCodeList.add(device.getDeviceCode());
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- log.error("站点{}无设备", siteId);
|
|
|
|
- return new ArrayList<>();
|
|
|
|
- }
|
|
|
|
|
|
+ List<String> deviceCodes = devices.stream()
|
|
|
|
+ .map(DeviceList::getDeviceCode)
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
|
|
- // pMap = (htAnalogDataService.getP(deviceCodeList)).stream().collect(Collectors.toMap(HtAnalogData::getDeviceName, HtAnalogData::getP));
|
|
|
|
- List<HtAnalogData> pList = htAnalogDataService.getP(deviceCodeList);
|
|
|
|
- if (pList.isEmpty()) {
|
|
|
|
- log.error("站点{},设备编号{} 无有功功率数据", siteId, deviceCodeList);
|
|
|
|
- for (DeviceList device : deviceList) {
|
|
|
|
- SiteLoadAnalysisVO deviceLoadAnalysis = new SiteLoadAnalysisVO();
|
|
|
|
- deviceLoadAnalysis.setName(device.getDeviceName());
|
|
|
|
- deviceLoadAnalysis.setId(null);
|
|
|
|
- deviceLoadAnalysis.setCode(device.getDeviceCode());
|
|
|
|
- deviceLoadAnalysis.setRatedCapacity(0.0);
|
|
|
|
- deviceLoadAnalysis.setRatedVoltage(0.0);
|
|
|
|
- deviceLoadAnalysis.setP(0.0);
|
|
|
|
- deviceLoadAnalysis.setLoadRate(0.0);
|
|
|
|
- deviceLoadAnalysis.setDataTime(null);
|
|
|
|
- records.add(deviceLoadAnalysis);
|
|
|
|
|
|
+ /* ---------- 3. 有功功率数据 ---------- */
|
|
|
|
+ // 解析时间
|
|
|
|
+ DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
|
|
|
+ LocalDateTime start = null, end = null;
|
|
|
|
+ if (StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime)) {
|
|
|
|
+ try {
|
|
|
|
+ start = LocalDateTime.parse(startTime, fmt);
|
|
|
|
+ end = LocalDateTime.parse(endTime, fmt);
|
|
|
|
+ } catch (DateTimeParseException ex) {
|
|
|
|
+ throw new BusinessException("时间格式错误: " + ex.getMessage());
|
|
}
|
|
}
|
|
- return new ArrayList<>();
|
|
|
|
}
|
|
}
|
|
- for (DeviceList device : deviceList) {
|
|
|
|
- log.info("设备信息:{}", device);
|
|
|
|
- SiteLoadAnalysisVO deviceLoadAnalysis = new SiteLoadAnalysisVO();
|
|
|
|
- deviceLoadAnalysis.setId(device.getId());
|
|
|
|
- deviceLoadAnalysis.setName(device.getDeviceName());
|
|
|
|
- deviceLoadAnalysis.setCode(device.getDeviceCode());
|
|
|
|
- double ratedCapacity = device.getRatedCurrent() * device.getRatedVoltage();
|
|
|
|
- log.info("额定容量:{}", ratedCapacity);
|
|
|
|
- deviceLoadAnalysis.setRatedCapacity(ratedCapacity);
|
|
|
|
- deviceLoadAnalysis.setRatedVoltage(device.getRatedVoltage());
|
|
|
|
-
|
|
|
|
- LocalDateTime dateTime = pList.stream()
|
|
|
|
- .filter(ht -> ht.getDeviceName().equals(device.getDeviceCode()))
|
|
|
|
- .findFirst()
|
|
|
|
- .map(HtAnalogData::getDataTime)
|
|
|
|
- .orElse(null);
|
|
|
|
- deviceLoadAnalysis.setDataTime(dateTime);
|
|
|
|
-
|
|
|
|
- // deviceLoadAnalysis.setP(pMap.get(device.getDeviceCode()));
|
|
|
|
-
|
|
|
|
- Double m = pList.stream()
|
|
|
|
- .filter(ht -> ht.getDeviceName().equals(device.getDeviceCode()))
|
|
|
|
- .findFirst()
|
|
|
|
- .map(HtAnalogData::getP)
|
|
|
|
- .orElse(0.0);
|
|
|
|
- deviceLoadAnalysis.setP(m);
|
|
|
|
|
|
|
|
- if (ratedCapacity != 0.0) {
|
|
|
|
- deviceLoadAnalysis.setLoadRate(Arith.div(m, ratedCapacity, 3));
|
|
|
|
- } else {
|
|
|
|
- deviceLoadAnalysis.setLoadRate(0.0);
|
|
|
|
- }
|
|
|
|
- records.add(deviceLoadAnalysis);
|
|
|
|
- }
|
|
|
|
|
|
+ // 统一获取数据并转 Map
|
|
|
|
+ Map<String, ? extends Number> pMap = start != null
|
|
|
|
+ ? htAnalogDataService.getP(deviceCodes, start, end)
|
|
|
|
+ .stream()
|
|
|
|
+ .collect(Collectors.toMap(HtAnalogData::getDeviceName,
|
|
|
|
+ HtAnalogData::getP,
|
|
|
|
+ (v1, v2) -> v1))
|
|
|
|
+ : rtAnalogDataService.getP(deviceCodes)
|
|
|
|
+ .stream()
|
|
|
|
+ .collect(Collectors.toMap(RtAnalogData::getDeviceName,
|
|
|
|
+ RtAnalogData::getP,
|
|
|
|
+ (v1, v2) -> v1));
|
|
|
|
+
|
|
|
|
+ /* ---------- 4. 组装结果 ---------- */
|
|
|
|
+ List<SiteLoadAnalysisVO> records = new ArrayList<>();
|
|
|
|
|
|
- // 没有的话则是其他类型的总和(类型2 视频监控除外)
|
|
|
|
- if (!typeOneDevices.isEmpty()) {
|
|
|
|
- for (DeviceList device : typeOneDevices) {
|
|
|
|
- Double m = pList.stream()
|
|
|
|
- .filter(ht -> ht.getDeviceName().equals(device.getDeviceCode()))
|
|
|
|
|
|
+ // 站点首行
|
|
|
|
+ SiteLoadAnalysisVO siteRow = new SiteLoadAnalysisVO();
|
|
|
|
+ siteRow.setId(site.getId());
|
|
|
|
+ siteRow.setName(site.getSiteName());
|
|
|
|
+ siteRow.setRatedCapacity(Double.valueOf(site.getInstalledCapacity()));
|
|
|
|
+ siteRow.setRatedVoltage(
|
|
|
|
+ Optional.ofNullable(sdp)
|
|
|
|
+ .map(SiteDynamicProperties::getVoltageLevel)
|
|
|
|
+ .filter(StringUtils::isNotBlank)
|
|
|
|
+ .map(v -> Double.parseDouble(v) / 1000.0)
|
|
|
|
+ .orElse(0.0));
|
|
|
|
+ records.add(siteRow);
|
|
|
|
+
|
|
|
|
+ // 设备行
|
|
|
|
+ LocalDateTime finalStart = start;
|
|
|
|
+ LocalDateTime finalEnd = end;
|
|
|
|
+ devices.forEach(d -> {
|
|
|
|
+ SiteLoadAnalysisVO r = new SiteLoadAnalysisVO();
|
|
|
|
+ r.setId(d.getId());
|
|
|
|
+ r.setName(d.getDeviceName());
|
|
|
|
+ r.setCode(d.getDeviceCode());
|
|
|
|
+ double ratedCap = d.getRatedCurrent() * d.getRatedVoltage();
|
|
|
|
+ r.setRatedCapacity(ratedCap);
|
|
|
|
+ r.setRatedVoltage(d.getRatedVoltage());
|
|
|
|
+
|
|
|
|
+ double p = Optional.ofNullable(pMap.get(d.getDeviceCode()))
|
|
|
|
+ .map(Number::doubleValue)
|
|
|
|
+ .orElse(0.0);
|
|
|
|
+ r.setP(p);
|
|
|
|
+ r.setLoadRate(ratedCap == 0 ? 0.0 : Arith.div(p, ratedCap, 3));
|
|
|
|
+
|
|
|
|
+ // 数据时间(如果有)
|
|
|
|
+ if (finalStart != null) {
|
|
|
|
+ htAnalogDataService.getP(deviceCodes, finalStart, finalEnd).stream()
|
|
|
|
+ .filter(h -> h.getDeviceName().equals(d.getDeviceCode()))
|
|
.findFirst()
|
|
.findFirst()
|
|
- .map(HtAnalogData::getP)
|
|
|
|
- .orElse(0.0);
|
|
|
|
- p += m;
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- for (DeviceList device : typeOtherDevices) {
|
|
|
|
- Double m = pList.stream()
|
|
|
|
- .filter(ht -> ht.getDeviceName().equals(device.getDeviceCode()))
|
|
|
|
|
|
+ .ifPresent(h -> r.setDataTime(h.getDataTime()));
|
|
|
|
+ } else {
|
|
|
|
+ rtAnalogDataService.getP(deviceCodes).stream()
|
|
|
|
+ .filter(h -> h.getDeviceName().equals(d.getDeviceCode()))
|
|
.findFirst()
|
|
.findFirst()
|
|
- .map(HtAnalogData::getP)
|
|
|
|
- .orElse(0.0);
|
|
|
|
- p += m;
|
|
|
|
|
|
+ .ifPresent(h -> r.setDataTime(h.getDataTime()));
|
|
}
|
|
}
|
|
- }
|
|
|
|
- records.get(0).setP(p);
|
|
|
|
|
|
+ records.add(r);
|
|
|
|
+ });
|
|
|
|
|
|
- // 负载率
|
|
|
|
- if (records.get(0).getRatedCapacity() != 0.0) {
|
|
|
|
- records.get(0).setLoadRate(Arith.div(p, records.get(0).getRatedCapacity(), 3));
|
|
|
|
- } else {
|
|
|
|
- records.get(0).setLoadRate(0.0);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return records;
|
|
|
|
|
|
+ /* ---------- 5. 站点总功率&负载率 ---------- */
|
|
|
|
+ double totalP = (typeOneDevices.isEmpty() ? typeOtherDevices : typeOneDevices)
|
|
|
|
+ .stream()
|
|
|
|
+ .mapToDouble(d -> Optional.ofNullable(pMap.get(d.getDeviceCode()))
|
|
|
|
+ .map(Number::doubleValue)
|
|
|
|
+ .orElse(0.0))
|
|
|
|
+ .sum();
|
|
|
|
+ siteRow.setP(totalP);
|
|
|
|
+ siteRow.setLoadRate(siteRow.getRatedCapacity() == 0
|
|
|
|
+ ? 0.0
|
|
|
|
+ : Arith.div(totalP, siteRow.getRatedCapacity(), 3));
|
|
|
|
+
|
|
|
|
+ return records;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|