|
@@ -143,7 +143,7 @@ public class SeSnapshotServiceImpl implements SeSnapshotService {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private void processFeederCurrent(JSONObject f, FhzgSeSnapshotDetail detail,
|
|
private void processFeederCurrent(JSONObject f, FhzgSeSnapshotDetail detail,
|
|
|
- LocalDateTime snapTime, Map<String, String[]> feederMap) {
|
|
|
|
|
|
|
+ LocalDateTime snapTime, Map<String, String[]> feederMap) {
|
|
|
if (detail.getCurrentStatus() == null) return;
|
|
if (detail.getCurrentStatus() == null) return;
|
|
|
String feederId = detail.getFeederId();
|
|
String feederId = detail.getFeederId();
|
|
|
String[] loc = feederMap.get(feederId);
|
|
String[] loc = feederMap.get(feederId);
|
|
@@ -194,10 +194,11 @@ public class SeSnapshotServiceImpl implements SeSnapshotService {
|
|
|
currentEventMapper.insert(event);
|
|
currentEventMapper.insert(event);
|
|
|
state.setAlarmTriggered(1);
|
|
state.setAlarmTriggered(1);
|
|
|
state.setAlarmEventId(event.getId());
|
|
state.setAlarmEventId(event.getId());
|
|
|
- // 异步触发重构算法(需要 feeder_id + point_time)
|
|
|
|
|
|
|
+ // 取事件窗口内最大负载率断面时刻作为重构触发断面时刻
|
|
|
|
|
+ LocalDateTime maxLrTime = findMaxLoadRateTime(feederId, state.getFirstOverTime(), snapTime);
|
|
|
eventPublisher.publishEvent(new ReconTriggerEvent(
|
|
eventPublisher.publishEvent(new ReconTriggerEvent(
|
|
|
event.getId(), feederId, feederName, countyId, subsId,
|
|
event.getId(), feederId, feederName, countyId, subsId,
|
|
|
- alarmType, snapTime, state.getFirstOverTime()));
|
|
|
|
|
|
|
+ alarmType, maxLrTime, state.getFirstOverTime()));
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
|
if (state.getAlarmTriggered() == 1 && state.getAlarmEventId() != null) {
|
|
if (state.getAlarmTriggered() == 1 && state.getAlarmEventId() != null) {
|
|
@@ -215,7 +216,7 @@ public class SeSnapshotServiceImpl implements SeSnapshotService {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private void processFeederVoltage(JSONObject f, FhzgSeSnapshotDetail detail,
|
|
private void processFeederVoltage(JSONObject f, FhzgSeSnapshotDetail detail,
|
|
|
- LocalDateTime snapTime, Map<String, String[]> feederMap) {
|
|
|
|
|
|
|
+ LocalDateTime snapTime, Map<String, String[]> feederMap) {
|
|
|
if (detail.getVoltageStatus() == null) return;
|
|
if (detail.getVoltageStatus() == null) return;
|
|
|
String[] loc = feederMap.get(detail.getFeederId());
|
|
String[] loc = feederMap.get(detail.getFeederId());
|
|
|
checkVoltageMonitor(detail.getFeederId(), "feeder", detail.getVoltageRatio(), detail.getVoltageStatus(),
|
|
checkVoltageMonitor(detail.getFeederId(), "feeder", detail.getVoltageRatio(), detail.getVoltageStatus(),
|
|
@@ -246,7 +247,7 @@ public class SeSnapshotServiceImpl implements SeSnapshotService {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private void processMvtransMonitor(JSONObject m, FhzgSeSnapshotDetail detail,
|
|
private void processMvtransMonitor(JSONObject m, FhzgSeSnapshotDetail detail,
|
|
|
- LocalDateTime snapTime, Map<String, String[]> feederMap) {
|
|
|
|
|
|
|
+ LocalDateTime snapTime, Map<String, String[]> feederMap) {
|
|
|
if (detail.getVoltageStatus() == null) return;
|
|
if (detail.getVoltageStatus() == null) return;
|
|
|
String mvtransId = detail.getDeviceId();
|
|
String mvtransId = detail.getDeviceId();
|
|
|
String[] loc = feederMap.get(detail.getFeederId());
|
|
String[] loc = feederMap.get(detail.getFeederId());
|
|
@@ -270,9 +271,9 @@ public class SeSnapshotServiceImpl implements SeSnapshotService {
|
|
|
// ============================================================
|
|
// ============================================================
|
|
|
|
|
|
|
|
private void checkVoltageMonitor(String deviceId, String deviceType,
|
|
private void checkVoltageMonitor(String deviceId, String deviceType,
|
|
|
- BigDecimal voltageRatio, int voltageStatus,
|
|
|
|
|
- LocalDateTime snapTime, String feederId, String feederName,
|
|
|
|
|
- String subsId, String countyId, String mvtransId, String consumerId) {
|
|
|
|
|
|
|
+ BigDecimal voltageRatio, int voltageStatus,
|
|
|
|
|
+ LocalDateTime snapTime, String feederId, String feederName,
|
|
|
|
|
+ String subsId, String countyId, String mvtransId, String consumerId) {
|
|
|
FhzgSeMonitorVoltage state = monitorVoltageMapper.selectOne(
|
|
FhzgSeMonitorVoltage state = monitorVoltageMapper.selectOne(
|
|
|
new LambdaQueryWrapper<FhzgSeMonitorVoltage>()
|
|
new LambdaQueryWrapper<FhzgSeMonitorVoltage>()
|
|
|
.eq(FhzgSeMonitorVoltage::getDeviceId, deviceId)
|
|
.eq(FhzgSeMonitorVoltage::getDeviceId, deviceId)
|
|
@@ -299,53 +300,53 @@ public class SeSnapshotServiceImpl implements SeSnapshotService {
|
|
|
if (state.getFirstOverTime() != null
|
|
if (state.getFirstOverTime() != null
|
|
|
&& Duration.between(state.getFirstOverTime(), snapTime).toMinutes() >= SeMonitorThreshold.TRIGGER_DURATION_MINUTES
|
|
&& Duration.between(state.getFirstOverTime(), snapTime).toMinutes() >= SeMonitorThreshold.TRIGGER_DURATION_MINUTES
|
|
|
&& state.getAlarmTriggered() == 0) {
|
|
&& state.getAlarmTriggered() == 0) {
|
|
|
- String countyName = lookupCountyName(countyId, null);
|
|
|
|
|
-
|
|
|
|
|
- if ("feeder".equals(deviceType)) {
|
|
|
|
|
- // === 馈线自身越限 → 创建 feeder 级独立事件 ===
|
|
|
|
|
- String alarmType = resolveVoltageAlarmType(deviceType, voltageStatus);
|
|
|
|
|
- BigDecimal threshold = resolveVoltageThreshold(deviceType, voltageStatus);
|
|
|
|
|
- BigDecimal[] vr = queryVoltageRangeFromSnap(feederId, state.getFirstOverTime(), snapTime);
|
|
|
|
|
- int[] mc = queryMvtransCounts(feederId, state.getFirstOverTime(), snapTime);
|
|
|
|
|
- FhzgSeVoltageEvent event = FhzgSeVoltageEvent.builder()
|
|
|
|
|
- .deviceId(deviceId).deviceName(feederName)
|
|
|
|
|
- .deviceType(deviceType).alarmLevel(deviceType).alarmType(alarmType)
|
|
|
|
|
- .feederId(feederId).feederName(feederName)
|
|
|
|
|
- .subsId(subsId).countyId(countyId).countyName(countyName)
|
|
|
|
|
- .threshold(threshold)
|
|
|
|
|
- .firstOverTime(state.getFirstOverTime()).triggerTime(snapTime)
|
|
|
|
|
- .triggerValue(voltageRatio)
|
|
|
|
|
- .voltageRangeMax(vr[0]).voltageRangeMin(vr[1])
|
|
|
|
|
- .overUpperMvtrans(mc[0]).overLowerMvtrans(mc[1])
|
|
|
|
|
- .lastValue(voltageRatio).status(1).build();
|
|
|
|
|
- voltageEventMapper.insert(event);
|
|
|
|
|
- state.setAlarmTriggered(1); state.setAlarmEventId(event.getId());
|
|
|
|
|
- // 馈线越下限 → 异步触发重构算法
|
|
|
|
|
- if ("feeder".equals(deviceType) && "voltage_under".equals(alarmType)) {
|
|
|
|
|
- eventPublisher.publishEvent(new ReconTriggerEvent(
|
|
|
|
|
- event.getId(), feederId, feederName, countyId, subsId,
|
|
|
|
|
- alarmType, snapTime, state.getFirstOverTime()));
|
|
|
|
|
- }
|
|
|
|
|
- } else if ("mvtrans".equals(deviceType)) {
|
|
|
|
|
- // === 台区越限 → 创建 mvtrans 级独立事件 ===
|
|
|
|
|
- String alarmType = resolveVoltageAlarmType(deviceType, voltageStatus);
|
|
|
|
|
- BigDecimal threshold = resolveVoltageThreshold(deviceType, voltageStatus);
|
|
|
|
|
- FhzgSeVoltageEvent event = FhzgSeVoltageEvent.builder()
|
|
|
|
|
- .deviceId(deviceId).deviceName(feederName)
|
|
|
|
|
- .deviceType(deviceType).alarmLevel(deviceType).alarmType(alarmType)
|
|
|
|
|
- .feederId(feederId).feederName(feederName)
|
|
|
|
|
- .subsId(subsId).countyId(countyId).countyName(countyName)
|
|
|
|
|
- .mvtransId(mvtransId)
|
|
|
|
|
- .threshold(threshold)
|
|
|
|
|
- .firstOverTime(state.getFirstOverTime()).triggerTime(snapTime)
|
|
|
|
|
- .triggerValue(voltageRatio).lastValue(voltageRatio).status(1)
|
|
|
|
|
- .build();
|
|
|
|
|
- voltageEventMapper.insert(event);
|
|
|
|
|
- state.setAlarmTriggered(1);
|
|
|
|
|
- state.setAlarmEventId(event.getId());
|
|
|
|
|
- }
|
|
|
|
|
- // consumer 级别暂走旧逻辑(如有可后续优化)
|
|
|
|
|
|
|
+ String countyName = lookupCountyName(countyId, null);
|
|
|
|
|
+
|
|
|
|
|
+ if ("feeder".equals(deviceType)) {
|
|
|
|
|
+ // === 馈线自身越限 → 创建 feeder 级独立事件 ===
|
|
|
|
|
+ String alarmType = resolveVoltageAlarmType(deviceType, voltageStatus);
|
|
|
|
|
+ BigDecimal threshold = resolveVoltageThreshold(deviceType, voltageStatus);
|
|
|
|
|
+ BigDecimal[] vr = queryVoltageRangeFromSnap(feederId, state.getFirstOverTime(), snapTime);
|
|
|
|
|
+ int[] mc = queryMvtransCounts(feederId, state.getFirstOverTime(), snapTime);
|
|
|
|
|
+ FhzgSeVoltageEvent event = FhzgSeVoltageEvent.builder()
|
|
|
|
|
+ .deviceId(deviceId).deviceName(feederName)
|
|
|
|
|
+ .deviceType(deviceType).alarmLevel(deviceType).alarmType(alarmType)
|
|
|
|
|
+ .feederId(feederId).feederName(feederName)
|
|
|
|
|
+ .subsId(subsId).countyId(countyId).countyName(countyName)
|
|
|
|
|
+ .threshold(threshold)
|
|
|
|
|
+ .firstOverTime(state.getFirstOverTime()).triggerTime(snapTime)
|
|
|
|
|
+ .triggerValue(voltageRatio)
|
|
|
|
|
+ .voltageRangeMax(vr[0]).voltageRangeMin(vr[1])
|
|
|
|
|
+ .overUpperMvtrans(mc[0]).overLowerMvtrans(mc[1])
|
|
|
|
|
+ .lastValue(voltageRatio).status(1).build();
|
|
|
|
|
+ voltageEventMapper.insert(event);
|
|
|
|
|
+ state.setAlarmTriggered(1); state.setAlarmEventId(event.getId());
|
|
|
|
|
+ // 馈线越下限 → 异步触发重构算法
|
|
|
|
|
+ if ("feeder".equals(deviceType) && "voltage_under".equals(alarmType)) {
|
|
|
|
|
+ eventPublisher.publishEvent(new ReconTriggerEvent(
|
|
|
|
|
+ event.getId(), feederId, feederName, countyId, subsId,
|
|
|
|
|
+ alarmType, snapTime, state.getFirstOverTime()));
|
|
|
}
|
|
}
|
|
|
|
|
+ } else if ("mvtrans".equals(deviceType)) {
|
|
|
|
|
+ // === 台区越限 → 创建 mvtrans 级独立事件 ===
|
|
|
|
|
+ String alarmType = resolveVoltageAlarmType(deviceType, voltageStatus);
|
|
|
|
|
+ BigDecimal threshold = resolveVoltageThreshold(deviceType, voltageStatus);
|
|
|
|
|
+ FhzgSeVoltageEvent event = FhzgSeVoltageEvent.builder()
|
|
|
|
|
+ .deviceId(deviceId).deviceName(feederName)
|
|
|
|
|
+ .deviceType(deviceType).alarmLevel(deviceType).alarmType(alarmType)
|
|
|
|
|
+ .feederId(feederId).feederName(feederName)
|
|
|
|
|
+ .subsId(subsId).countyId(countyId).countyName(countyName)
|
|
|
|
|
+ .mvtransId(mvtransId)
|
|
|
|
|
+ .threshold(threshold)
|
|
|
|
|
+ .firstOverTime(state.getFirstOverTime()).triggerTime(snapTime)
|
|
|
|
|
+ .triggerValue(voltageRatio).lastValue(voltageRatio).status(1)
|
|
|
|
|
+ .build();
|
|
|
|
|
+ voltageEventMapper.insert(event);
|
|
|
|
|
+ state.setAlarmTriggered(1);
|
|
|
|
|
+ state.setAlarmEventId(event.getId());
|
|
|
|
|
+ }
|
|
|
|
|
+ // consumer 级别暂走旧逻辑(如有可后续优化)
|
|
|
|
|
+ }
|
|
|
} else {
|
|
} else {
|
|
|
if (state.getAlarmTriggered() == 1 && state.getAlarmEventId() != null) {
|
|
if (state.getAlarmTriggered() == 1 && state.getAlarmEventId() != null) {
|
|
|
// 只有 feeder 自身恢复才标聚合事件 status=2;mvtrans 恢复不动聚合事件
|
|
// 只有 feeder 自身恢复才标聚合事件 status=2;mvtrans 恢复不动聚合事件
|
|
@@ -501,6 +502,26 @@ public class SeSnapshotServiceImpl implements SeSnapshotService {
|
|
|
try { return new BigDecimal(v); } catch (NumberFormatException e) { return null; }
|
|
try { return new BigDecimal(v); } catch (NumberFormatException e) { return null; }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 查事件窗口 [start, end] 内该馈线最大负载率的那条断面的 snapshotTime
|
|
|
|
|
+ */
|
|
|
|
|
+ private LocalDateTime findMaxLoadRateTime(String feederId, LocalDateTime start, LocalDateTime end) {
|
|
|
|
|
+ if (feederId == null || start == null) return end;
|
|
|
|
|
+ List<FhzgSeSnapshotDetail> list = snapshotDetailMapper.selectList(
|
|
|
|
|
+ new LambdaQueryWrapper<FhzgSeSnapshotDetail>()
|
|
|
|
|
+ .eq(FhzgSeSnapshotDetail::getFeederId, feederId)
|
|
|
|
|
+ .eq(FhzgSeSnapshotDetail::getDeviceType, "feeder")
|
|
|
|
|
+ .isNotNull(FhzgSeSnapshotDetail::getLoadRate)
|
|
|
|
|
+ .ge(FhzgSeSnapshotDetail::getSnapshotTime, start)
|
|
|
|
|
+ .le(FhzgSeSnapshotDetail::getSnapshotTime, end != null ? end : LocalDateTime.now())
|
|
|
|
|
+ .orderByDesc(FhzgSeSnapshotDetail::getLoadRate)
|
|
|
|
|
+ .last("LIMIT 1"));
|
|
|
|
|
+ if (list != null && !list.isEmpty()) {
|
|
|
|
|
+ return list.get(0).getSnapshotTime();
|
|
|
|
|
+ }
|
|
|
|
|
+ return end;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 按 countyId 从 SeSnapshotConstants.COUNTIES 查 countyName。
|
|
* 按 countyId 从 SeSnapshotConstants.COUNTIES 查 countyName。
|
|
|
* COUNTIES 的 key=countyId(=maintOrg UUID),value=[countySid, countyName]
|
|
* COUNTIES 的 key=countyId(=maintOrg UUID),value=[countySid, countyName]
|
|
@@ -527,7 +548,7 @@ public class SeSnapshotServiceImpl implements SeSnapshotService {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private void buildFeederMappingRecursive(List<FeederGroupTreeNode> nodes, Map<String, String[]> map,
|
|
private void buildFeederMappingRecursive(List<FeederGroupTreeNode> nodes, Map<String, String[]> map,
|
|
|
- String parentSubsId, String parentCountyId) {
|
|
|
|
|
|
|
+ String parentSubsId, String parentCountyId) {
|
|
|
if (nodes == null) return;
|
|
if (nodes == null) return;
|
|
|
for (FeederGroupTreeNode node : nodes) {
|
|
for (FeederGroupTreeNode node : nodes) {
|
|
|
String subsId = parentSubsId, countyId = parentCountyId;
|
|
String subsId = parentSubsId, countyId = parentCountyId;
|
|
@@ -562,4 +583,4 @@ public class SeSnapshotServiceImpl implements SeSnapshotService {
|
|
|
// 重新走正常流程写入(此时防重逻辑不会跳过任何记录)
|
|
// 重新走正常流程写入(此时防重逻辑不会跳过任何记录)
|
|
|
processSnapshot(snapshotJson);
|
|
processSnapshot(snapshotJson);
|
|
|
}
|
|
}
|
|
|
-}
|
|
|
|
|
|
|
+}
|