1.单体电池批量新增修改
This commit is contained in:
@ -16,6 +16,8 @@ import com.xzzn.ems.domain.vo.PointDataRequest;
|
||||
import com.xzzn.ems.domain.vo.PointQueryResponse;
|
||||
import com.xzzn.ems.domain.vo.SiteDeviceListVo;
|
||||
import com.xzzn.ems.domain.vo.SiteMonitorProjectPointMappingSaveRequest;
|
||||
import com.xzzn.ems.domain.vo.SingleBatteryConfigInitRequest;
|
||||
import com.xzzn.ems.domain.vo.SingleBatteryConfigInitResultVo;
|
||||
import com.xzzn.ems.domain.vo.SingleBatteryMonitorImportResultVo;
|
||||
import com.xzzn.ems.domain.vo.SingleBatteryMonitorImportRowVo;
|
||||
import com.xzzn.ems.domain.vo.WorkStatusEnumMappingSaveRequest;
|
||||
@ -204,6 +206,12 @@ public class EmsSiteConfigController extends BaseController {
|
||||
return AjaxResult.success(result);
|
||||
}
|
||||
|
||||
@PostMapping("/initializeSingleBatteryMonitorMappings")
|
||||
public AjaxResult initializeSingleBatteryMonitorMappings(@RequestBody SingleBatteryConfigInitRequest request) {
|
||||
SingleBatteryConfigInitResultVo result = iEmsDeviceSettingService.initializeSingleBatteryMonitorMappings(request, getUsername());
|
||||
return AjaxResult.success(result);
|
||||
}
|
||||
|
||||
// @PreAuthorize("@ss.hasPermi('system:device:onAndOff')")
|
||||
@Log(title = "寮€鍏虫満", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/updateDeviceStatus")
|
||||
|
||||
@ -0,0 +1,41 @@
|
||||
package com.xzzn.ems.domain.vo;
|
||||
|
||||
public class SingleBatteryConfigInitRequest {
|
||||
|
||||
private String siteId;
|
||||
private String scopeType;
|
||||
private String scopeDeviceId;
|
||||
private Integer targetCount;
|
||||
|
||||
public String getSiteId() {
|
||||
return siteId;
|
||||
}
|
||||
|
||||
public void setSiteId(String siteId) {
|
||||
this.siteId = siteId;
|
||||
}
|
||||
|
||||
public String getScopeType() {
|
||||
return scopeType;
|
||||
}
|
||||
|
||||
public void setScopeType(String scopeType) {
|
||||
this.scopeType = scopeType;
|
||||
}
|
||||
|
||||
public String getScopeDeviceId() {
|
||||
return scopeDeviceId;
|
||||
}
|
||||
|
||||
public void setScopeDeviceId(String scopeDeviceId) {
|
||||
this.scopeDeviceId = scopeDeviceId;
|
||||
}
|
||||
|
||||
public Integer getTargetCount() {
|
||||
return targetCount;
|
||||
}
|
||||
|
||||
public void setTargetCount(Integer targetCount) {
|
||||
this.targetCount = targetCount;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,122 @@
|
||||
package com.xzzn.ems.domain.vo;
|
||||
|
||||
public class SingleBatteryConfigInitResultVo {
|
||||
|
||||
private Boolean committed;
|
||||
private String siteId;
|
||||
private String scopeType;
|
||||
private String scopeDeviceId;
|
||||
private Integer targetCount;
|
||||
private Integer existingBatteryCount;
|
||||
private Integer initializedBatteryCount;
|
||||
private Integer insertedBatteryCount;
|
||||
private Integer pointHitCount;
|
||||
private Integer fixedValueFallbackCount;
|
||||
private Integer insertedMappingCount;
|
||||
private Integer updatedMappingCount;
|
||||
private String message;
|
||||
|
||||
public Boolean getCommitted() {
|
||||
return committed;
|
||||
}
|
||||
|
||||
public void setCommitted(Boolean committed) {
|
||||
this.committed = committed;
|
||||
}
|
||||
|
||||
public String getSiteId() {
|
||||
return siteId;
|
||||
}
|
||||
|
||||
public void setSiteId(String siteId) {
|
||||
this.siteId = siteId;
|
||||
}
|
||||
|
||||
public String getScopeType() {
|
||||
return scopeType;
|
||||
}
|
||||
|
||||
public void setScopeType(String scopeType) {
|
||||
this.scopeType = scopeType;
|
||||
}
|
||||
|
||||
public String getScopeDeviceId() {
|
||||
return scopeDeviceId;
|
||||
}
|
||||
|
||||
public void setScopeDeviceId(String scopeDeviceId) {
|
||||
this.scopeDeviceId = scopeDeviceId;
|
||||
}
|
||||
|
||||
public Integer getTargetCount() {
|
||||
return targetCount;
|
||||
}
|
||||
|
||||
public void setTargetCount(Integer targetCount) {
|
||||
this.targetCount = targetCount;
|
||||
}
|
||||
|
||||
public Integer getExistingBatteryCount() {
|
||||
return existingBatteryCount;
|
||||
}
|
||||
|
||||
public void setExistingBatteryCount(Integer existingBatteryCount) {
|
||||
this.existingBatteryCount = existingBatteryCount;
|
||||
}
|
||||
|
||||
public Integer getInitializedBatteryCount() {
|
||||
return initializedBatteryCount;
|
||||
}
|
||||
|
||||
public void setInitializedBatteryCount(Integer initializedBatteryCount) {
|
||||
this.initializedBatteryCount = initializedBatteryCount;
|
||||
}
|
||||
|
||||
public Integer getInsertedBatteryCount() {
|
||||
return insertedBatteryCount;
|
||||
}
|
||||
|
||||
public void setInsertedBatteryCount(Integer insertedBatteryCount) {
|
||||
this.insertedBatteryCount = insertedBatteryCount;
|
||||
}
|
||||
|
||||
public Integer getPointHitCount() {
|
||||
return pointHitCount;
|
||||
}
|
||||
|
||||
public void setPointHitCount(Integer pointHitCount) {
|
||||
this.pointHitCount = pointHitCount;
|
||||
}
|
||||
|
||||
public Integer getFixedValueFallbackCount() {
|
||||
return fixedValueFallbackCount;
|
||||
}
|
||||
|
||||
public void setFixedValueFallbackCount(Integer fixedValueFallbackCount) {
|
||||
this.fixedValueFallbackCount = fixedValueFallbackCount;
|
||||
}
|
||||
|
||||
public Integer getInsertedMappingCount() {
|
||||
return insertedMappingCount;
|
||||
}
|
||||
|
||||
public void setInsertedMappingCount(Integer insertedMappingCount) {
|
||||
this.insertedMappingCount = insertedMappingCount;
|
||||
}
|
||||
|
||||
public Integer getUpdatedMappingCount() {
|
||||
return updatedMappingCount;
|
||||
}
|
||||
|
||||
public void setUpdatedMappingCount(Integer updatedMappingCount) {
|
||||
this.updatedMappingCount = updatedMappingCount;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
@ -10,6 +10,8 @@ import com.xzzn.ems.domain.vo.SiteMonitorDataSaveRequest;
|
||||
import com.xzzn.ems.domain.vo.SiteMonitorProjectDisplayVo;
|
||||
import com.xzzn.ems.domain.vo.SiteMonitorProjectPointMappingSaveRequest;
|
||||
import com.xzzn.ems.domain.vo.SiteMonitorProjectPointMappingVo;
|
||||
import com.xzzn.ems.domain.vo.SingleBatteryConfigInitRequest;
|
||||
import com.xzzn.ems.domain.vo.SingleBatteryConfigInitResultVo;
|
||||
import com.xzzn.ems.domain.vo.SingleBatteryMonitorImportResultVo;
|
||||
import com.xzzn.ems.domain.vo.SingleBatteryMonitorImportRowVo;
|
||||
import com.xzzn.ems.domain.vo.WorkStatusEnumMappingVo;
|
||||
@ -60,4 +62,6 @@ public interface IEmsDeviceSettingService
|
||||
public int syncSiteMonitorDataByMqtt(String siteId, String deviceId, String jsonData, Date valueTime);
|
||||
|
||||
public SingleBatteryMonitorImportResultVo importSingleBatteryMonitorMappings(String siteId, List<SingleBatteryMonitorImportRowVo> rows, String operName);
|
||||
|
||||
public SingleBatteryConfigInitResultVo initializeSingleBatteryMonitorMappings(SingleBatteryConfigInitRequest request, String operName);
|
||||
}
|
||||
|
||||
@ -39,6 +39,8 @@ import com.xzzn.ems.domain.vo.SiteMonitorDataVo;
|
||||
import com.xzzn.ems.domain.vo.SiteMonitorProjectDisplayVo;
|
||||
import com.xzzn.ems.domain.vo.SiteMonitorProjectPointMappingSaveRequest;
|
||||
import com.xzzn.ems.domain.vo.SiteMonitorProjectPointMappingVo;
|
||||
import com.xzzn.ems.domain.vo.SingleBatteryConfigInitRequest;
|
||||
import com.xzzn.ems.domain.vo.SingleBatteryConfigInitResultVo;
|
||||
import com.xzzn.ems.domain.vo.SingleBatteryMonitorImportFailureVo;
|
||||
import com.xzzn.ems.domain.vo.SingleBatteryMonitorImportResultVo;
|
||||
import com.xzzn.ems.domain.vo.SingleBatteryMonitorImportRowVo;
|
||||
@ -69,6 +71,7 @@ import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@ -122,6 +125,9 @@ public class EmsDeviceSettingServiceImpl implements IEmsDeviceSettingService
|
||||
private static final String BATTERY_FIELD_TEMPERATURE = "SBJK_DTDC__temperature";
|
||||
private static final String BATTERY_FIELD_SOC = "SBJK_DTDC__soc";
|
||||
private static final String BATTERY_FIELD_SOH = "SBJK_DTDC__soh";
|
||||
private static final String SINGLE_BATTERY_SCOPE_CLUSTER = "cluster";
|
||||
private static final String SINGLE_BATTERY_SCOPE_STACK = "stack";
|
||||
private static final String SINGLE_BATTERY_FIELD_VALUE_ZERO = "0";
|
||||
private static final Set<String> SINGLE_BATTERY_IMPORT_FIELD_CODES = new HashSet<>(Arrays.asList(
|
||||
BATTERY_FIELD_VOLTAGE, BATTERY_FIELD_TEMPERATURE, BATTERY_FIELD_SOC, BATTERY_FIELD_SOH
|
||||
));
|
||||
@ -1081,6 +1087,375 @@ public class EmsDeviceSettingServiceImpl implements IEmsDeviceSettingService
|
||||
}
|
||||
}
|
||||
|
||||
private static class SingleBatteryInitScope {
|
||||
private final String normalizedSiteId;
|
||||
private final String scopeType;
|
||||
private final String scopeDeviceId;
|
||||
private final List<EmsDevicesSetting> scopeClusters;
|
||||
private final String appendClusterId;
|
||||
private final List<EmsDevicesSetting> allSiteDevices;
|
||||
|
||||
private SingleBatteryInitScope(String normalizedSiteId,
|
||||
String scopeType,
|
||||
String scopeDeviceId,
|
||||
List<EmsDevicesSetting> scopeClusters,
|
||||
String appendClusterId,
|
||||
List<EmsDevicesSetting> allSiteDevices) {
|
||||
this.normalizedSiteId = normalizedSiteId;
|
||||
this.scopeType = scopeType;
|
||||
this.scopeDeviceId = scopeDeviceId;
|
||||
this.scopeClusters = scopeClusters;
|
||||
this.appendClusterId = appendClusterId;
|
||||
this.allSiteDevices = allSiteDevices;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public SingleBatteryConfigInitResultVo initializeSingleBatteryMonitorMappings(SingleBatteryConfigInitRequest request, String operName) {
|
||||
SingleBatteryInitScope scope = resolveSingleBatteryInitScope(request);
|
||||
SingleBatteryConfigInitResultVo result = new SingleBatteryConfigInitResultVo();
|
||||
result.setCommitted(false);
|
||||
result.setSiteId(scope.normalizedSiteId);
|
||||
result.setScopeType(scope.scopeType);
|
||||
result.setScopeDeviceId(scope.scopeDeviceId);
|
||||
result.setTargetCount(request.getTargetCount());
|
||||
result.setExistingBatteryCount(0);
|
||||
result.setInitializedBatteryCount(0);
|
||||
result.setInsertedBatteryCount(0);
|
||||
result.setPointHitCount(0);
|
||||
result.setFixedValueFallbackCount(0);
|
||||
result.setInsertedMappingCount(0);
|
||||
result.setUpdatedMappingCount(0);
|
||||
|
||||
Map<String, EmsDevicesSetting> deviceMap = scope.allSiteDevices.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.filter(item -> StringUtils.isNotBlank(item.getDeviceId()))
|
||||
.collect(Collectors.toMap(
|
||||
item -> StringUtils.trim(item.getDeviceId()),
|
||||
item -> item,
|
||||
(left, right) -> right,
|
||||
LinkedHashMap::new
|
||||
));
|
||||
Set<String> scopeClusterIdSet = scope.scopeClusters.stream()
|
||||
.map(EmsDevicesSetting::getDeviceId)
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.map(String::trim)
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
List<EmsDevicesSetting> scopeBatteryList = getScopeBatteryList(scope.allSiteDevices, scopeClusterIdSet);
|
||||
result.setExistingBatteryCount(scopeBatteryList.size());
|
||||
|
||||
int targetCount = request.getTargetCount();
|
||||
if (targetCount > scopeBatteryList.size()) {
|
||||
int appendCount = targetCount - scopeBatteryList.size();
|
||||
List<EmsDevicesSetting> newBatteryList = createMissingSingleBatteries(
|
||||
scope.normalizedSiteId,
|
||||
scope.appendClusterId,
|
||||
appendCount,
|
||||
deviceMap,
|
||||
operName
|
||||
);
|
||||
scopeBatteryList.addAll(newBatteryList);
|
||||
result.setInsertedBatteryCount(newBatteryList.size());
|
||||
}
|
||||
|
||||
Map<String, List<EmsDevicesSetting>> batteryByCluster = scopeBatteryList.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.filter(item -> StringUtils.isNotBlank(item.getParentId()))
|
||||
.collect(Collectors.groupingBy(
|
||||
item -> StringUtils.trim(item.getParentId()),
|
||||
LinkedHashMap::new,
|
||||
Collectors.toList()
|
||||
));
|
||||
Set<String> pointIds = new HashSet<>();
|
||||
List<SingleBatteryFieldInitTask> taskList = new ArrayList<>();
|
||||
for (EmsDevicesSetting cluster : scope.scopeClusters) {
|
||||
if (cluster == null || StringUtils.isBlank(cluster.getDeviceId())) {
|
||||
continue;
|
||||
}
|
||||
String clusterId = StringUtils.trim(cluster.getDeviceId());
|
||||
List<EmsDevicesSetting> clusterBatteryList = batteryByCluster.getOrDefault(clusterId, Collections.emptyList())
|
||||
.stream()
|
||||
.sorted(Comparator.comparing(item -> StringUtils.defaultString(item.getDeviceId())))
|
||||
.collect(Collectors.toList());
|
||||
for (int i = 0; i < clusterBatteryList.size(); i++) {
|
||||
EmsDevicesSetting battery = clusterBatteryList.get(i);
|
||||
String batteryId = StringUtils.trim(battery.getDeviceId());
|
||||
String serialNo = formatSingleBatterySerial(i + 1);
|
||||
taskList.add(buildSingleBatteryFieldInitTask(scope.normalizedSiteId, clusterId, batteryId, BATTERY_FIELD_VOLTAGE, "DY", serialNo));
|
||||
taskList.add(buildSingleBatteryFieldInitTask(scope.normalizedSiteId, clusterId, batteryId, BATTERY_FIELD_TEMPERATURE, "WD", serialNo));
|
||||
taskList.add(buildSingleBatteryFieldInitTask(scope.normalizedSiteId, clusterId, batteryId, BATTERY_FIELD_SOC, "SOC", serialNo));
|
||||
taskList.add(buildSingleBatteryFieldInitTask(scope.normalizedSiteId, clusterId, batteryId, BATTERY_FIELD_SOH, "SOH", serialNo));
|
||||
pointIds.add(clusterId + "DTDY" + serialNo);
|
||||
pointIds.add(clusterId + "DTWD" + serialNo);
|
||||
pointIds.add(clusterId + "DTSOC" + serialNo);
|
||||
pointIds.add(clusterId + "DTSOH" + serialNo);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, EmsPointConfig> pointConfigMap = pointIds.isEmpty()
|
||||
? Collections.emptyMap()
|
||||
: emsPointConfigMapper.selectBySiteIdAndPointIds(scope.normalizedSiteId, new ArrayList<>(pointIds))
|
||||
.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.filter(item -> StringUtils.isNotBlank(item.getPointId()))
|
||||
.collect(Collectors.toMap(
|
||||
item -> StringUtils.trim(item.getPointId()),
|
||||
item -> item,
|
||||
(left, right) -> right,
|
||||
HashMap::new
|
||||
));
|
||||
|
||||
Map<String, EmsSiteMonitorPointMatch> existingPointMatchMap = emsSiteMonitorPointMatchMapper.selectBySiteId(scope.normalizedSiteId)
|
||||
.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.filter(item -> SINGLE_BATTERY_IMPORT_FIELD_CODES.contains(StringUtils.trim(item.getFieldCode())))
|
||||
.filter(item -> StringUtils.isNotBlank(item.getDeviceId()))
|
||||
.collect(Collectors.toMap(
|
||||
item -> buildMatchKey(StringUtils.trim(item.getFieldCode()), StringUtils.trim(item.getDeviceId())),
|
||||
item -> item,
|
||||
(left, right) -> right,
|
||||
LinkedHashMap::new
|
||||
));
|
||||
|
||||
List<EmsSiteMonitorPointMatch> insertList = new ArrayList<>();
|
||||
Set<String> affectedBatteryIds = scopeBatteryList.stream()
|
||||
.map(EmsDevicesSetting::getDeviceId)
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.map(String::trim)
|
||||
.collect(Collectors.toSet());
|
||||
for (SingleBatteryFieldInitTask task : taskList) {
|
||||
boolean pointExists = pointConfigMap.containsKey(task.pointId);
|
||||
if (pointExists) {
|
||||
result.setPointHitCount(result.getPointHitCount() + 1);
|
||||
} else {
|
||||
result.setFixedValueFallbackCount(result.getFixedValueFallbackCount() + 1);
|
||||
}
|
||||
upsertSingleBatteryPointMatchForInit(insertList, existingPointMatchMap, result, task, pointExists, operName);
|
||||
}
|
||||
if (!insertList.isEmpty()) {
|
||||
emsSiteMonitorPointMatchMapper.insertBatch(insertList);
|
||||
}
|
||||
|
||||
refreshSingleBatteryImportCache(scope.normalizedSiteId, affectedBatteryIds);
|
||||
result.setInitializedBatteryCount(scopeBatteryList.size());
|
||||
result.setCommitted(true);
|
||||
result.setMessage(String.format(
|
||||
"初始化完成:已初始化单体 %d 个,新增单体 %d 个,命中点位 %d 条,固定值回填 %d 条",
|
||||
result.getInitializedBatteryCount(),
|
||||
result.getInsertedBatteryCount(),
|
||||
result.getPointHitCount(),
|
||||
result.getFixedValueFallbackCount()
|
||||
));
|
||||
return result;
|
||||
}
|
||||
|
||||
private SingleBatteryInitScope resolveSingleBatteryInitScope(SingleBatteryConfigInitRequest request) {
|
||||
if (request == null) {
|
||||
throw new ServiceException("鍒濆鍖栬姹備笉鑳戒负绌?");
|
||||
}
|
||||
String normalizedSiteId = StringUtils.trim(request.getSiteId());
|
||||
String normalizedScopeType = StringUtils.trimToEmpty(request.getScopeType()).toLowerCase();
|
||||
String normalizedScopeDeviceId = StringUtils.trim(request.getScopeDeviceId());
|
||||
Integer targetCount = request.getTargetCount();
|
||||
if (StringUtils.isBlank(normalizedSiteId)) {
|
||||
throw new ServiceException("绔欑偣ID涓嶈兘涓虹┖");
|
||||
}
|
||||
if (StringUtils.isBlank(normalizedScopeType) || StringUtils.isBlank(normalizedScopeDeviceId)) {
|
||||
throw new ServiceException("鍒濆鍖栬寖鍥村拰璁惧ID涓嶈兘涓虹┖");
|
||||
}
|
||||
if (!SINGLE_BATTERY_SCOPE_CLUSTER.equals(normalizedScopeType) && !SINGLE_BATTERY_SCOPE_STACK.equals(normalizedScopeType)) {
|
||||
throw new ServiceException("鍒濆鍖栬寖鍥诲彧鏀寔 cluster 鎴?stack");
|
||||
}
|
||||
if (targetCount == null || targetCount < 1) {
|
||||
throw new ServiceException("鍗曚綋鏁伴噺蹇呴』澶т簬 0");
|
||||
}
|
||||
|
||||
List<EmsDevicesSetting> allSiteDevices = emsDevicesMapper.selectEmsDevicesSettingList(buildSiteDeviceQuery(normalizedSiteId));
|
||||
Map<String, EmsDevicesSetting> deviceMap = allSiteDevices.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.filter(item -> StringUtils.isNotBlank(item.getDeviceId()))
|
||||
.collect(Collectors.toMap(
|
||||
item -> StringUtils.trim(item.getDeviceId()),
|
||||
item -> item,
|
||||
(left, right) -> right,
|
||||
LinkedHashMap::new
|
||||
));
|
||||
if (SINGLE_BATTERY_SCOPE_CLUSTER.equals(normalizedScopeType)) {
|
||||
EmsDevicesSetting cluster = deviceMap.get(normalizedScopeDeviceId);
|
||||
if (cluster == null || !StringUtils.equals(DeviceCategory.CLUSTER.getCode(), StringUtils.trim(cluster.getDeviceCategory()))) {
|
||||
throw new ServiceException(String.format("电池簇编号[%s]不存在", normalizedScopeDeviceId));
|
||||
}
|
||||
return new SingleBatteryInitScope(
|
||||
normalizedSiteId,
|
||||
normalizedScopeType,
|
||||
normalizedScopeDeviceId,
|
||||
Collections.singletonList(cluster),
|
||||
normalizedScopeDeviceId,
|
||||
allSiteDevices
|
||||
);
|
||||
}
|
||||
|
||||
EmsDevicesSetting stack = deviceMap.get(normalizedScopeDeviceId);
|
||||
if (stack == null || !StringUtils.equals(DeviceCategory.STACK.getCode(), StringUtils.trim(stack.getDeviceCategory()))) {
|
||||
throw new ServiceException(String.format("电池堆编号[%s]不存在", normalizedScopeDeviceId));
|
||||
}
|
||||
List<EmsDevicesSetting> scopeClusters = allSiteDevices.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.filter(item -> StringUtils.equals(DeviceCategory.CLUSTER.getCode(), StringUtils.trim(item.getDeviceCategory())))
|
||||
.filter(item -> StringUtils.equals(normalizedScopeDeviceId, StringUtils.trim(item.getParentId())))
|
||||
.sorted(Comparator.comparing(item -> StringUtils.defaultString(item.getDeviceId())))
|
||||
.collect(Collectors.toList());
|
||||
if (CollectionUtils.isEmpty(scopeClusters)) {
|
||||
throw new ServiceException(String.format("电池堆[%s]下未配置电池簇,无法初始化单体电池", normalizedScopeDeviceId));
|
||||
}
|
||||
return new SingleBatteryInitScope(
|
||||
normalizedSiteId,
|
||||
normalizedScopeType,
|
||||
normalizedScopeDeviceId,
|
||||
scopeClusters,
|
||||
StringUtils.trim(scopeClusters.get(0).getDeviceId()),
|
||||
allSiteDevices
|
||||
);
|
||||
}
|
||||
|
||||
private List<EmsDevicesSetting> getScopeBatteryList(List<EmsDevicesSetting> allSiteDevices, Set<String> scopeClusterIdSet) {
|
||||
if (CollectionUtils.isEmpty(allSiteDevices) || CollectionUtils.isEmpty(scopeClusterIdSet)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return allSiteDevices.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.filter(item -> StringUtils.equals(DeviceCategory.BATTERY.getCode(), StringUtils.trim(item.getDeviceCategory())))
|
||||
.filter(item -> scopeClusterIdSet.contains(StringUtils.trim(item.getParentId())))
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
}
|
||||
|
||||
private List<EmsDevicesSetting> createMissingSingleBatteries(String siteId,
|
||||
String clusterDeviceId,
|
||||
int appendCount,
|
||||
Map<String, EmsDevicesSetting> deviceMap,
|
||||
String operName) {
|
||||
List<EmsDevicesSetting> result = new ArrayList<>();
|
||||
if (appendCount < 1) {
|
||||
return result;
|
||||
}
|
||||
Set<String> existingIds = deviceMap.keySet().stream()
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.map(String::trim)
|
||||
.collect(Collectors.toSet());
|
||||
Set<String> clusterBatteryIds = deviceMap.values().stream()
|
||||
.filter(Objects::nonNull)
|
||||
.filter(item -> StringUtils.equals(DeviceCategory.BATTERY.getCode(), StringUtils.trim(item.getDeviceCategory())))
|
||||
.filter(item -> StringUtils.equals(clusterDeviceId, StringUtils.trim(item.getParentId())))
|
||||
.map(EmsDevicesSetting::getDeviceId)
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.map(String::trim)
|
||||
.collect(Collectors.toCollection(HashSet::new));
|
||||
Date now = DateUtils.getNowDate();
|
||||
int serial = 1;
|
||||
while (result.size() < appendCount) {
|
||||
String candidateId = formatSingleBatterySerial(serial);
|
||||
serial++;
|
||||
if (existingIds.contains(candidateId) || clusterBatteryIds.contains(candidateId)) {
|
||||
continue;
|
||||
}
|
||||
EmsDevicesSetting insertDevice = new EmsDevicesSetting();
|
||||
insertDevice.setSiteId(siteId);
|
||||
insertDevice.setDeviceId(candidateId);
|
||||
insertDevice.setDeviceName(candidateId);
|
||||
insertDevice.setDeviceType(DeviceType.TCP.name());
|
||||
insertDevice.setCommunicationStatus(CommunicationStatus.OK.getCode());
|
||||
insertDevice.setDeviceCategory(DeviceCategory.BATTERY.getCode());
|
||||
insertDevice.setDeviceStatus(DeviceRunningStatus.OFFLINE.getCode());
|
||||
insertDevice.setWorkStatus(WorkStatus.NORMAL.getCode());
|
||||
insertDevice.setParentId(clusterDeviceId);
|
||||
insertDevice.setDescription("single battery initialize");
|
||||
insertDevice.setCreateBy(operName);
|
||||
insertDevice.setUpdateBy(operName);
|
||||
insertDevice.setCreatedAt(now);
|
||||
insertDevice.setUpdatedAt(now);
|
||||
emsDevicesMapper.insertEmsDevicesSetting(insertDevice);
|
||||
existingIds.add(candidateId);
|
||||
clusterBatteryIds.add(candidateId);
|
||||
deviceMap.put(candidateId, insertDevice);
|
||||
result.add(insertDevice);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private String formatSingleBatterySerial(int serialNo) {
|
||||
return String.format("%03d", serialNo);
|
||||
}
|
||||
|
||||
private SingleBatteryFieldInitTask buildSingleBatteryFieldInitTask(String siteId,
|
||||
String clusterDeviceId,
|
||||
String batteryDeviceId,
|
||||
String fieldCode,
|
||||
String bizCode,
|
||||
String serialNo) {
|
||||
String pointId = clusterDeviceId + "DT" + bizCode + serialNo;
|
||||
return new SingleBatteryFieldInitTask(siteId, clusterDeviceId, batteryDeviceId, fieldCode, pointId);
|
||||
}
|
||||
|
||||
private void upsertSingleBatteryPointMatchForInit(List<EmsSiteMonitorPointMatch> insertList,
|
||||
Map<String, EmsSiteMonitorPointMatch> existingPointMatchMap,
|
||||
SingleBatteryConfigInitResultVo result,
|
||||
SingleBatteryFieldInitTask task,
|
||||
boolean pointExists,
|
||||
String operName) {
|
||||
String key = buildMatchKey(task.fieldCode, task.batteryDeviceId);
|
||||
EmsSiteMonitorPointMatch existing = existingPointMatchMap.get(key);
|
||||
String dataPoint = pointExists ? task.pointId : "";
|
||||
String fixedDataPoint = pointExists ? null : SINGLE_BATTERY_FIELD_VALUE_ZERO;
|
||||
int useFixedDisplay = pointExists ? 0 : USE_FIXED_DISPLAY_YES;
|
||||
if (existing == null) {
|
||||
EmsSiteMonitorPointMatch insertItem = new EmsSiteMonitorPointMatch();
|
||||
insertItem.setSiteId(task.siteId);
|
||||
insertItem.setFieldCode(task.fieldCode);
|
||||
insertItem.setDeviceId(task.batteryDeviceId);
|
||||
insertItem.setDataPoint(dataPoint);
|
||||
insertItem.setFixedDataPoint(fixedDataPoint);
|
||||
insertItem.setUseFixedDisplay(useFixedDisplay);
|
||||
insertItem.setCreateBy(operName);
|
||||
insertItem.setUpdateBy(operName);
|
||||
insertList.add(insertItem);
|
||||
result.setInsertedMappingCount(result.getInsertedMappingCount() + 1);
|
||||
return;
|
||||
}
|
||||
boolean changed = !StringUtils.equals(StringUtils.trimToEmpty(existing.getDataPoint()), dataPoint)
|
||||
|| !StringUtils.equals(StringUtils.trimToEmpty(existing.getFixedDataPoint()), StringUtils.trimToEmpty(fixedDataPoint))
|
||||
|| (existing.getUseFixedDisplay() == null ? 0 : existing.getUseFixedDisplay()) != useFixedDisplay;
|
||||
if (!changed) {
|
||||
return;
|
||||
}
|
||||
existing.setDataPoint(dataPoint);
|
||||
existing.setFixedDataPoint(fixedDataPoint);
|
||||
existing.setUseFixedDisplay(useFixedDisplay);
|
||||
existing.setUpdateBy(operName);
|
||||
emsSiteMonitorPointMatchMapper.updateEmsSiteMonitorPointMatch(existing);
|
||||
result.setUpdatedMappingCount(result.getUpdatedMappingCount() + 1);
|
||||
}
|
||||
|
||||
private static class SingleBatteryFieldInitTask {
|
||||
private final String siteId;
|
||||
private final String clusterDeviceId;
|
||||
private final String batteryDeviceId;
|
||||
private final String fieldCode;
|
||||
private final String pointId;
|
||||
|
||||
private SingleBatteryFieldInitTask(String siteId,
|
||||
String clusterDeviceId,
|
||||
String batteryDeviceId,
|
||||
String fieldCode,
|
||||
String pointId) {
|
||||
this.siteId = siteId;
|
||||
this.clusterDeviceId = clusterDeviceId;
|
||||
this.batteryDeviceId = batteryDeviceId;
|
||||
this.fieldCode = fieldCode;
|
||||
this.pointId = pointId;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public SingleBatteryMonitorImportResultVo importSingleBatteryMonitorMappings(String siteId, List<SingleBatteryMonitorImportRowVo> rows, String operName) {
|
||||
|
||||
@ -97,6 +97,7 @@ public class SingleSiteServiceImpl implements ISingleSiteService {
|
||||
"deviceId", "clusterDeviceId", "dataTimestamp"
|
||||
));
|
||||
private static final String MENU_SBJK_DTDC = "SBJK_DTDC";
|
||||
private static final String MENU_SBJK_BMSDCC = "SBJK_BMSDCC";
|
||||
|
||||
private static final String CLUSTER_DATA_TEP = "温度";
|
||||
|
||||
@ -1092,11 +1093,17 @@ public class SingleSiteServiceImpl implements ISingleSiteService {
|
||||
log.warn("getClusterDataInfoList early return, siteId is empty");
|
||||
return batteryDataStatsListVo;
|
||||
}
|
||||
List<SiteMonitorProjectDisplayVo> projectDisplayList = iEmsDeviceSettingService.getSiteMonitorProjectDisplay(siteId);
|
||||
Map<String, Map<String, SiteMonitorProjectDisplayVo>> batteryDisplayMap =
|
||||
buildBatteryDisplayMap(iEmsDeviceSettingService.getSiteMonitorProjectDisplay(siteId));
|
||||
buildBatteryDisplayMap(projectDisplayList);
|
||||
Map<String, Map<String, SiteMonitorProjectDisplayVo>> clusterDisplayMap =
|
||||
buildClusterDisplayMap(projectDisplayList);
|
||||
if (batteryDisplayMap.isEmpty()) {
|
||||
log.warn("getClusterDataInfoList no battery display data from projectDisplay, siteId={}", siteId);
|
||||
}
|
||||
if (clusterDisplayMap.isEmpty()) {
|
||||
log.warn("getClusterDataInfoList no cluster display data from projectDisplay, siteId={}", siteId);
|
||||
}
|
||||
log.info("getClusterDataInfoList battery list source projectDisplay, siteId={}, batteryCount={}",
|
||||
siteId, batteryDisplayMap.size());
|
||||
|
||||
@ -1136,6 +1143,9 @@ public class SingleSiteServiceImpl implements ISingleSiteService {
|
||||
fillBatteryValueFromProjectDisplay(batteryDataStatsVo, batteryDisplayMap.get(batteryDeviceId));
|
||||
batteryDataStatsVo.setDeviceId(batteryDeviceId);
|
||||
batteryDataStatsVo.setClusterDeviceId(currentClusterDeviceId);
|
||||
// 单体电池未配置 SOC/SOH 点位时,回退使用所属电池簇的 SOC/SOH 点位和值。
|
||||
applyClusterSocSohFallback(batteryDataStatsVo,
|
||||
clusterDisplayMap.get(currentClusterDeviceId), currentClusterDeviceId);
|
||||
batteryDataStatsListVo.add(batteryDataStatsVo);
|
||||
log.info("getClusterDataInfoList battery from projectDisplay list, siteId={}, batteryDeviceId={}, clusterDeviceId={}, voltage={}, temperature={}, soc={}, soh={}, voltagePointId={}, temperaturePointId={}, socPointId={}, sohPointId={}, dataTimestamp={}",
|
||||
siteId, batteryDeviceId, currentClusterDeviceId, batteryDataStatsVo.getVoltage(),
|
||||
@ -1149,7 +1159,7 @@ public class SingleSiteServiceImpl implements ISingleSiteService {
|
||||
log.info("getClusterDataInfoList fallback to realtime cache, siteId={}, stackDeviceId={}, clusterDeviceId={}, batteryId={}",
|
||||
siteId, targetStackDeviceId, targetClusterDeviceId, targetBatteryId);
|
||||
appendBatteryFromRealtimeCache(siteId, targetStackDeviceId, targetClusterDeviceId, targetBatteryId,
|
||||
batteryDisplayMap, batteryDataStatsListVo);
|
||||
batteryDisplayMap, clusterDisplayMap, batteryDataStatsListVo);
|
||||
}
|
||||
|
||||
log.info("getClusterDataInfoList end, siteId={}, stackDeviceId={}, clusterDeviceId={}, batteryId={}, total={}",
|
||||
@ -1162,6 +1172,7 @@ public class SingleSiteServiceImpl implements ISingleSiteService {
|
||||
String targetClusterDeviceId,
|
||||
String targetBatteryId,
|
||||
Map<String, Map<String, SiteMonitorProjectDisplayVo>> batteryDisplayMap,
|
||||
Map<String, Map<String, SiteMonitorProjectDisplayVo>> clusterDisplayMap,
|
||||
List<BatteryDataStatsListVo> targetList) {
|
||||
if (StringUtils.isBlank(siteId) || targetList == null) {
|
||||
return;
|
||||
@ -1204,6 +1215,9 @@ public class SingleSiteServiceImpl implements ISingleSiteService {
|
||||
batteryDataStatsVo.setClusterDeviceId(clusterId);
|
||||
}
|
||||
fillBatteryPointIdFromProjectDisplay(batteryDataStatsVo, batteryDisplayMap == null ? null : batteryDisplayMap.get(currentBatteryId));
|
||||
// Redis 实时缓存中的单体数据如果没有单独配置 SOC/SOH 点位,同样回退到电池簇配置。
|
||||
applyClusterSocSohFallback(batteryDataStatsVo,
|
||||
clusterDisplayMap == null ? null : clusterDisplayMap.get(clusterId), clusterId);
|
||||
targetList.add(batteryDataStatsVo);
|
||||
}
|
||||
}
|
||||
@ -1283,6 +1297,31 @@ public class SingleSiteServiceImpl implements ISingleSiteService {
|
||||
return result;
|
||||
}
|
||||
|
||||
private Map<String, Map<String, SiteMonitorProjectDisplayVo>> buildClusterDisplayMap(List<SiteMonitorProjectDisplayVo> displayList) {
|
||||
Map<String, Map<String, SiteMonitorProjectDisplayVo>> result = new HashMap<>();
|
||||
if (CollectionUtils.isEmpty(displayList)) {
|
||||
return result;
|
||||
}
|
||||
for (SiteMonitorProjectDisplayVo item : displayList) {
|
||||
if (item == null) {
|
||||
continue;
|
||||
}
|
||||
String menuCode = StringUtils.trimToEmpty(item.getMenuCode());
|
||||
String deviceId = StringUtils.trimToEmpty(item.getDeviceId());
|
||||
String fieldCode = StringUtils.trimToEmpty(item.getFieldCode());
|
||||
if (!MENU_SBJK_BMSDCC.equals(menuCode) || StringUtils.isEmpty(deviceId) || StringUtils.isEmpty(fieldCode)) {
|
||||
continue;
|
||||
}
|
||||
Map<String, SiteMonitorProjectDisplayVo> fieldMap = result.computeIfAbsent(deviceId, key -> new HashMap<>());
|
||||
fieldMap.put(fieldCode, item);
|
||||
String normalizedFieldCode = normalizeBatteryFieldCode(fieldCode);
|
||||
if (StringUtils.isNotBlank(normalizedFieldCode)) {
|
||||
fieldMap.put(normalizedFieldCode, item);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private String normalizeBatteryFieldCode(String fieldCode) {
|
||||
String normalized = StringUtils.trimToEmpty(fieldCode);
|
||||
if (StringUtils.isBlank(normalized)) {
|
||||
@ -1348,6 +1387,48 @@ public class SingleSiteServiceImpl implements ISingleSiteService {
|
||||
target.setSohPointId(sohVo == null ? null : StringUtils.trimToNull(sohVo.getDataPoint()));
|
||||
}
|
||||
|
||||
private void applyClusterSocSohFallback(BatteryDataStatsListVo target,
|
||||
Map<String, SiteMonitorProjectDisplayVo> clusterFieldMap,
|
||||
String clusterDeviceId) {
|
||||
if (target == null || clusterFieldMap == null || clusterFieldMap.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
boolean useClusterSoc = StringUtils.isBlank(target.getSocPointId());
|
||||
boolean useClusterSoh = StringUtils.isBlank(target.getSohPointId());
|
||||
if (!useClusterSoc && !useClusterSoh) {
|
||||
return;
|
||||
}
|
||||
|
||||
SiteMonitorProjectDisplayVo clusterSocVo = clusterFieldMap.get("currentsoc");
|
||||
SiteMonitorProjectDisplayVo clusterSohVo = clusterFieldMap.get("soh");
|
||||
Date latest = target.getDataTimestamp();
|
||||
|
||||
// 单体没有配置 SOC 点位时,使用所属电池簇的 currentSoc 作为兜底。
|
||||
if (useClusterSoc && clusterSocVo != null) {
|
||||
target.setSocPointId(StringUtils.trimToNull(clusterSocVo.getDataPoint()));
|
||||
if (StringUtils.isNotBlank(clusterSocVo.getFieldValue())) {
|
||||
target.setSoc(StringUtils.getBigDecimal(clusterSocVo.getFieldValue()));
|
||||
}
|
||||
latest = pickLaterTime(latest, clusterSocVo.getValueTime());
|
||||
}
|
||||
|
||||
// 单体没有配置 SOH 点位时,使用所属电池簇的 soh 作为兜底。
|
||||
if (useClusterSoh && clusterSohVo != null) {
|
||||
target.setSohPointId(StringUtils.trimToNull(clusterSohVo.getDataPoint()));
|
||||
if (StringUtils.isNotBlank(clusterSohVo.getFieldValue())) {
|
||||
target.setSoh(StringUtils.getBigDecimal(clusterSohVo.getFieldValue()));
|
||||
}
|
||||
latest = pickLaterTime(latest, clusterSohVo.getValueTime());
|
||||
}
|
||||
|
||||
if (latest != null) {
|
||||
target.setDataTimestamp(latest);
|
||||
}
|
||||
log.info("applyClusterSocSohFallback, clusterDeviceId={}, batteryDeviceId={}, useClusterSoc={}, useClusterSoh={}, socPointId={}, sohPointId={}, soc={}, soh={}",
|
||||
clusterDeviceId, target.getDeviceId(), useClusterSoc, useClusterSoh,
|
||||
target.getSocPointId(), target.getSohPointId(), target.getSoc(), target.getSoh());
|
||||
}
|
||||
|
||||
private Date pickLaterTime(Date left, Date right) {
|
||||
if (left == null) {
|
||||
return right;
|
||||
|
||||
Reference in New Issue
Block a user