|
@@ -4,6 +4,7 @@ import cn.hutool.core.lang.Snowflake;
|
|
|
import cn.hutool.core.util.IdUtil;
|
|
import cn.hutool.core.util.IdUtil;
|
|
|
import com.alibaba.fastjson.JSON;
|
|
import com.alibaba.fastjson.JSON;
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
import com.hdkj.hussar.ApiResponse;
|
|
import com.hdkj.hussar.ApiResponse;
|
|
@@ -18,6 +19,7 @@ import com.hdkj.lt.bf.mapper.FhzgSeEventStateEstimationMapper;
|
|
|
import com.hdkj.lt.bf.mapper.FhzgSeVoltageEventMapper;
|
|
import com.hdkj.lt.bf.mapper.FhzgSeVoltageEventMapper;
|
|
|
import com.hdkj.lt.bf.mapper.XlRelMapper;
|
|
import com.hdkj.lt.bf.mapper.XlRelMapper;
|
|
|
import com.hdkj.lt.bf.entity.dto.XlRelDTO;
|
|
import com.hdkj.lt.bf.entity.dto.XlRelDTO;
|
|
|
|
|
+import com.hdkj.lt.bf.service.FhzgSeEventStateEstimationService;
|
|
|
import com.hdkj.lt.core.bizms.modle.dto.StateEstimation;
|
|
import com.hdkj.lt.core.bizms.modle.dto.StateEstimation;
|
|
|
import com.hdkj.lt.core.bizms.modle.po.DwdShbDsFeederBase;
|
|
import com.hdkj.lt.core.bizms.modle.po.DwdShbDsFeederBase;
|
|
|
import com.hdkj.lt.core.bizms.modle.po.Jxz;
|
|
import com.hdkj.lt.core.bizms.modle.po.Jxz;
|
|
@@ -34,6 +36,7 @@ import com.hdkj.lt.modle.dto.simulation.SwitchFeederDTO;
|
|
|
import com.hdkj.lt.modle.vo.recon.ReconstructionParam;
|
|
import com.hdkj.lt.modle.vo.recon.ReconstructionParam;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
import lombok.RequiredArgsConstructor;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
+import org.apache.commons.compress.utils.Lists;
|
|
|
import org.springframework.context.event.EventListener;
|
|
import org.springframework.context.event.EventListener;
|
|
|
import org.springframework.data.redis.connection.stream.Consumer;
|
|
import org.springframework.data.redis.connection.stream.Consumer;
|
|
|
import org.springframework.data.redis.connection.stream.MapRecord;
|
|
import org.springframework.data.redis.connection.stream.MapRecord;
|
|
@@ -90,7 +93,7 @@ public class ReconTriggerListener {
|
|
|
private final FhzgSeVoltageEventMapper voltageEventMapper;
|
|
private final FhzgSeVoltageEventMapper voltageEventMapper;
|
|
|
private final RedisTemplate<String, Object> redisTemplate;
|
|
private final RedisTemplate<String, Object> redisTemplate;
|
|
|
private final FhzgSeEventStateEstimationMapper stateEstimationMapper;
|
|
private final FhzgSeEventStateEstimationMapper stateEstimationMapper;
|
|
|
- private final IStateEstimationApiClient stateEstimationApiClient;
|
|
|
|
|
|
|
+ private final FhzgSeEventStateEstimationService seEventStateEstimationService;
|
|
|
|
|
|
|
|
private static final DateTimeFormatter DT_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
|
private static final DateTimeFormatter DT_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
|
|
private final ObjectMapper writeMapper = new ObjectMapper();
|
|
private final ObjectMapper writeMapper = new ObjectMapper();
|
|
@@ -287,6 +290,8 @@ public class ReconTriggerListener {
|
|
|
// ============================================================
|
|
// ============================================================
|
|
|
|
|
|
|
|
private void handleReconTrigger(ReconTriggerEvent event) {
|
|
private void handleReconTrigger(ReconTriggerEvent event) {
|
|
|
|
|
+ // 保存状估数据
|
|
|
|
|
+ saveStateEstimation(event);
|
|
|
// 幂等保护:事件已完成重构(有方案/无方案)则跳过,防重投/重复触发重复调用重构接口
|
|
// 幂等保护:事件已完成重构(有方案/无方案)则跳过,防重投/重复触发重复调用重构接口
|
|
|
Integer doneStatus = queryReconStatus(event.getEventId(), event.getAlarmType());
|
|
Integer doneStatus = queryReconStatus(event.getEventId(), event.getAlarmType());
|
|
|
if (doneStatus != null && (doneStatus == RECON_COMPLETED || doneStatus == RECON_NO_PLAN)) {
|
|
if (doneStatus != null && (doneStatus == RECON_COMPLETED || doneStatus == RECON_NO_PLAN)) {
|
|
@@ -308,8 +313,7 @@ public class ReconTriggerListener {
|
|
|
log.info("重构触发: eventId={}, feederId={}, alarmType={}, pointTime={}",
|
|
log.info("重构触发: eventId={}, feederId={}, alarmType={}, pointTime={}",
|
|
|
event.getEventId(), event.getFeederId(), event.getAlarmType(), event.getPointTime());
|
|
event.getEventId(), event.getFeederId(), event.getAlarmType(), event.getPointTime());
|
|
|
|
|
|
|
|
- // 保存状估数据
|
|
|
|
|
- CompletableFuture.runAsync(() -> saveStateEstimation(event));
|
|
|
|
|
|
|
+
|
|
|
// 异步调用求解器,不阻塞后续重构请求
|
|
// 异步调用求解器,不阻塞后续重构请求
|
|
|
CompletableFuture.runAsync(() -> callSolver(event));
|
|
CompletableFuture.runAsync(() -> callSolver(event));
|
|
|
|
|
|
|
@@ -506,66 +510,19 @@ public class ReconTriggerListener {
|
|
|
* @param event
|
|
* @param event
|
|
|
*/
|
|
*/
|
|
|
private void saveStateEstimation(ReconTriggerEvent event){
|
|
private void saveStateEstimation(ReconTriggerEvent event){
|
|
|
- // 1. 查询接线组线路
|
|
|
|
|
- Long eventId = event.getEventId();
|
|
|
|
|
- List<Jxz> jxzList = jxzMapper.queryJxzXl(event.getFeederId());
|
|
|
|
|
- List<String> groupFeederIds = jxzList.stream()
|
|
|
|
|
- .map(Jxz::getFeederId)
|
|
|
|
|
- .filter(Objects::nonNull)
|
|
|
|
|
- .distinct()
|
|
|
|
|
- .collect(Collectors.toList());
|
|
|
|
|
- //没有接线组只存当前线路数据
|
|
|
|
|
- if (groupFeederIds.isEmpty()) {
|
|
|
|
|
- groupFeederIds = Collections.singletonList(event.getFeederId());
|
|
|
|
|
- }
|
|
|
|
|
- Snowflake snowflake = IdUtil.getSnowflake(1,1);
|
|
|
|
|
- for (String feeder : groupFeederIds) {
|
|
|
|
|
- StateEstimationRequest req = buildStateEstimationReq(event.getTriggerTime().format(DT_FMT));
|
|
|
|
|
- req.setPsrIds(Collections.singletonList(feeder));
|
|
|
|
|
- StateEstimation stateEstimation = callWithRetry(feeder, req);
|
|
|
|
|
- if(Objects.nonNull(stateEstimation)){
|
|
|
|
|
- FhzgSeEventStateEstimation estimation = FhzgSeEventStateEstimation.builder()
|
|
|
|
|
- .id(snowflake.nextId()).eventId(eventId).feederId(feeder)
|
|
|
|
|
- .createTime(new Date()).build();
|
|
|
|
|
- try {
|
|
|
|
|
- String jsonStr = writeMapper.writeValueAsString(stateEstimation);
|
|
|
|
|
- estimation.setStateEstimationJson(jsonStr);
|
|
|
|
|
- } catch (JsonProcessingException e) {
|
|
|
|
|
- log.warn("馈线={} 状估数据 序列化失败: {}", feeder, e.getMessage());
|
|
|
|
|
- continue;
|
|
|
|
|
- }
|
|
|
|
|
- try {
|
|
|
|
|
- stateEstimationMapper.insert(estimation);
|
|
|
|
|
- log.info("馈线={} ,事件={} ,状估数据 保存成功!", feeder, eventId);
|
|
|
|
|
- } catch (Exception e) {
|
|
|
|
|
- log.error("馈线={} ,事件={} ,落库失败: {}", feeder, eventId, e.getMessage(), e);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- private StateEstimationRequest buildStateEstimationReq(String pointTime){
|
|
|
|
|
- StateEstimationRequest req = new StateEstimationRequest();
|
|
|
|
|
- req.setContainerCode(Collections.singletonList("switch"));
|
|
|
|
|
- req.setStartTime(pointTime);
|
|
|
|
|
- req.setEndTime(pointTime);
|
|
|
|
|
- return req;
|
|
|
|
|
- }
|
|
|
|
|
- private static final int RETRY_COUNT = 2;
|
|
|
|
|
- private StateEstimation callWithRetry(String feeder, StateEstimationRequest req) {
|
|
|
|
|
- int maxAttempts = RETRY_COUNT + 1;
|
|
|
|
|
- Exception last = null;
|
|
|
|
|
- for (int attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
|
|
|
- try {
|
|
|
|
|
- ApiResponse<StateEstimation> resp = stateEstimationApiClient.queryByFeeder(req);
|
|
|
|
|
- if (resp != null) {
|
|
|
|
|
- return resp.getData();
|
|
|
|
|
- }
|
|
|
|
|
- } catch (Exception e) {
|
|
|
|
|
- last = e;
|
|
|
|
|
- log.warn(" 第{}/{}次: {}, psrIds ={}", attempt, maxAttempts, e.getMessage(), feeder);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ //
|
|
|
|
|
+ log.info("=========状估数据=========");
|
|
|
|
|
+ Long selectCount = stateEstimationMapper.selectCount(new LambdaQueryWrapper<FhzgSeEventStateEstimation>()
|
|
|
|
|
+ .eq(FhzgSeEventStateEstimation::getEventId, event.getEventId())
|
|
|
|
|
+ .eq(FhzgSeEventStateEstimation::getAlarmType, event.getAlarmType()));
|
|
|
|
|
+ log.info("eventId={}, 状估数据有【{}】条", event.getEventId(), selectCount);
|
|
|
|
|
+ if(selectCount == null || selectCount <= 0) {
|
|
|
|
|
+ CompletableFuture.runAsync(() -> {
|
|
|
|
|
+ FhzgSeEventStateEstimation estimation = new FhzgSeEventStateEstimation();
|
|
|
|
|
+ estimation.setEventId(event.getEventId()).setFeederId(event.getFeederId())
|
|
|
|
|
+ .setTriggerTime(event.getTriggerTime().format(DT_FMT)).setAlarmType(event.getAlarmType());
|
|
|
|
|
+ seEventStateEstimationService.saveStateEstimation(estimation);
|
|
|
|
|
+ });
|
|
|
}
|
|
}
|
|
|
- throw new RuntimeException("状估调用失败 (已重试 " + RETRY_COUNT+ " 次), psrIds ="
|
|
|
|
|
- + feeder + ", 最后错误: " + (last == null ? "unknown" : last.getMessage()), last);
|
|
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|