Merge branch 'test'
This commit is contained in:
commit
88d9ae234c
|
@ -0,0 +1,8 @@
|
|||
package club.joylink.rtss.constants;
|
||||
|
||||
public interface ProjectCode {
|
||||
|
||||
String THAILAND_SANDBOX = "THAILAND_SANDBOX";
|
||||
String SR_SANDBOX = "SR_SANDBOX";
|
||||
|
||||
}
|
|
@ -7,12 +7,32 @@ import club.joylink.rtss.services.project.DeviceService;
|
|||
import club.joylink.rtss.vo.AccountVO;
|
||||
import club.joylink.rtss.vo.LoginUserInfoVO;
|
||||
import club.joylink.rtss.vo.client.PageVO;
|
||||
import club.joylink.rtss.vo.client.project.*;
|
||||
import club.joylink.rtss.vo.client.project.IbpConfigVO;
|
||||
import club.joylink.rtss.vo.client.project.LswConfigVO;
|
||||
import club.joylink.rtss.vo.client.project.LwConfigVO;
|
||||
import club.joylink.rtss.vo.client.project.PlcGatewayConfigVO;
|
||||
import club.joylink.rtss.vo.client.project.ProjectDevicePageQueryVO;
|
||||
import club.joylink.rtss.vo.client.project.ProjectDeviceVO;
|
||||
import club.joylink.rtss.vo.client.project.PscConfigVO;
|
||||
import club.joylink.rtss.vo.client.project.PsdConfigVO;
|
||||
import club.joylink.rtss.vo.client.project.PslConfigVO;
|
||||
import club.joylink.rtss.vo.client.project.RelationLoginConfigVO;
|
||||
import club.joylink.rtss.vo.client.project.SignalConfigVO;
|
||||
import club.joylink.rtss.vo.client.project.SwitchConfigVO;
|
||||
import club.joylink.rtss.vo.client.project.VrIbpConfigVO;
|
||||
import club.joylink.rtss.vo.client.project.VrpsdConfigVO;
|
||||
import java.util.List;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestAttribute;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 项目设备管理接口(新)
|
||||
|
@ -258,4 +278,10 @@ public class DeviceController {
|
|||
AccountVO accountVO) {
|
||||
this.deviceService.addOrUpdateSayDeviceConfig(accountVO);
|
||||
}
|
||||
|
||||
@PostMapping("/thailand/addOrUpdate/{mapId}")
|
||||
public void addOrUpdateThailandDeviceConfig(@RequestAttribute(name = AuthenticateInterceptor.LOGIN_USER_KEY)
|
||||
AccountVO accountVO, @PathVariable Long mapId) {
|
||||
this.deviceService.addOrUpdateThailandDeviceConfig(accountVO, mapId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -403,7 +403,7 @@ public class OrgUserService implements IOrgUserService {
|
|||
Map<Long, List<UserSimulationRecord>> userRecordMap = records.stream()
|
||||
.collect(Collectors.groupingBy(UserSimulationRecord::getUserId));
|
||||
vos.forEach(vo -> {
|
||||
List<UserSimulationRecord> recordList = userRecordMap.get(vo.getUserId());
|
||||
List<UserSimulationRecord> recordList = userRecordMap.getOrDefault(vo.getUserId(), List.of());
|
||||
long simDuration = recordList.stream().filter(record -> UserSimulationRecordManager.SimulationUseInfo.SIMULATION.equals(record.getType()))
|
||||
.mapToLong(UserSimulationRecord::getDuration)
|
||||
.sum();
|
||||
|
|
|
@ -23,6 +23,7 @@ import com.google.common.base.Joiner;
|
|||
import com.google.common.base.Strings;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
@ -64,6 +65,8 @@ public class PaperUserService {
|
|||
private PagerQuestionService paperQuestionService;
|
||||
@Autowired
|
||||
private Training2PublishService training2PublishService;
|
||||
@Autowired
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
/**
|
||||
* 获取理论或实操的所有标签
|
||||
|
@ -214,16 +217,18 @@ public class PaperUserService {
|
|||
rsp.setCommonScore(scoreCommon);
|
||||
rsp.setTrainingScore(scoreTraining);
|
||||
rsp.setPassScore(composition.getPassScore());
|
||||
this.publishUserExam();
|
||||
this.publishUserExam(user, rsp.getScore(), composition.getName(), (int) paperTime);
|
||||
return rsp;
|
||||
}
|
||||
|
||||
private void publishUserExam() {
|
||||
// UserExam ue = new UserExam();
|
||||
// ue.setExamId();
|
||||
// ue.setUserId(user.getAccount());
|
||||
//TODO 需要将 UserExam 发送 {@link UserExamService.submit 方法}
|
||||
// this.applicationContext.publishEvent(new UserExamRecordEvent(userExam));
|
||||
private void publishUserExam(AccountVO user, float score, String examName, int paperTimeMin) {
|
||||
UserExam ue = new UserExam();
|
||||
ue.setUserId(user.getId());
|
||||
ue.setExamName(examName);
|
||||
ue.setScore(score);
|
||||
ue.setUsedTime(paperTimeMin * 60);
|
||||
//需要将 UserExam 发送 {@link UserExamService.submit 方法}
|
||||
this.applicationContext.publishEvent(new UserExamRecordEvent(ue));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -4,8 +4,20 @@ import club.joylink.rtss.constants.ProjectDeviceType;
|
|||
import club.joylink.rtss.vo.AccountVO;
|
||||
import club.joylink.rtss.vo.LoginUserInfoVO;
|
||||
import club.joylink.rtss.vo.client.PageVO;
|
||||
import club.joylink.rtss.vo.client.project.*;
|
||||
|
||||
import club.joylink.rtss.vo.client.project.IbpConfigVO;
|
||||
import club.joylink.rtss.vo.client.project.LswConfigVO;
|
||||
import club.joylink.rtss.vo.client.project.LwConfigVO;
|
||||
import club.joylink.rtss.vo.client.project.PlcGatewayConfigVO;
|
||||
import club.joylink.rtss.vo.client.project.ProjectDevicePageQueryVO;
|
||||
import club.joylink.rtss.vo.client.project.ProjectDeviceVO;
|
||||
import club.joylink.rtss.vo.client.project.PscConfigVO;
|
||||
import club.joylink.rtss.vo.client.project.PsdConfigVO;
|
||||
import club.joylink.rtss.vo.client.project.PslConfigVO;
|
||||
import club.joylink.rtss.vo.client.project.RelationLoginConfigVO;
|
||||
import club.joylink.rtss.vo.client.project.SignalConfigVO;
|
||||
import club.joylink.rtss.vo.client.project.SwitchConfigVO;
|
||||
import club.joylink.rtss.vo.client.project.VrIbpConfigVO;
|
||||
import club.joylink.rtss.vo.client.project.VrpsdConfigVO;
|
||||
import java.util.List;
|
||||
|
||||
public interface DeviceService {
|
||||
|
@ -216,4 +228,6 @@ public interface DeviceService {
|
|||
void addOrUpdateHhcjDeviceConfig(AccountVO accountVO);
|
||||
|
||||
void addOrUpdateSayDeviceConfig(AccountVO accountVO);
|
||||
|
||||
void addOrUpdateThailandDeviceConfig(AccountVO accountVO, Long mapId);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -433,22 +433,13 @@ public class AtsTrainService {
|
|||
throw new SimulationException(SimulationExceptionType.System_Fault, "只能选列车或区段");
|
||||
}
|
||||
Section section = (Section) element;
|
||||
VirtualRealityTrain linkTrain = train.getLinkTrain();
|
||||
if (linkTrain != null) {
|
||||
Section linkTrainTargetSection = section.getNextRunningSectionOf(right);
|
||||
if (linkTrainTargetSection.isStandTrack()) {
|
||||
SectionPosition linkTrainTargetPosition = new SectionPosition(linkTrainTargetSection, linkTrainTargetSection.getStopPointByDirection(right));
|
||||
Float distance = CalculateService.calculateDistance(linkTrain.getHeadPosition(), linkTrainTargetPosition, right, false);
|
||||
if (distance == null) {
|
||||
throw new SimulationException(SimulationExceptionType.Illegal_Argument, "无法到达的位置");
|
||||
}
|
||||
tempTargetPosition = CalculateService.calculateNextPositionByStartAndLen(headPosition, right, distance, false);
|
||||
} else {
|
||||
tempTargetPosition = new SectionPosition(section, section.getStopPointByDirection(right));
|
||||
}
|
||||
} else {
|
||||
tempTargetPosition = new SectionPosition(section, section.getStopPointByDirection(right));
|
||||
Section targetSection = section.getNextRunningSectionOf(right);
|
||||
SectionPosition trainTargetPosition = new SectionPosition(targetSection, targetSection.getStopPointByDirection(right));
|
||||
Float distance = CalculateService.calculateDistance(train.getHeadPosition(), trainTargetPosition, right, false);
|
||||
if (distance == null) {
|
||||
throw new SimulationException(SimulationExceptionType.Illegal_Argument, "无法到达的位置");
|
||||
}
|
||||
tempTargetPosition = new SectionPosition(section, section.getStopPointByDirection(right));
|
||||
} else {
|
||||
VirtualRealityTrain targetTrain = repository.getVRByCode(targetDeviceCode, VirtualRealityTrain.class);
|
||||
SectionPosition targetTrainTailPosition = targetTrain.calculateTailPosition();
|
||||
|
@ -503,8 +494,23 @@ public class AtsTrainService {
|
|||
param.setThroughSignal(null);
|
||||
param.setThroughSignalAspect(null);
|
||||
}
|
||||
VirtualRealityTrain linkTrain = train.getLinkTrain();
|
||||
if (linkTrain != null) {
|
||||
DriveParamVO linkParamVO = param.cloneParamVO();
|
||||
if (targetPosition != null) {
|
||||
Section targetSection = targetPosition.getSection();
|
||||
float offset = targetSection.getStopPointByDirection(train.isRight());
|
||||
SectionPosition linkTargetSectionPosition = new SectionPosition(targetSection, offset);
|
||||
linkParamVO.setTargetPosition(linkTargetSectionPosition);
|
||||
Float distance = CalculateService.calculateDistance(headPosition, linkTrain.calculateTailPosition(), right, false);
|
||||
float len = linkTrain.getLen() + (distance == null ? 0 : distance);
|
||||
targetPosition = new SectionPosition(targetSection, offset + (len * (right ? -1 : 1)));
|
||||
}
|
||||
linkTrain.setRobotDriveParam(linkParamVO);
|
||||
}
|
||||
param.setTargetPosition(targetPosition);
|
||||
train.setRobotDriveParam(param);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package club.joylink.rtss.simulation.cbtc.CI.device;
|
||||
|
||||
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
|
||||
import club.joylink.rtss.simulation.cbtc.Simulation;
|
||||
import club.joylink.rtss.simulation.cbtc.constant.SignalAspect;
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.Signal;
|
||||
|
@ -62,9 +61,9 @@ public class CiSignalControlService {
|
|||
} else {
|
||||
this.virtualRealityDeviceService.control(simulation, vrSignal, SignalAspect.No);
|
||||
}
|
||||
} else { // 后背模式,开放室外信号
|
||||
} else { // 后备模式,开放室外信号
|
||||
if(signal.getSignalModel().getDefaultAspect().equals(aspect) ||
|
||||
(signal.getSignalModel().getGuideAspect().equals(aspect) && signal.isHigherThanGuideLevel()) ||
|
||||
(aspect.equals(signal.getSignalModel().getGuideAspect()) && signal.isHigherThanGuideLevel()) ||
|
||||
(signal.isAtpLevel() || signal.isMainLevel())) {
|
||||
this.virtualRealityDeviceService.control(simulation, vrSignal, aspect);
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Component
|
||||
public class CiSwitchControlService {
|
||||
|
@ -97,21 +98,27 @@ public class CiSwitchControlService {
|
|||
*/
|
||||
public boolean turn(Simulation simulation, Switch aSwitch) {
|
||||
VirtualRealitySwitch vrSwitch = aSwitch.getVirtualSwitch();
|
||||
boolean isRP;
|
||||
if (vrSwitch.getCommand() != null) {
|
||||
switch (vrSwitch.getCommand()) {
|
||||
case NP:
|
||||
return this.turn2ReversePosition(simulation, aSwitch);
|
||||
case RP:
|
||||
return this.turn2NormalPosition(simulation, aSwitch);
|
||||
}
|
||||
isRP = vrSwitch.getCommand().equals(VirtualRealitySwitch.Operation.RP);
|
||||
} else {
|
||||
if (vrSwitch.isPosN()) {
|
||||
return this.turn2ReversePosition(simulation, aSwitch);
|
||||
} else if (vrSwitch.isPosR()) {
|
||||
return this.turn2NormalPosition(simulation, aSwitch);
|
||||
isRP = vrSwitch.isPosR();
|
||||
}
|
||||
if (simulation.getRepository().getConfig().isSwitchNRTurnChain()) {
|
||||
Switch linkedSwitch = aSwitch.queryLinkedSwitch();
|
||||
if (Objects.nonNull(linkedSwitch)) {
|
||||
if (isRP) {
|
||||
this.turn2NormalPosition(simulation, linkedSwitch);
|
||||
} else {
|
||||
this.turn2ReversePosition(simulation, linkedSwitch);
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.turn2NormalPosition(simulation, aSwitch);
|
||||
if (isRP) {
|
||||
return this.turn2NormalPosition(simulation, aSwitch);
|
||||
} else {
|
||||
return this.turn2ReversePosition(simulation, aSwitch);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,8 +1,17 @@
|
|||
package club.joylink.rtss.simulation.cbtc.CTC;
|
||||
|
||||
import club.joylink.rtss.constants.ProjectCode;
|
||||
import club.joylink.rtss.simulation.cbtc.ATS.service.AtsTrainLoadService;
|
||||
import club.joylink.rtss.simulation.cbtc.CTC.data.*;
|
||||
import club.joylink.rtss.simulation.cbtc.CTC.data.vo.*;
|
||||
import club.joylink.rtss.simulation.cbtc.CTC.data.CtcEffectRepository;
|
||||
import club.joylink.rtss.simulation.cbtc.CTC.data.CtcRepository;
|
||||
import club.joylink.rtss.simulation.cbtc.CTC.data.CtcStationRunPlanLog;
|
||||
import club.joylink.rtss.simulation.cbtc.CTC.data.RouteSequence;
|
||||
import club.joylink.rtss.simulation.cbtc.CTC.data.TrackView;
|
||||
import club.joylink.rtss.simulation.cbtc.CTC.data.vo.BusyBoardVO;
|
||||
import club.joylink.rtss.simulation.cbtc.CTC.data.vo.CtcStationRunPlanLogVO;
|
||||
import club.joylink.rtss.simulation.cbtc.CTC.data.vo.RailDispatchCommandVO;
|
||||
import club.joylink.rtss.simulation.cbtc.CTC.data.vo.RouteSequenceVO;
|
||||
import club.joylink.rtss.simulation.cbtc.CTC.data.vo.TrackViewVO;
|
||||
import club.joylink.rtss.simulation.cbtc.CTC.rail.dcmd.service.DisCmdSendService;
|
||||
import club.joylink.rtss.simulation.cbtc.CTC.service.CTCService;
|
||||
import club.joylink.rtss.simulation.cbtc.CTC.service.CtcDispatchCommandService;
|
||||
|
@ -21,426 +30,464 @@ import club.joylink.rtss.vo.client.WebSocketMessageType;
|
|||
import club.joylink.rtss.vo.client.factory.SocketMessageFactory;
|
||||
import club.joylink.rtss.websocket.StompMessageService;
|
||||
import club.joylink.rtss.websocket.WebSocketMessage;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class CTCLogicLoop {
|
||||
public static final String LOGIC_NAME = "CTC"; //逻辑循环任务名称
|
||||
public static final int LOGIC_RATE = 1000; //逻辑循环频率
|
||||
public static final String MESSAGE_NAME = "CTC_MESSAGE"; //消息发送任务名称
|
||||
public static final int MESSAGE_RATE = 1000; //消息发送频率
|
||||
|
||||
@Autowired
|
||||
private StompMessageService stompMessageService;
|
||||
@Autowired
|
||||
private CTCService ctcService;
|
||||
@Autowired
|
||||
private CtcDispatchCommandService ctcDispatchCommandService;
|
||||
@Autowired
|
||||
private DisCmdSendService disCmdService;
|
||||
@Autowired
|
||||
private AtsTrainLoadService atsTrainLoadService;
|
||||
public static final String LOGIC_NAME = "CTC"; //逻辑循环任务名称
|
||||
public static final int LOGIC_RATE = 1000; //逻辑循环频率
|
||||
public static final String MESSAGE_NAME = "CTC_MESSAGE"; //消息发送任务名称
|
||||
public static final int MESSAGE_RATE = 1000; //消息发送频率
|
||||
|
||||
public void run(Simulation simulation) {
|
||||
updateRunPlanLog(simulation);
|
||||
routeSequenceUpdate(simulation);
|
||||
trackViewUpdate(simulation);
|
||||
// 加载已签收行车日志,
|
||||
loadSignRunPlanTrain(simulation);
|
||||
@Autowired
|
||||
private StompMessageService stompMessageService;
|
||||
@Autowired
|
||||
private CTCService ctcService;
|
||||
@Autowired
|
||||
private CtcDispatchCommandService ctcDispatchCommandService;
|
||||
@Autowired
|
||||
private DisCmdSendService disCmdService;
|
||||
@Autowired
|
||||
private AtsTrainLoadService atsTrainLoadService;
|
||||
|
||||
public void run(Simulation simulation) {
|
||||
updateRunPlanLog(simulation);
|
||||
routeSequenceUpdate(simulation);
|
||||
trackViewUpdate(simulation);
|
||||
// 加载已签收行车日志,
|
||||
loadSignRunPlanTrain(simulation);
|
||||
}
|
||||
|
||||
public void sendMessage(Simulation simulation) {
|
||||
sendTrackViewMessage(simulation);
|
||||
sendRouteSequenceMessage(simulation);
|
||||
// 发送运行计划变化消息
|
||||
sendRunPlanChangeMessage(simulation);
|
||||
sendRunPlanRemoveMessage(simulation);
|
||||
// 下发计划
|
||||
sendZoneRunPlanSend(simulation);
|
||||
// 发送计划按钮是否闪烁
|
||||
sendRunPlanConfirmActiveMessage(simulation);
|
||||
}
|
||||
|
||||
public void sendMessageWhenSubscribeCtc(Simulation simulation, String userId) {
|
||||
sendAllBusyBoardMessage(simulation, userId);
|
||||
//dis cmd v1
|
||||
sendUnreadDispatchCommand(simulation, userId);
|
||||
//dis cmd v2
|
||||
disCmdService.autoSendUnread(simulation, userId);
|
||||
}
|
||||
|
||||
private void sendAllBusyBoardMessage(Simulation simulation, String userId) {
|
||||
CtcRepository ctcRepository = simulation.getCtcRepository();
|
||||
List<BusyBoardVO> list = new ArrayList<>();
|
||||
Map<String, TrackViewVO> trackViewVOMap = ctcRepository.getTrackViewVOMap();
|
||||
Map<String, RouteSequenceVO> routeSequenceVOMap = ctcRepository.getRouteSequenceVOMap();
|
||||
HashSet<String> stationCodes = new HashSet<>(trackViewVOMap.keySet());
|
||||
stationCodes.addAll(routeSequenceVOMap.keySet());
|
||||
for (String stationCode : stationCodes) {
|
||||
TrackViewVO trackViewVO = trackViewVOMap.get(stationCode);
|
||||
RouteSequenceVO routeSequenceVO = routeSequenceVOMap.get(stationCode);
|
||||
BusyBoardVO busyBoardVO = new BusyBoardVO(stationCode, routeSequenceVO, trackViewVO);
|
||||
list.add(busyBoardVO);
|
||||
}
|
||||
|
||||
public void sendMessage(Simulation simulation) {
|
||||
sendTrackViewMessage(simulation);
|
||||
sendRouteSequenceMessage(simulation);
|
||||
// 发送运行计划变化消息
|
||||
sendRunPlanChangeMessage(simulation);
|
||||
sendRunPlanRemoveMessage(simulation);
|
||||
// 下发计划
|
||||
sendZoneRunPlanSend(simulation);
|
||||
// 发送计划按钮是否闪烁
|
||||
sendRunPlanConfirmActiveMessage(simulation);
|
||||
}
|
||||
SocketMessageVO<List<BusyBoardVO>> message
|
||||
= SocketMessageFactory.buildCtcBusyBoardMessage(simulation.getId(), list);
|
||||
stompMessageService.sendToUser(userId, message);
|
||||
}
|
||||
|
||||
public void sendMessageWhenSubscribeCtc(Simulation simulation, String userId) {
|
||||
sendAllBusyBoardMessage(simulation, userId);
|
||||
//dis cmd v1
|
||||
sendUnreadDispatchCommand(simulation, userId);
|
||||
//dis cmd v2
|
||||
disCmdService.autoSendUnread(simulation,userId);
|
||||
}
|
||||
|
||||
private void sendAllBusyBoardMessage(Simulation simulation, String userId) {
|
||||
CtcRepository ctcRepository = simulation.getCtcRepository();
|
||||
List<BusyBoardVO> list = new ArrayList<>();
|
||||
Map<String, TrackViewVO> trackViewVOMap = ctcRepository.getTrackViewVOMap();
|
||||
Map<String, RouteSequenceVO> routeSequenceVOMap = ctcRepository.getRouteSequenceVOMap();
|
||||
HashSet<String> stationCodes = new HashSet<>(trackViewVOMap.keySet());
|
||||
stationCodes.addAll(routeSequenceVOMap.keySet());
|
||||
for (String stationCode : stationCodes) {
|
||||
TrackViewVO trackViewVO = trackViewVOMap.get(stationCode);
|
||||
RouteSequenceVO routeSequenceVO = routeSequenceVOMap.get(stationCode);
|
||||
BusyBoardVO busyBoardVO = new BusyBoardVO(stationCode, routeSequenceVO, trackViewVO);
|
||||
list.add(busyBoardVO);
|
||||
}
|
||||
|
||||
SocketMessageVO<List<BusyBoardVO>> message
|
||||
= SocketMessageFactory.buildCtcBusyBoardMessage(simulation.getId(), list);
|
||||
/**
|
||||
* 发送该成员所属受令方的未读的调度命令
|
||||
*/
|
||||
private void sendUnreadDispatchCommand(Simulation simulation, String userId) {
|
||||
SimulationMember member = simulation.querySimulationMemberByUserId(userId);
|
||||
if (member != null) {
|
||||
List<RailDispatchCommandVO> unreadCommands = ctcDispatchCommandService.queryUnreadDispatchCommand(
|
||||
simulation, member);
|
||||
for (RailDispatchCommandVO unreadCommand : unreadCommands) {
|
||||
WebSocketMessage<RailDispatchCommandVO.WsMsgType, RailDispatchCommandVO> messageBody
|
||||
= new WebSocketMessage<>(RailDispatchCommandVO.WsMsgType.ADD, unreadCommand);
|
||||
SocketMessageVO<WebSocketMessage<RailDispatchCommandVO.WsMsgType, RailDispatchCommandVO>> message
|
||||
= SocketMessageFactory.buildDispatchCommandMessage(simulation.getId(), messageBody);
|
||||
stompMessageService.sendToUser(userId, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送该成员所属受令方的未读的调度命令
|
||||
*/
|
||||
private void sendUnreadDispatchCommand(Simulation simulation, String userId) {
|
||||
SimulationMember member = simulation.querySimulationMemberByUserId(userId);
|
||||
if (member != null) {
|
||||
List<RailDispatchCommandVO> unreadCommands = ctcDispatchCommandService.queryUnreadDispatchCommand(simulation, member);
|
||||
for (RailDispatchCommandVO unreadCommand : unreadCommands) {
|
||||
WebSocketMessage<RailDispatchCommandVO.WsMsgType, RailDispatchCommandVO> messageBody
|
||||
= new WebSocketMessage<>(RailDispatchCommandVO.WsMsgType.ADD, unreadCommand);
|
||||
SocketMessageVO<WebSocketMessage<RailDispatchCommandVO.WsMsgType, RailDispatchCommandVO>> message
|
||||
= SocketMessageFactory.buildDispatchCommandMessage(simulation.getId(), messageBody);
|
||||
stompMessageService.sendToUser(userId, message);
|
||||
private void trackViewUpdate(Simulation simulation) {
|
||||
CtcRepository ctcRepository = simulation.getCtcRepository();
|
||||
for (TrackView trackView : ctcRepository.getTrackViewMap().values()) {
|
||||
for (Map<String, TrackView.Line> lineMap : trackView.getTrackLineMap().values()) {
|
||||
Iterator<TrackView.Line> lineIterator = lineMap.values().iterator();
|
||||
while (lineIterator.hasNext()) {
|
||||
TrackView.Line line = lineIterator.next();
|
||||
int remain = line.getRemain2Delete();
|
||||
if (remain == -1) {
|
||||
TrackView.Process process = line.getProcess();
|
||||
if (TrackView.Process.FINISH.equals(process)) {
|
||||
line.startDelayDelete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void trackViewUpdate(Simulation simulation) {
|
||||
CtcRepository ctcRepository = simulation.getCtcRepository();
|
||||
for (TrackView trackView : ctcRepository.getTrackViewMap().values()) {
|
||||
for (Map<String, TrackView.Line> lineMap : trackView.getTrackLineMap().values()) {
|
||||
Iterator<TrackView.Line> lineIterator = lineMap.values().iterator();
|
||||
while (lineIterator.hasNext()) {
|
||||
TrackView.Line line = lineIterator.next();
|
||||
int remain = line.getRemain2Delete();
|
||||
if (remain == -1) {
|
||||
TrackView.Process process = line.getProcess();
|
||||
if (TrackView.Process.FINISH.equals(process)) {
|
||||
line.startDelayDelete();
|
||||
}
|
||||
} else {
|
||||
remain -= LOGIC_RATE;
|
||||
if (remain <= 0) {
|
||||
lineIterator.remove();
|
||||
} else {
|
||||
line.setRemain2Delete(remain);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 进路序列更新与自触
|
||||
*/
|
||||
private void routeSequenceUpdate(Simulation simulation) {
|
||||
LocalDateTime correctSystemTime = simulation.getCorrectSystemTime();
|
||||
SimulationDataRepository repository = simulation.getRepository();
|
||||
for (Map.Entry<String, RouteSequence> entry : simulation.getCtcRepository().getRouteSequenceMap().entrySet()) {
|
||||
String stationCode = entry.getKey();
|
||||
Station station = repository.getByCode(stationCode, Station.class);
|
||||
RouteSequence routeSequence = entry.getValue();
|
||||
for (RouteSequence.Line line : routeSequence.getLines()) {
|
||||
//更新触发/正在触发状态
|
||||
if (line.isTriggered())
|
||||
continue;
|
||||
Route route = line.getRoute();
|
||||
if (route == null)
|
||||
continue;
|
||||
if (Objects.equals(line.getTripNumber(), route.getTripNumber())) {
|
||||
if (route.isLock()) {
|
||||
line.setTriggered(true);
|
||||
continue;
|
||||
} else {
|
||||
line.setSetting(route.isSetting());
|
||||
if (line.isSetting())
|
||||
continue;
|
||||
}
|
||||
}
|
||||
//自动触发
|
||||
if (station.isInterlockControl() || !line.isAutoTrigger()) //非常站控或者没有设置自触
|
||||
continue;
|
||||
TrainInfo trainInfo = repository.findSupervisedTrainByTrip("", line.getTripNumber());
|
||||
if (line.isDeparture()) { //发车进路需列车停稳并到达计划时间
|
||||
if (correctSystemTime.isBefore(line.getPlanDateTime()))
|
||||
continue;
|
||||
if (trainInfo != null && trainInfo.isStop() && Objects.equals(trainInfo.getPhysicalSection(), line.getTrackCode()))
|
||||
ctcService.setRoute(simulation, line.getRouteCode(), line.getTripNumber(), false, null);
|
||||
} else {
|
||||
if (!correctSystemTime.isBefore(line.getPlanDateTime()))
|
||||
ctcService.setRoute(simulation, line.getRouteCode(), line.getTripNumber(), false, null);
|
||||
else if (trainInfo != null && line.isTriggerSection(trainInfo.getPhysicalSection()))
|
||||
ctcService.setRoute(simulation, line.getRouteCode(), line.getTripNumber(), false, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新行车日志状态
|
||||
*/
|
||||
private void updateRunPlanLog(Simulation simulation) {
|
||||
SimulationDataRepository repository = simulation.getRepository();
|
||||
String actualTime = simulation.getCorrectSystemTime().toLocalTime().toString();
|
||||
int index = actualTime.indexOf(".");
|
||||
if (index != -1) {
|
||||
actualTime = actualTime.substring(0, index);
|
||||
}
|
||||
CtcRepository ctcRepository = simulation.getCtcRepository();
|
||||
for (TrainInfo trainInfo : repository.getSuperviseTrainList()) {
|
||||
VirtualRealityTrain train = repository.getOnlineTrainBy(trainInfo.getGroupNumber());
|
||||
SectionPosition headPosition = train.getHeadPosition();
|
||||
Section headSection = headPosition.getSection();
|
||||
Station station = headSection.getDeviceStation();
|
||||
String tripNumber = trainInfo.getTripNumber();
|
||||
CtcStationRunPlanLog runPlan = ctcRepository.findRunPlan(station.getCode(), tripNumber);
|
||||
if (runPlan == null)
|
||||
continue;
|
||||
// 接车计划到点:列车占压区段与接车计划股道一致,且列车是停站状态
|
||||
CtcStationRunPlanLog.RunPlanItem arriveRunPlan = runPlan.getArriveRunPlan();
|
||||
if (arriveRunPlan != null) {
|
||||
if (!arriveRunPlan.isFinish()) {
|
||||
if (headSection.equals(arriveRunPlan.getTrackSection()) && train.isParkingAt()) {
|
||||
arriveRunPlan.setActualTime(actualTime);
|
||||
arriveRunPlan.setFinish(true);
|
||||
//设置上一站的<邻站到达>
|
||||
Station previousStation = runPlan.findPreviousStation();
|
||||
if (previousStation != null) {
|
||||
CtcStationRunPlanLog previousRunPlan = ctcRepository.findRunPlan(previousStation.getCode(), tripNumber);
|
||||
if (previousRunPlan != null) {
|
||||
CtcStationRunPlanLog.RunPlanItem previousDeparturePlan = previousRunPlan.getDepartRunPlan();
|
||||
if (previousDeparturePlan != null) {
|
||||
previousDeparturePlan.setAdjacentDepart(actualTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 发车计划发点:列车位置越过出站信号机
|
||||
CtcStationRunPlanLog.RunPlanItem departRunPlan = runPlan.getDepartRunPlan();
|
||||
if (departRunPlan != null) {
|
||||
if (!departRunPlan.isFinish()) { //实际发车时间没填
|
||||
Section trackSection = departRunPlan.getTrackSection();
|
||||
Signal signal = trackSection.getSignalOf(departRunPlan.isRight());
|
||||
if (headPosition.isAheadOf(signal.getPosition(), departRunPlan.isRight())) { //车头越过出站信号机
|
||||
departRunPlan.setActualTime(actualTime);
|
||||
departRunPlan.setFinish(true);
|
||||
//设置下一站的<邻站出发>
|
||||
Station nextStation = runPlan.findNextStation();
|
||||
if (nextStation != null) {
|
||||
CtcStationRunPlanLog nextRunPlan = ctcRepository.findRunPlan(nextStation.getCode(), tripNumber);
|
||||
if (nextRunPlan != null) {
|
||||
CtcStationRunPlanLog.RunPlanItem nextArriveRunPlan = nextRunPlan.getArriveRunPlan();
|
||||
if (nextArriveRunPlan != null) {
|
||||
nextArriveRunPlan.setAdjacentDepart(actualTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sendTrackViewMessage(Simulation simulation) {
|
||||
List<BusyBoardVO> list = new ArrayList<>();
|
||||
CtcRepository ctcRepository = simulation.getCtcRepository();
|
||||
Map<String, TrackView> trackViewMap = ctcRepository.getTrackViewMap();
|
||||
Map<String, TrackViewVO> trackViewVOMap = ctcRepository.getTrackViewVOMap();
|
||||
for (Map.Entry<String, TrackView> trackViewEntry : trackViewMap.entrySet()) {
|
||||
String stationCode = trackViewEntry.getKey();
|
||||
TrackView trackView = trackViewEntry.getValue();
|
||||
TrackViewVO trackViewVO = trackViewVOMap.get(stationCode);
|
||||
TrackViewVO changedViewVO;
|
||||
if (trackViewVO == null) {
|
||||
trackViewVO = new TrackViewVO(trackView);
|
||||
trackViewVOMap.put(stationCode, trackViewVO);
|
||||
changedViewVO = trackViewVO;
|
||||
} else {
|
||||
remain -= LOGIC_RATE;
|
||||
if (remain <= 0) {
|
||||
lineIterator.remove();
|
||||
} else {
|
||||
changedViewVO = trackViewVO.updateAndReturnChanged(trackView);
|
||||
}
|
||||
if (changedViewVO != null) {
|
||||
BusyBoardVO busyBoardVO = new BusyBoardVO(stationCode, null, changedViewVO);
|
||||
list.add(busyBoardVO);
|
||||
line.setRemain2Delete(remain);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(list)) {
|
||||
SocketMessageVO<List<BusyBoardVO>> message
|
||||
= SocketMessageFactory.buildCtcBusyBoardMessage(simulation.getId(), list);
|
||||
stompMessageService.sendToUser(simulation.getSimulationUserIds(), message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送进路序列消息
|
||||
*/
|
||||
private void sendRouteSequenceMessage(Simulation simulation) {
|
||||
CtcRepository ctcRepository = simulation.getCtcRepository();
|
||||
Map<String, RouteSequence> routeSequenceMap = ctcRepository.getRouteSequenceMap();
|
||||
Map<String, RouteSequenceVO> routeSequenceVOMap = ctcRepository.getRouteSequenceVOMap();
|
||||
List<BusyBoardVO> list = new ArrayList<>();
|
||||
if (CollectionUtils.isEmpty(routeSequenceVOMap)) {
|
||||
for (RouteSequence routeSequence : routeSequenceMap.values()) {
|
||||
RouteSequenceVO routeSequenceVO = new RouteSequenceVO(routeSequence);
|
||||
routeSequenceVOMap.put(routeSequenceVO.getStationCode(), routeSequenceVO);
|
||||
BusyBoardVO busyBoardVO = new BusyBoardVO(routeSequenceVO.getStationCode(), routeSequenceVO, null);
|
||||
list.add(busyBoardVO);
|
||||
/**
|
||||
* 进路序列更新与自触
|
||||
*/
|
||||
private void routeSequenceUpdate(Simulation simulation) {
|
||||
LocalDateTime correctSystemTime = simulation.getCorrectSystemTime();
|
||||
SimulationDataRepository repository = simulation.getRepository();
|
||||
for (Map.Entry<String, RouteSequence> entry : simulation.getCtcRepository()
|
||||
.getRouteSequenceMap().entrySet()) {
|
||||
String stationCode = entry.getKey();
|
||||
Station station = repository.getByCode(stationCode, Station.class);
|
||||
RouteSequence routeSequence = entry.getValue();
|
||||
for (RouteSequence.Line line : routeSequence.getLines()) {
|
||||
//更新触发/正在触发状态
|
||||
if (line.isTriggered()) {
|
||||
continue;
|
||||
}
|
||||
Route route = line.getRoute();
|
||||
if (route == null) {
|
||||
continue;
|
||||
}
|
||||
if (Objects.equals(line.getTripNumber(), route.getTripNumber())) {
|
||||
if (route.isLock()) {
|
||||
line.setTriggered(true);
|
||||
continue;
|
||||
} else {
|
||||
line.setSetting(route.isSetting());
|
||||
if (line.isSetting()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
//自动触发
|
||||
if (station.isInterlockControl() || !line.isAutoTrigger()) //非常站控或者没有设置自触
|
||||
{
|
||||
continue;
|
||||
}
|
||||
TrainInfo trainInfo = repository.findSupervisedTrainByTrip("", line.getTripNumber());
|
||||
if (line.isDeparture()) { //发车进路需列车停稳并到达计划时间
|
||||
if (correctSystemTime.isBefore(line.getPlanDateTime())) {
|
||||
continue;
|
||||
}
|
||||
if (trainInfo != null && trainInfo.isStop() && Objects.equals(
|
||||
trainInfo.getPhysicalSection(), line.getTrackCode())) {
|
||||
ctcService.setRoute(simulation, line.getRouteCode(), line.getTripNumber(), false, null);
|
||||
}
|
||||
} else {
|
||||
for (RouteSequence routeSequence : routeSequenceMap.values()) {
|
||||
RouteSequenceVO vo = routeSequenceVOMap.get(routeSequence.getStationCode());
|
||||
RouteSequenceVO changed = vo.updateAndReturnChanged(routeSequence);
|
||||
if (changed != null) {
|
||||
BusyBoardVO busyBoardVO = new BusyBoardVO(vo.getStationCode(), changed, null);
|
||||
list.add(busyBoardVO);
|
||||
if (!correctSystemTime.isBefore(line.getPlanDateTime())) {
|
||||
ctcService.setRoute(simulation, line.getRouteCode(), line.getTripNumber(), false, null);
|
||||
} else if (trainInfo != null && line.isTriggerSection(trainInfo.getPhysicalSection())) {
|
||||
ctcService.setRoute(simulation, line.getRouteCode(), line.getTripNumber(), false, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新行车日志状态
|
||||
*/
|
||||
private void updateRunPlanLog(Simulation simulation) {
|
||||
SimulationDataRepository repository = simulation.getRepository();
|
||||
String actualTime = simulation.getCorrectSystemTime().toLocalTime().toString();
|
||||
int index = actualTime.indexOf(".");
|
||||
if (index != -1) {
|
||||
actualTime = actualTime.substring(0, index);
|
||||
}
|
||||
CtcRepository ctcRepository = simulation.getCtcRepository();
|
||||
for (TrainInfo trainInfo : repository.getSuperviseTrainList()) {
|
||||
VirtualRealityTrain train = repository.getOnlineTrainBy(trainInfo.getGroupNumber());
|
||||
SectionPosition headPosition = train.getHeadPosition();
|
||||
Section headSection = headPosition.getSection();
|
||||
Station station = headSection.getDeviceStation();
|
||||
String tripNumber = trainInfo.getTripNumber();
|
||||
CtcStationRunPlanLog runPlan = ctcRepository.findRunPlan(station.getCode(), tripNumber);
|
||||
if (runPlan == null) {
|
||||
continue;
|
||||
}
|
||||
// 接车计划到点:列车占压区段与接车计划股道一致,且列车是停站状态
|
||||
CtcStationRunPlanLog.RunPlanItem arriveRunPlan = runPlan.getArriveRunPlan();
|
||||
if (arriveRunPlan != null) {
|
||||
if (!arriveRunPlan.isFinish()) {
|
||||
if (headSection.equals(arriveRunPlan.getTrackSection()) && train.isParkingAt()) {
|
||||
arriveRunPlan.setActualTime(actualTime);
|
||||
arriveRunPlan.setFinish(true);
|
||||
//设置上一站的<邻站到达>
|
||||
Station previousStation = runPlan.findPreviousStation();
|
||||
if (previousStation != null) {
|
||||
CtcStationRunPlanLog previousRunPlan = ctcRepository.findRunPlan(
|
||||
previousStation.getCode(), tripNumber);
|
||||
if (previousRunPlan != null) {
|
||||
CtcStationRunPlanLog.RunPlanItem previousDeparturePlan = previousRunPlan.getDepartRunPlan();
|
||||
if (previousDeparturePlan != null) {
|
||||
previousDeparturePlan.setAdjacentDepart(actualTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(list)) {
|
||||
SocketMessageVO<List<BusyBoardVO>> message
|
||||
= SocketMessageFactory.buildCtcBusyBoardMessage(simulation.getId(), list);
|
||||
stompMessageService.sendToUser(simulation.getSimulationUserIds(), message);
|
||||
}
|
||||
}
|
||||
|
||||
public void addJobs(Simulation simulation) {
|
||||
simulation.addJob(LOGIC_NAME, () -> this.run(simulation), LOGIC_RATE);
|
||||
simulation.addFixedRateJob(MESSAGE_NAME, () -> this.sendMessage(simulation), MESSAGE_RATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 行车区段运行计划下发
|
||||
*/
|
||||
public void sendZoneRunPlanSend(Simulation simulation) {
|
||||
List<CtcEffectRepository.CtcStageRunPlanRepository.CtcStageRunPlanVO> allList = simulation.getCtcRepository().getCtcEffectRepository().getChangeStageRunPlan();
|
||||
if (!CollectionUtils.isEmpty(allList)) {
|
||||
sendCtcMessage(simulation.getId(), allList, WebSocketMessageType.SIMULATION_RAILWAY_RUN_PLAN_SEND, simulation.getSimulationUserIds());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 运行计划发送变化事件
|
||||
*/
|
||||
private void sendRunPlanChangeMessage(Simulation simulation) {
|
||||
Map<String, CtcStationRunPlanLogVO> ctcRunPlanVOMap = simulation.getCtcRepository().getRunPlanStatusVOMap();
|
||||
List<CtcStationRunPlanLog> allRunPlanList = simulation.getCtcRepository().getAllRunPlanList();
|
||||
List<CtcStationRunPlanLogVO> messageList = new ArrayList<>();
|
||||
allRunPlanList.forEach(runPlan -> {
|
||||
String mapKey = runPlan.getStation().getCode() + "_" + runPlan.getCode();
|
||||
CtcStationRunPlanLogVO runPlanVO = ctcRunPlanVOMap.get(mapKey);
|
||||
if (runPlanVO == null) {
|
||||
ctcRunPlanVOMap.put(mapKey, new CtcStationRunPlanLogVO(runPlan));
|
||||
messageList.add(ctcRunPlanVOMap.get(mapKey));
|
||||
} else {
|
||||
CtcStationRunPlanLogVO changeCtcStationRunPlanLogVo = runPlanVO.compareAndChange(runPlan);
|
||||
if (changeCtcStationRunPlanLogVo != null) {
|
||||
messageList.add(changeCtcStationRunPlanLogVo);
|
||||
}
|
||||
// 发车计划发点:列车位置越过出站信号机
|
||||
CtcStationRunPlanLog.RunPlanItem departRunPlan = runPlan.getDepartRunPlan();
|
||||
if (departRunPlan != null) {
|
||||
if (!departRunPlan.isFinish()) { //实际发车时间没填
|
||||
Section trackSection = departRunPlan.getTrackSection();
|
||||
Signal signal = trackSection.getSignalOf(departRunPlan.isRight());
|
||||
if (headPosition.isAheadOf(signal.getPosition(), departRunPlan.isRight())) { //车头越过出站信号机
|
||||
departRunPlan.setActualTime(actualTime);
|
||||
departRunPlan.setFinish(true);
|
||||
//设置下一站的<邻站出发>
|
||||
Station nextStation = runPlan.findNextStation();
|
||||
if (nextStation != null) {
|
||||
CtcStationRunPlanLog nextRunPlan = ctcRepository.findRunPlan(nextStation.getCode(),
|
||||
tripNumber);
|
||||
if (nextRunPlan != null) {
|
||||
CtcStationRunPlanLog.RunPlanItem nextArriveRunPlan = nextRunPlan.getArriveRunPlan();
|
||||
if (nextArriveRunPlan != null) {
|
||||
nextArriveRunPlan.setAdjacentDepart(actualTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!CollectionUtils.isEmpty(messageList)) {
|
||||
sendCtcMessage(simulation.getId(), messageList
|
||||
, WebSocketMessageType.SIMULATION_CTC_RUN_PLAN_CHANGE, simulation.getSimulationUserIds());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 运行计划移除时清除垃圾数据
|
||||
*
|
||||
* @param simulation 仿真实体
|
||||
*/
|
||||
public void sendRunPlanRemoveMessage(Simulation simulation) {
|
||||
Map<String, CtcStationRunPlanLogVO> ctcRunPlanVOMap = simulation.getCtcRepository().getRunPlanStatusVOMap();
|
||||
List<CtcStationRunPlanLogVO> ctcStationRunPlanLogVOList = ctcRunPlanVOMap.values().stream()
|
||||
.filter(vo -> simulation.getCtcRepository().getRunPlanByRunPlanCodeAndStationCode(vo.getStationCode(), vo.getCode()) == null)
|
||||
.map(vo -> new CtcStationRunPlanLogVO(vo.getStationCode(), vo.getCode()))
|
||||
.collect(Collectors.toList());
|
||||
if (!CollectionUtils.isEmpty(ctcStationRunPlanLogVOList)) {
|
||||
// 移除已删除的数据
|
||||
ctcStationRunPlanLogVOList.forEach(vo -> ctcRunPlanVOMap.remove(vo.getStationCode() + "_" + vo.getCode()));
|
||||
sendCtcMessage(simulation.getId(), ctcStationRunPlanLogVOList
|
||||
, WebSocketMessageType.SIMULATION_CTC_RUN_PLAN_REMOVE, simulation.getSimulationUserIds());
|
||||
private void sendTrackViewMessage(Simulation simulation) {
|
||||
List<BusyBoardVO> list = new ArrayList<>();
|
||||
CtcRepository ctcRepository = simulation.getCtcRepository();
|
||||
Map<String, TrackView> trackViewMap = ctcRepository.getTrackViewMap();
|
||||
Map<String, TrackViewVO> trackViewVOMap = ctcRepository.getTrackViewVOMap();
|
||||
for (Map.Entry<String, TrackView> trackViewEntry : trackViewMap.entrySet()) {
|
||||
String stationCode = trackViewEntry.getKey();
|
||||
TrackView trackView = trackViewEntry.getValue();
|
||||
TrackViewVO trackViewVO = trackViewVOMap.get(stationCode);
|
||||
TrackViewVO changedViewVO;
|
||||
if (trackViewVO == null) {
|
||||
trackViewVO = new TrackViewVO(trackView);
|
||||
trackViewVOMap.put(stationCode, trackViewVO);
|
||||
changedViewVO = trackViewVO;
|
||||
} else {
|
||||
changedViewVO = trackViewVO.updateAndReturnChanged(trackView);
|
||||
}
|
||||
if (changedViewVO != null) {
|
||||
BusyBoardVO busyBoardVO = new BusyBoardVO(stationCode, null, changedViewVO);
|
||||
list.add(busyBoardVO);
|
||||
}
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(list)) {
|
||||
SocketMessageVO<List<BusyBoardVO>> message
|
||||
= SocketMessageFactory.buildCtcBusyBoardMessage(simulation.getId(), list);
|
||||
stompMessageService.sendToUser(simulation.getSimulationUserIds(), message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送进路序列消息
|
||||
*/
|
||||
private void sendRouteSequenceMessage(Simulation simulation) {
|
||||
CtcRepository ctcRepository = simulation.getCtcRepository();
|
||||
Map<String, RouteSequence> routeSequenceMap = ctcRepository.getRouteSequenceMap();
|
||||
Map<String, RouteSequenceVO> routeSequenceVOMap = ctcRepository.getRouteSequenceVOMap();
|
||||
List<BusyBoardVO> list = new ArrayList<>();
|
||||
if (CollectionUtils.isEmpty(routeSequenceVOMap)) {
|
||||
for (RouteSequence routeSequence : routeSequenceMap.values()) {
|
||||
RouteSequenceVO routeSequenceVO = new RouteSequenceVO(routeSequence);
|
||||
routeSequenceVOMap.put(routeSequenceVO.getStationCode(), routeSequenceVO);
|
||||
BusyBoardVO busyBoardVO = new BusyBoardVO(routeSequenceVO.getStationCode(), routeSequenceVO,
|
||||
null);
|
||||
list.add(busyBoardVO);
|
||||
}
|
||||
} else {
|
||||
for (RouteSequence routeSequence : routeSequenceMap.values()) {
|
||||
RouteSequenceVO vo = routeSequenceVOMap.get(routeSequence.getStationCode());
|
||||
RouteSequenceVO changed = vo.updateAndReturnChanged(routeSequence);
|
||||
if (changed != null) {
|
||||
BusyBoardVO busyBoardVO = new BusyBoardVO(vo.getStationCode(), changed, null);
|
||||
list.add(busyBoardVO);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(list)) {
|
||||
SocketMessageVO<List<BusyBoardVO>> message
|
||||
= SocketMessageFactory.buildCtcBusyBoardMessage(simulation.getId(), list);
|
||||
stompMessageService.sendToUser(simulation.getSimulationUserIds(), message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 运行计划发送计划
|
||||
*/
|
||||
public void sendRunPlanConfirmActiveMessage(Simulation simulation) {
|
||||
Map<String, Boolean> changeMap = new HashMap<>();
|
||||
simulation.getCtcRepository().getSimulationRunPlanMap().forEach((k, v) -> {
|
||||
boolean isChange = v.values().stream().anyMatch(CtcStationRunPlanLog::isChange);
|
||||
if (isChange) {
|
||||
changeMap.put(k, Boolean.TRUE);
|
||||
public void addJobs(Simulation simulation) {
|
||||
simulation.addJob(LOGIC_NAME, () -> this.run(simulation), LOGIC_RATE);
|
||||
simulation.addFixedRateJob(MESSAGE_NAME, () -> this.sendMessage(simulation), MESSAGE_RATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 行车区段运行计划下发
|
||||
*/
|
||||
public void sendZoneRunPlanSend(Simulation simulation) {
|
||||
List<CtcEffectRepository.CtcStageRunPlanRepository.CtcStageRunPlanVO> allList = simulation.getCtcRepository()
|
||||
.getCtcEffectRepository().getChangeStageRunPlan();
|
||||
if (!CollectionUtils.isEmpty(allList)) {
|
||||
sendCtcMessage(simulation.getId(), allList,
|
||||
WebSocketMessageType.SIMULATION_RAILWAY_RUN_PLAN_SEND, simulation.getSimulationUserIds());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 运行计划发送变化事件
|
||||
*/
|
||||
private void sendRunPlanChangeMessage(Simulation simulation) {
|
||||
Map<String, CtcStationRunPlanLogVO> ctcRunPlanVOMap = simulation.getCtcRepository()
|
||||
.getRunPlanStatusVOMap();
|
||||
List<CtcStationRunPlanLog> allRunPlanList = simulation.getCtcRepository().getAllRunPlanList();
|
||||
List<CtcStationRunPlanLogVO> messageList = new ArrayList<>();
|
||||
allRunPlanList.forEach(runPlan -> {
|
||||
String mapKey = runPlan.getStation().getCode() + "_" + runPlan.getCode();
|
||||
CtcStationRunPlanLogVO runPlanVO = ctcRunPlanVOMap.get(mapKey);
|
||||
if (runPlanVO == null) {
|
||||
ctcRunPlanVOMap.put(mapKey, new CtcStationRunPlanLogVO(runPlan));
|
||||
messageList.add(ctcRunPlanVOMap.get(mapKey));
|
||||
} else {
|
||||
CtcStationRunPlanLogVO changeCtcStationRunPlanLogVo = runPlanVO.compareAndChange(runPlan);
|
||||
if (changeCtcStationRunPlanLogVo != null) {
|
||||
messageList.add(changeCtcStationRunPlanLogVo);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!CollectionUtils.isEmpty(messageList)) {
|
||||
sendCtcMessage(simulation.getId(), messageList
|
||||
, WebSocketMessageType.SIMULATION_CTC_RUN_PLAN_CHANGE, simulation.getSimulationUserIds());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 运行计划移除时清除垃圾数据
|
||||
*
|
||||
* @param simulation 仿真实体
|
||||
*/
|
||||
public void sendRunPlanRemoveMessage(Simulation simulation) {
|
||||
Map<String, CtcStationRunPlanLogVO> ctcRunPlanVOMap = simulation.getCtcRepository()
|
||||
.getRunPlanStatusVOMap();
|
||||
List<CtcStationRunPlanLogVO> ctcStationRunPlanLogVOList = ctcRunPlanVOMap.values().stream()
|
||||
.filter(vo -> simulation.getCtcRepository()
|
||||
.getRunPlanByRunPlanCodeAndStationCode(vo.getStationCode(), vo.getCode()) == null)
|
||||
.map(vo -> new CtcStationRunPlanLogVO(vo.getStationCode(), vo.getCode()))
|
||||
.collect(Collectors.toList());
|
||||
if (!CollectionUtils.isEmpty(ctcStationRunPlanLogVOList)) {
|
||||
// 移除已删除的数据
|
||||
ctcStationRunPlanLogVOList.forEach(
|
||||
vo -> ctcRunPlanVOMap.remove(vo.getStationCode() + "_" + vo.getCode()));
|
||||
sendCtcMessage(simulation.getId(), ctcStationRunPlanLogVOList
|
||||
, WebSocketMessageType.SIMULATION_CTC_RUN_PLAN_REMOVE, simulation.getSimulationUserIds());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 运行计划发送计划
|
||||
*/
|
||||
public void sendRunPlanConfirmActiveMessage(Simulation simulation) {
|
||||
Map<String, Boolean> changeMap = new HashMap<>();
|
||||
simulation.getCtcRepository().getSimulationRunPlanMap().forEach((k, v) -> {
|
||||
boolean isChange = v.values().stream().anyMatch(CtcStationRunPlanLog::isChange);
|
||||
if (isChange) {
|
||||
changeMap.put(k, Boolean.TRUE);
|
||||
}
|
||||
});
|
||||
// 为空时
|
||||
if (!Objects.equals(simulation.getCtcRepository().getRunPlanSendOut(), changeMap.isEmpty())
|
||||
|| !changeMap.isEmpty()) {
|
||||
simulation.getCtcRepository().setRunPlanSendOut(changeMap.isEmpty());
|
||||
sendCtcMessage(simulation.getId(), changeMap,
|
||||
WebSocketMessageType.SIMULATION_CTC_RUN_PLAN_CONFIRM_SEND
|
||||
, simulation.getSimulationUserIds());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送CTC运行计划消息
|
||||
*
|
||||
* @param simulationId 仿真ID
|
||||
* @param messageInfo 运行计划列表
|
||||
* @param type 消息类型
|
||||
* @param userIds 用户ID
|
||||
*/
|
||||
public <T> void sendCtcMessage(String simulationId, T messageInfo, WebSocketMessageType type,
|
||||
Set<String> userIds) {
|
||||
if (messageInfo != null) {
|
||||
SocketMessageVO<T> messageVO = SocketMessageFactory.build(type, simulationId, messageInfo);
|
||||
stompMessageService.sendToUser(userIds, messageVO);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 加载已签收至占线板上的列车
|
||||
*
|
||||
* @param simulation 仿真信息
|
||||
*/
|
||||
private void loadSignRunPlanTrain(Simulation simulation) {
|
||||
if (!simulation.isPlanRunning() || ProjectCode.THAILAND_SANDBOX.equals(
|
||||
simulation.getProject())) { //泰国沙盘项目不能随意指定列车上线,所以禁用此逻辑,后续考虑用地图配置
|
||||
return;
|
||||
}
|
||||
// 没有加载过计划、始发计划、已发送至占线板、当前时间晚于计划时间提前5分钟
|
||||
simulation.getCtcRepository().getAllRunPlanList().stream()
|
||||
.filter(r -> r.getDepartRunPlan() != null && (r.isStartRunPlan() || (
|
||||
r.getArriveRunPlan() == null && r.getDepartRunPlan() != null)))
|
||||
.filter(r -> {
|
||||
boolean valid = !r.isLoad() && r.isSign() && r.getStatus() != -1
|
||||
&& simulation.getCorrectSystemTime()
|
||||
.isAfter(r.getDepartRunPlan().getPlanTime().minusMinutes(5));
|
||||
if (valid) {
|
||||
valid = !simulation.getRepository().getTrainInfoMap().values().stream()
|
||||
.anyMatch(trainInfo -> r.getDepartRunPlan().getTripNumber()
|
||||
.equals(trainInfo.getTripNumber()));
|
||||
if (!valid) { // 如果列车已经上线,则直接修改状态
|
||||
r.setLoad(true);
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
})
|
||||
.sorted((r1, r2) ->
|
||||
r1.getDepartRunPlan().getPlanTime().isBefore(r2.getDepartRunPlan().getPlanTime()) ? -1
|
||||
: 1)
|
||||
.forEach(r -> {
|
||||
Section section = r.getDepartRunPlan().getTrackSection();
|
||||
if (section.isFree()) {
|
||||
String tripNumber = r.getDepartRunPlan().getTripNumber();
|
||||
int lastNum = tripNumber.charAt(tripNumber.length() - 1) - 48;
|
||||
atsTrainLoadService.loadTripNumberTrain(simulation, tripNumber, section.getCode(),
|
||||
lastNum % 2 == 0);
|
||||
r.setLoad(true); // 已上线
|
||||
}
|
||||
});
|
||||
// 为空时
|
||||
if (!Objects.equals(simulation.getCtcRepository().getRunPlanSendOut(), changeMap.isEmpty()) || !changeMap.isEmpty()) {
|
||||
simulation.getCtcRepository().setRunPlanSendOut(changeMap.isEmpty());
|
||||
sendCtcMessage(simulation.getId(), changeMap, WebSocketMessageType.SIMULATION_CTC_RUN_PLAN_CONFIRM_SEND
|
||||
, simulation.getSimulationUserIds());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送CTC运行计划消息
|
||||
*
|
||||
* @param simulationId 仿真ID
|
||||
* @param messageInfo 运行计划列表
|
||||
* @param type 消息类型
|
||||
* @param userIds 用户ID
|
||||
*/
|
||||
public <T> void sendCtcMessage(String simulationId, T messageInfo, WebSocketMessageType type, Set<String> userIds) {
|
||||
if (messageInfo != null) {
|
||||
SocketMessageVO<T> messageVO = SocketMessageFactory.build(type, simulationId, messageInfo);
|
||||
stompMessageService.sendToUser(userIds, messageVO);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 加载已签收至占线板上的列车
|
||||
*
|
||||
* @param simulation 仿真信息
|
||||
*/
|
||||
private void loadSignRunPlanTrain(Simulation simulation) {
|
||||
if (!simulation.isPlanRunning()) {
|
||||
return;
|
||||
}
|
||||
// 没有加载过计划、始发计划、已发送至占线板、当前时间晚于计划时间提前5分钟
|
||||
simulation.getCtcRepository().getAllRunPlanList().stream()
|
||||
.filter(r -> r.getDepartRunPlan() != null && (r.isStartRunPlan() || (r.getArriveRunPlan() == null && r.getDepartRunPlan() != null)))
|
||||
.filter(r -> {
|
||||
boolean valid = !r.isLoad() && r.isSign() && r.getStatus() != -1
|
||||
&& simulation.getCorrectSystemTime().isAfter(r.getDepartRunPlan().getPlanTime().minusMinutes(5));
|
||||
if (valid) {
|
||||
valid = !simulation.getRepository().getTrainInfoMap().values().stream()
|
||||
.anyMatch(trainInfo -> r.getDepartRunPlan().getTripNumber().equals(trainInfo.getTripNumber()));
|
||||
if (!valid) { // 如果列车已经上线,则直接修改状态
|
||||
r.setLoad(true);
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
})
|
||||
.sorted((r1, r2) -> r1.getDepartRunPlan().getPlanTime().isBefore(r2.getDepartRunPlan().getPlanTime()) ? -1 : 1)
|
||||
.forEach(r -> {
|
||||
Section section = r.getDepartRunPlan().getTrackSection();
|
||||
if (section.isFree()) {
|
||||
String tripNumber = r.getDepartRunPlan().getTripNumber();
|
||||
int lastNum = tripNumber.charAt(tripNumber.length() - 1) - 48;
|
||||
atsTrainLoadService.loadTripNumberTrain(simulation, tripNumber, section.getCode(), lastNum % 2 == 0);
|
||||
r.setLoad(true); // 已上线
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,261 +2,264 @@ package club.joylink.rtss.simulation.cbtc.CTC.service;
|
|||
|
||||
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
|
||||
import club.joylink.rtss.simulation.cbtc.CI.CiApiService;
|
||||
import club.joylink.rtss.simulation.cbtc.CTC.data.*;
|
||||
import club.joylink.rtss.simulation.cbtc.CTC.data.CascoControl;
|
||||
import club.joylink.rtss.simulation.cbtc.CTC.data.CtcRepository;
|
||||
import club.joylink.rtss.simulation.cbtc.CTC.data.CtcStationRunPlanLog;
|
||||
import club.joylink.rtss.simulation.cbtc.CTC.data.RouteSequence;
|
||||
import club.joylink.rtss.simulation.cbtc.Simulation;
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.*;
|
||||
import club.joylink.rtss.simulation.cbtc.exception.SimulationException;
|
||||
import club.joylink.rtss.simulation.cbtc.exception.SimulationExceptionType;
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.Route;
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.Section;
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.Station;
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.Switch;
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.SwitchElement;
|
||||
import java.time.LocalTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class CTCService {
|
||||
@Autowired
|
||||
private CiApiService ciApiService;
|
||||
@Resource
|
||||
private CascoControlService cascoControlService;
|
||||
/**
|
||||
* 创建了新的运行计划item
|
||||
*/
|
||||
public void runPlanItemCreate(Simulation simulation, Station station, CtcStationRunPlanLog.RunPlanItem item, boolean departure) {
|
||||
regenerateRouteSequenceAndTrackView(simulation, station);
|
||||
// CtcRepository ctcRepository = simulation.getCtcRepository();
|
||||
// //进路序列
|
||||
// RouteSequence routeSequence = ctcRepository.getRouteSequence(station.getCode());
|
||||
// AtomicInteger idGenerator = ctcRepository.getRouteSequenceIdGenerator();
|
||||
// RouteSequence.Line line = RouteSequence.buildLine(item, departure, idGenerator);
|
||||
// routeSequence.addLine(line);
|
||||
// //股道视图
|
||||
// TrackView trackView = ctcRepository.getTrackView(station.getCode());
|
||||
// if (departure) {
|
||||
// trackView.addDepartureLine(line);
|
||||
// } else {
|
||||
// trackView.addReceivingLine(line);
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* 运行计划item更新了
|
||||
*/
|
||||
public void runPlanItemUpdate(Simulation simulation, Station station, CtcStationRunPlanLog.RunPlanItem item, boolean departure) {
|
||||
regenerateRouteSequenceAndTrackView(simulation, station);
|
||||
// CtcRepository ctcRepository = simulation.getCtcRepository();
|
||||
// RouteSequence.Line routeSequenceLine = ctcRepository.getRouteSequenceLine(station.getCode(), item.getTripNumber(), departure);
|
||||
//
|
||||
// String oldTc = routeSequenceLine.getTrackCode();
|
||||
// String oldTn = routeSequenceLine.getTripNumber();
|
||||
//
|
||||
// routeSequenceLine.update();
|
||||
//
|
||||
// ctcRepository.updateTrackView(station.getCode(), oldTc, oldTn, routeSequenceLine);
|
||||
}
|
||||
@Autowired
|
||||
private CiApiService ciApiService;
|
||||
@Resource
|
||||
private CascoControlService cascoControlService;
|
||||
|
||||
/**
|
||||
* 重新生成进路序列和股道视图
|
||||
* 该方法应该在车务终端发送阶段计划之后调用
|
||||
*/
|
||||
public void regenerateRouteSequenceAndTrackView(Simulation simulation, Station station) {
|
||||
if (simulation.getRepository().getConfig().isHasCTC()) {
|
||||
CtcRepository ctcRepository = simulation.getCtcRepository();
|
||||
ctcRepository.buildRouteSequence(station);
|
||||
ctcRepository.buildTrackViewData(station);
|
||||
/**
|
||||
* 重新生成进路序列和股道视图 该方法应该在车务终端发送阶段计划之后调用
|
||||
*/
|
||||
public void regenerateRouteSequenceAndTrackView(Simulation simulation, Station station) {
|
||||
if (simulation.getRepository().getConfig().isHasCTC()) {
|
||||
CtcRepository ctcRepository = simulation.getCtcRepository();
|
||||
ctcRepository.buildRouteSequence(station);
|
||||
ctcRepository.buildTrackViewData(station);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 完成接预
|
||||
*/
|
||||
public void finishReceivingNotice(Simulation simulation, String stationCode, String tripNumber) {
|
||||
CtcStationRunPlanLog plan = getCtcStationRunPlan(simulation, stationCode, tripNumber);
|
||||
plan.finishReceivingNotice();
|
||||
String systemTime = simulation.getCorrectSystemTime()
|
||||
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:dd"));
|
||||
plan.getArriveRunPlan().setAdjacentMessageTime(systemTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消接预
|
||||
*/
|
||||
public void cancelReceivingNotice(Simulation simulation, String stationCode, String tripNumber) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 完成发预
|
||||
*/
|
||||
public void finishDepartureNotice(Simulation simulation, String stationCode, String tripNumber) {
|
||||
CtcStationRunPlanLog plan = getCtcStationRunPlan(simulation, stationCode, tripNumber);
|
||||
plan.finishDepartureNotice();
|
||||
String systemTime = simulation.getCorrectSystemTime()
|
||||
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:dd"));
|
||||
plan.getDepartRunPlan().setAdjacentMessageTime(systemTime);
|
||||
}
|
||||
|
||||
public void cancelDepartureNotice(Simulation simulation, String stationCode, String tripNumber) {
|
||||
|
||||
}
|
||||
|
||||
public void finishArrive(Simulation simulation, String stationCode, String tripNumber,
|
||||
LocalTime time) {
|
||||
CtcStationRunPlanLog plan = getCtcStationRunPlan(simulation, stationCode, tripNumber);
|
||||
if (time == null) {
|
||||
time = simulation.getCorrectSystemTime().toLocalTime();
|
||||
}
|
||||
plan.finishArrive(time);
|
||||
}
|
||||
|
||||
public void cancelArrive(Simulation simulation, String stationCode, String tripNumber) {
|
||||
CtcStationRunPlanLog plan = getCtcStationRunPlan(simulation, stationCode, tripNumber);
|
||||
plan.cancelArrive();
|
||||
}
|
||||
|
||||
public void finishDeparture(Simulation simulation, String stationCode, String tripNumber,
|
||||
LocalTime time) {
|
||||
CtcStationRunPlanLog plan = getCtcStationRunPlan(simulation, stationCode, tripNumber);
|
||||
if (time == null) {
|
||||
time = simulation.getCorrectSystemTime().toLocalTime();
|
||||
}
|
||||
plan.finishDeparture(time);
|
||||
}
|
||||
|
||||
public void cancelDeparture(Simulation simulation, String stationCode, String tripNumber) {
|
||||
CtcStationRunPlanLog plan = getCtcStationRunPlan(simulation, stationCode, tripNumber);
|
||||
plan.cancelDeparture();
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送发车预告
|
||||
*/
|
||||
public void sendDepartureNotice(Simulation simulation, String stationCode, String runPlanCode) {
|
||||
CtcStationRunPlanLog currentStationPlan = getCtcStationRunPlanByRunPlanCode(simulation,
|
||||
stationCode, runPlanCode);
|
||||
Station nextStation = currentStationPlan.getNextStation();
|
||||
CtcStationRunPlanLog nextStationPlan = getCtcStationRunPlanByRunPlanCode(simulation,
|
||||
nextStation.getCode(), runPlanCode);
|
||||
currentStationPlan.sendDepartureNotice();
|
||||
nextStationPlan.receiveDepartureNotice();
|
||||
}
|
||||
|
||||
/**
|
||||
* 同意发车预告
|
||||
*/
|
||||
public void agreeDepartureNotice(Simulation simulation, String stationCode, String runPlanCode) {
|
||||
CtcStationRunPlanLog currentStationPlan = getCtcStationRunPlanByRunPlanCode(simulation,
|
||||
stationCode, runPlanCode);
|
||||
Station previousStation = currentStationPlan.getPreviousStation();
|
||||
CtcStationRunPlanLog previousStationPlan = getCtcStationRunPlanByRunPlanCode(simulation,
|
||||
previousStation.getCode(), runPlanCode);
|
||||
currentStationPlan.finishReceivingNotice();
|
||||
previousStationPlan.finishDepartureNotice();
|
||||
String systemTime = simulation.getCorrectSystemTime()
|
||||
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:dd"));
|
||||
currentStationPlan.getArriveRunPlan().setAdjacentMessageTime(systemTime);
|
||||
previousStationPlan.getDepartRunPlan().setAdjacentMessageTime(systemTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 进路自触
|
||||
*/
|
||||
public void routeAutoTrigger(Simulation simulation, String stationCode, String tripNumber,
|
||||
String routeCode, boolean trigger) {
|
||||
CtcRepository ctcRepository = simulation.getCtcRepository();
|
||||
RouteSequence.Line line = ctcRepository.getRouteSequenceLine(stationCode, tripNumber,
|
||||
routeCode);
|
||||
line.setAutoTrigger(trigger);
|
||||
}
|
||||
|
||||
private List<String> cascoControl(CascoControl cc, boolean force) {
|
||||
if (Objects.equals(true, force)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return this.cascoControlService.checkCascoControlRoute(cc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param simulation
|
||||
* @param routeCode
|
||||
* @param tripNumber
|
||||
* @param force
|
||||
* @param duration
|
||||
* @return
|
||||
*/
|
||||
public List<String> setRoute(Simulation simulation, String routeCode, String tripNumber,
|
||||
Boolean force, Integer duration) {
|
||||
Route route = simulation.getRepository().getByCode(routeCode, Route.class);
|
||||
if (force == null || !force) { // 非强制办理
|
||||
// 存在分路不良的区段
|
||||
boolean isBadShut = route.getSectionList().stream().anyMatch(Section::isBadShunt);
|
||||
if (isBadShut) {
|
||||
throw BusinessExceptionAssertEnum.OPERATION_FAIL.exception("进路不能办理,存在分路不良区段");
|
||||
}
|
||||
}
|
||||
Station station = route.getStart().getStation();
|
||||
if (station == null) {
|
||||
station = route.getStart().getDeviceStation();
|
||||
}
|
||||
|
||||
List<String> conflictInfo = new ArrayList<>();
|
||||
CtcRepository ctcRepository = simulation.getCtcRepository();
|
||||
CascoControl cc = new CascoControl(simulation, station, route, tripNumber);
|
||||
List<String> errCCMsg = this.cascoControl(cc,
|
||||
Objects.isNull(force) ? false : force.booleanValue());//站细卡控
|
||||
if (Objects.equals(false, CollectionUtils.isEmpty(errCCMsg))) {
|
||||
//站细检测错误的信息
|
||||
return errCCMsg;
|
||||
}
|
||||
if (StringUtils.hasText(tripNumber) && !Objects.equals(true, force)) { //列车进路防错办
|
||||
List<RouteSequence.Line> lines = ctcRepository.findRouteSequenceLines(station.getCode(),
|
||||
tripNumber);
|
||||
if (!CollectionUtils.isEmpty(lines)) {
|
||||
boolean b = lines.stream()
|
||||
.noneMatch(line -> Objects.equals(line.getRouteCode(), routeCode));
|
||||
if (b) {
|
||||
conflictInfo.add(
|
||||
String.format("车次[%s]的进路序列中不包含进路[name:%s]", tripNumber, route.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (duration != null && !Objects.equals(true, force)) { //调车进路防错办
|
||||
Set<Section> sections = new HashSet<>(route.getSectionList());
|
||||
Map<Switch, SwitchElement> switchMap = new HashMap<>();
|
||||
List<SwitchElement> switchList = route.getSwitchList();
|
||||
if (!CollectionUtils.isEmpty(switchList)) {
|
||||
switchMap = switchList.stream()
|
||||
.collect(Collectors.toMap(SwitchElement::getASwitch, Function.identity()));
|
||||
}
|
||||
LocalTime endTime = simulation.getCorrectSystemTime().plusSeconds(duration).toLocalTime();
|
||||
List<RouteSequence.Line> lines = ctcRepository.findRouteSequenceLineThatLessThan(
|
||||
station.getCode(), endTime);
|
||||
out:
|
||||
for (RouteSequence.Line line : lines) {
|
||||
Route lineRoute = line.getRoute();
|
||||
if (lineRoute == null) {
|
||||
continue;
|
||||
}
|
||||
for (Section section : lineRoute.getSectionList()) {
|
||||
if (sections.contains(section)) {
|
||||
conflictInfo.add(String.format("所选进路[name:%s]与车次[%s]的[name:%s]进路冲突",
|
||||
route.getName(), line.getTripNumber(), lineRoute.getName()));
|
||||
continue out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 完成接预
|
||||
*/
|
||||
public void finishReceivingNotice(Simulation simulation, String stationCode, String tripNumber) {
|
||||
CtcStationRunPlanLog plan = getCtcStationRunPlan(simulation, stationCode, tripNumber);
|
||||
plan.finishReceivingNotice();
|
||||
String systemTime = simulation.getCorrectSystemTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:dd"));
|
||||
plan.getArriveRunPlan().setAdjacentMessageTime(systemTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消接预
|
||||
*/
|
||||
public void cancelReceivingNotice(Simulation simulation, String stationCode, String tripNumber) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 完成发预
|
||||
*/
|
||||
public void finishDepartureNotice(Simulation simulation, String stationCode, String tripNumber) {
|
||||
CtcStationRunPlanLog plan = getCtcStationRunPlan(simulation, stationCode, tripNumber);
|
||||
plan.finishDepartureNotice();
|
||||
String systemTime = simulation.getCorrectSystemTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:dd"));
|
||||
plan.getDepartRunPlan().setAdjacentMessageTime(systemTime);
|
||||
}
|
||||
|
||||
public void cancelDepartureNotice(Simulation simulation, String stationCode, String tripNumber) {
|
||||
|
||||
}
|
||||
|
||||
public void finishArrive(Simulation simulation, String stationCode, String tripNumber, LocalTime time) {
|
||||
CtcStationRunPlanLog plan = getCtcStationRunPlan(simulation, stationCode, tripNumber);
|
||||
if (time == null)
|
||||
time = simulation.getCorrectSystemTime().toLocalTime();
|
||||
plan.finishArrive(time);
|
||||
}
|
||||
|
||||
public void cancelArrive(Simulation simulation, String stationCode, String tripNumber) {
|
||||
CtcStationRunPlanLog plan = getCtcStationRunPlan(simulation, stationCode, tripNumber);
|
||||
plan.cancelArrive();
|
||||
}
|
||||
|
||||
public void finishDeparture(Simulation simulation, String stationCode, String tripNumber, LocalTime time) {
|
||||
CtcStationRunPlanLog plan = getCtcStationRunPlan(simulation, stationCode, tripNumber);
|
||||
if (time == null)
|
||||
time = simulation.getCorrectSystemTime().toLocalTime();
|
||||
plan.finishDeparture(time);
|
||||
}
|
||||
|
||||
public void cancelDeparture(Simulation simulation, String stationCode, String tripNumber) {
|
||||
CtcStationRunPlanLog plan = getCtcStationRunPlan(simulation, stationCode, tripNumber);
|
||||
plan.cancelDeparture();
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送发车预告
|
||||
*/
|
||||
public void sendDepartureNotice(Simulation simulation, String stationCode, String runPlanCode) {
|
||||
CtcStationRunPlanLog currentStationPlan = getCtcStationRunPlanByRunPlanCode(simulation, stationCode, runPlanCode);
|
||||
Station nextStation = currentStationPlan.getNextStation();
|
||||
CtcStationRunPlanLog nextStationPlan = getCtcStationRunPlanByRunPlanCode(simulation, nextStation.getCode(), runPlanCode);
|
||||
currentStationPlan.sendDepartureNotice();
|
||||
nextStationPlan.receiveDepartureNotice();
|
||||
}
|
||||
|
||||
/**
|
||||
* 同意发车预告
|
||||
*/
|
||||
public void agreeDepartureNotice(Simulation simulation, String stationCode, String runPlanCode) {
|
||||
CtcStationRunPlanLog currentStationPlan = getCtcStationRunPlanByRunPlanCode(simulation, stationCode, runPlanCode);
|
||||
Station previousStation = currentStationPlan.getPreviousStation();
|
||||
CtcStationRunPlanLog previousStationPlan = getCtcStationRunPlanByRunPlanCode(simulation, previousStation.getCode(), runPlanCode);
|
||||
currentStationPlan.finishReceivingNotice();
|
||||
previousStationPlan.finishDepartureNotice();
|
||||
String systemTime = simulation.getCorrectSystemTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:dd"));
|
||||
currentStationPlan.getArriveRunPlan().setAdjacentMessageTime(systemTime);
|
||||
previousStationPlan.getDepartRunPlan().setAdjacentMessageTime(systemTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 进路自触
|
||||
*/
|
||||
public void routeAutoTrigger(Simulation simulation, String stationCode, String tripNumber, String routeCode, boolean trigger) {
|
||||
CtcRepository ctcRepository = simulation.getCtcRepository();
|
||||
RouteSequence.Line line = ctcRepository.getRouteSequenceLine(stationCode, tripNumber, routeCode);
|
||||
line.setAutoTrigger(trigger);
|
||||
}
|
||||
|
||||
private List<String> cascoControl(CascoControl cc,boolean force){
|
||||
if(Objects.equals(true,force)){
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return this.cascoControlService.checkCascoControlRoute(cc);
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param simulation
|
||||
* @param routeCode
|
||||
* @param tripNumber
|
||||
* @param force
|
||||
* @param duration
|
||||
* @return
|
||||
*/
|
||||
public List<String> setRoute(Simulation simulation, String routeCode, String tripNumber, Boolean force, Integer duration) {
|
||||
Route route = simulation.getRepository().getByCode(routeCode, Route.class);
|
||||
if (force == null || !force) { // 非强制办理
|
||||
// 存在分路不良的区段
|
||||
boolean isBadShut = route.getSectionList().stream().anyMatch(Section::isBadShunt);
|
||||
if (isBadShut) {
|
||||
throw BusinessExceptionAssertEnum.OPERATION_FAIL.exception("进路不能办理,存在分路不良区段");
|
||||
List<SwitchElement> sl = lineRoute.getSwitchList();
|
||||
if (!CollectionUtils.isEmpty(sl)) {
|
||||
for (SwitchElement element : sl) {
|
||||
SwitchElement e = switchMap.get(element.getASwitch());
|
||||
if (e != null && !element.equals(e)) {
|
||||
conflictInfo.add(String.format("所选进路[name:%s]与车次[%s]的[name:%s]进路冲突",
|
||||
route.getName(), line.getTripNumber(), lineRoute.getName()));
|
||||
continue out;
|
||||
}
|
||||
}
|
||||
}
|
||||
Station station = route.getStart().getStation();
|
||||
if (station == null)
|
||||
station = route.getStart().getDeviceStation();
|
||||
|
||||
List<String> conflictInfo = new ArrayList<>();
|
||||
CtcRepository ctcRepository = simulation.getCtcRepository();
|
||||
CascoControl cc = new CascoControl(simulation,station,route,tripNumber);
|
||||
List<String> errCCMsg = this.cascoControl(cc,Objects.isNull(force) ? false:force.booleanValue());//站细卡控
|
||||
if(Objects.equals(false,CollectionUtils.isEmpty(errCCMsg))){
|
||||
//站细检测错误的信息
|
||||
return errCCMsg;
|
||||
}
|
||||
if (StringUtils.hasText(tripNumber) && !Objects.equals(true, force)) { //列车进路防错办
|
||||
List<RouteSequence.Line> lines = ctcRepository.findRouteSequenceLines(station.getCode(), tripNumber);
|
||||
if (!CollectionUtils.isEmpty(lines)) {
|
||||
boolean b = lines.stream().noneMatch(line -> Objects.equals(line.getRouteCode(), routeCode));
|
||||
if (b)
|
||||
conflictInfo.add(String.format("车次[%s]的进路序列中不包含进路[name:%s]", tripNumber, route.getName()));
|
||||
}
|
||||
}
|
||||
if (duration != null && !Objects.equals(true, force)) { //调车进路防错办
|
||||
Set<Section> sections = new HashSet<>(route.getSectionList());
|
||||
Map<Switch, SwitchElement> switchMap = new HashMap<>();
|
||||
List<SwitchElement> switchList = route.getSwitchList();
|
||||
if (!CollectionUtils.isEmpty(switchList)) {
|
||||
switchMap = switchList.stream().collect(Collectors.toMap(SwitchElement::getASwitch, Function.identity()));
|
||||
}
|
||||
LocalTime endTime = simulation.getCorrectSystemTime().plusSeconds(duration).toLocalTime();
|
||||
List<RouteSequence.Line> lines = ctcRepository.findRouteSequenceLineThatLessThan(station.getCode(), endTime);
|
||||
out:
|
||||
for (RouteSequence.Line line : lines) {
|
||||
Route lineRoute = line.getRoute();
|
||||
if (lineRoute == null)
|
||||
continue;
|
||||
for (Section section : lineRoute.getSectionList()) {
|
||||
if (sections.contains(section)) {
|
||||
conflictInfo.add(String.format("所选进路[name:%s]与车次[%s]的[name:%s]进路冲突",
|
||||
route.getName(), line.getTripNumber(), lineRoute.getName()));
|
||||
continue out;
|
||||
}
|
||||
}
|
||||
List<SwitchElement> sl = lineRoute.getSwitchList();
|
||||
if (!CollectionUtils.isEmpty(sl)) {
|
||||
for (SwitchElement element : sl) {
|
||||
SwitchElement e = switchMap.get(element.getASwitch());
|
||||
if (e != null && !element.equals(e)) {
|
||||
conflictInfo.add(String.format("所选进路[name:%s]与车次[%s]的[name:%s]进路冲突",
|
||||
route.getName(), line.getTripNumber(), lineRoute.getName()));
|
||||
continue out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!conflictInfo.isEmpty())
|
||||
return conflictInfo;
|
||||
|
||||
Route.CheckFailMessage checkFailMessage = ciApiService.settingRoute(simulation, routeCode);
|
||||
if (checkFailMessage != null)
|
||||
throw BusinessExceptionAssertEnum.OPERATION_FAIL.exception(checkFailMessage.debugStr());
|
||||
route.setTripNumber(tripNumber);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (!conflictInfo.isEmpty()) {
|
||||
return conflictInfo;
|
||||
}
|
||||
|
||||
private CtcStationRunPlanLog getCtcStationRunPlan(Simulation simulation, String stationCode, String tripNumber) {
|
||||
CtcRepository ctcRepository = simulation.getCtcRepository();
|
||||
return ctcRepository.getRunPlan(stationCode, tripNumber);
|
||||
}
|
||||
Route.CheckFailMessage checkFailMessage = ciApiService.settingRoute(simulation, routeCode);
|
||||
if (checkFailMessage != null) {
|
||||
throw BusinessExceptionAssertEnum.OPERATION_FAIL.exception(checkFailMessage.debugStr());
|
||||
}
|
||||
route.setTripNumber(tripNumber);
|
||||
return null;
|
||||
}
|
||||
|
||||
private CtcStationRunPlanLog getCtcStationRunPlanByRunPlanCode(Simulation simulation, String stationCode, String runPlanCode) {
|
||||
CtcRepository ctcRepository = simulation.getCtcRepository();
|
||||
return ctcRepository.getRunPlanByRunPlanCode(stationCode, runPlanCode);
|
||||
}
|
||||
private CtcStationRunPlanLog getCtcStationRunPlan(Simulation simulation, String stationCode,
|
||||
String tripNumber) {
|
||||
CtcRepository ctcRepository = simulation.getCtcRepository();
|
||||
return ctcRepository.getRunPlan(stationCode, tripNumber);
|
||||
}
|
||||
|
||||
private CtcStationRunPlanLog getCtcStationRunPlanByRunPlanCode(Simulation simulation,
|
||||
String stationCode, String runPlanCode) {
|
||||
CtcRepository ctcRepository = simulation.getCtcRepository();
|
||||
return ctcRepository.getRunPlanByRunPlanCode(stationCode, runPlanCode);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,21 +7,6 @@ import club.joylink.rtss.vo.project.ProjectVO;
|
|||
* 项目综合演练仿真服务
|
||||
*/
|
||||
public interface ProjectJointSimulationService {
|
||||
/**
|
||||
* 实训室教员机登录创建仿真
|
||||
*
|
||||
* @param loginUserInfo
|
||||
* @return
|
||||
*/
|
||||
Simulation createSimulation(LoginUserInfoVO loginUserInfo);
|
||||
|
||||
/**
|
||||
* 获取实训室仿真
|
||||
*
|
||||
* @param project
|
||||
* @return
|
||||
*/
|
||||
Simulation getProjectSimulation(String project);
|
||||
|
||||
/**
|
||||
* 通过项目设置的mapID与功能ID获取仿真
|
||||
|
|
|
@ -1,35 +1,21 @@
|
|||
package club.joylink.rtss.simulation.cbtc;
|
||||
|
||||
import club.joylink.rtss.constants.MapPrdTypeEnum;
|
||||
import club.joylink.rtss.constants.ProjectDeviceType;
|
||||
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
|
||||
import club.joylink.rtss.services.IMapService;
|
||||
import club.joylink.rtss.services.auth.ProjectDeviceLogoutEvent;
|
||||
import club.joylink.rtss.services.auth.UserLogoutEvent;
|
||||
import club.joylink.rtss.services.project.DeviceService;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.SimulationRealDeviceThread;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.device.RealDeviceConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPRealDeviceThread;
|
||||
import club.joylink.rtss.simulation.cbtc.event.SimulationUserEnterEvent;
|
||||
import club.joylink.rtss.simulation.cbtc.member.MemberManager;
|
||||
import club.joylink.rtss.simulation.cbtc.member.SimulationUser;
|
||||
import club.joylink.rtss.vo.AccountVO;
|
||||
import club.joylink.rtss.vo.LoginUserInfoVO;
|
||||
import club.joylink.rtss.vo.client.project.ProjectDeviceVO;
|
||||
import club.joylink.rtss.vo.map.MapVO;
|
||||
import club.joylink.rtss.vo.project.ProjectVO;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
|
@ -40,169 +26,17 @@ public class ProjectJointSimulationServiceImpl implements ProjectJointSimulation
|
|||
@Autowired
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
@Autowired
|
||||
private IMapService iMapService;
|
||||
|
||||
@Autowired
|
||||
private DeviceService deviceService;
|
||||
|
||||
@Autowired
|
||||
private GroupSimulationService groupSimulationService;
|
||||
|
||||
@Autowired
|
||||
private MemberManager memberManager;
|
||||
|
||||
@Autowired
|
||||
private SimulationRealDeviceThread simulationRealDeviceThread;
|
||||
|
||||
@Autowired
|
||||
private UDPRealDeviceThread udpRealDeviceThread;
|
||||
|
||||
@Autowired
|
||||
private SimulationService simulationService;
|
||||
|
||||
@Override
|
||||
public Simulation createSimulation(LoginUserInfoVO loginUserInfo) {
|
||||
String project = loginUserInfo.getProject();
|
||||
Simulation oldSimulation = projectSimulationMap.get(project);
|
||||
// 之前的仿真销毁
|
||||
if (Objects.nonNull(oldSimulation)) {
|
||||
this.handleLogout(oldSimulation.getBuildParams().getLoginUserInfo());
|
||||
}
|
||||
// 权限判断
|
||||
|
||||
AccountVO accountVO = loginUserInfo.getAccountVO();
|
||||
// 查询用户综合演练配置
|
||||
|
||||
// 查询项目地图,默认取第一个(暂时这样处理,后面考虑配置实训室-地图对应?)
|
||||
List<MapVO> mapList = this.iMapService.findOnlineMapByProjectCode(project);
|
||||
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED.assertCollectionNotEmpty(mapList,
|
||||
String.format("项目[%s]无地图", project));
|
||||
// 查询项目设备
|
||||
List<ProjectDeviceVO> projectDeviceList = this.deviceService
|
||||
.queryDetailByTypes(ProjectDeviceType.PlcDeviceList(), project);
|
||||
List<RealDeviceConfig> realDeviceList = ProjectDeviceVO.convert2RealDeviceList(projectDeviceList);
|
||||
log.info(String.format("load project device list: [%s]",
|
||||
String.join(",", realDeviceList.stream().map(realDevice -> realDevice.toString()).collect(Collectors.toList()))));
|
||||
// 构建仿真
|
||||
Long mapId = mapList.get(0).getId();
|
||||
Simulation simulation = this.groupSimulationService.create(loginUserInfo, mapId,
|
||||
MapPrdTypeEnum.JOINT, Simulation.FunctionalType.SIMULATION);
|
||||
this.loadRealDevices(simulation, realDeviceList);
|
||||
projectSimulationMap.put(project, simulation);
|
||||
return simulation;
|
||||
}
|
||||
|
||||
private void loadRealDevices(Simulation simulation, List<RealDeviceConfig> realDeviceList) {
|
||||
try {
|
||||
simulation.setRealDeviceList(realDeviceList);
|
||||
if (!CollectionUtils.isEmpty(realDeviceList)) {
|
||||
simulationRealDeviceThread.addJobs(simulation);
|
||||
udpRealDeviceThread.addJobs(simulation);
|
||||
}
|
||||
for (RealDeviceConfig realDevice : realDeviceList) {
|
||||
if (ProjectDeviceType.PLC_GATEWAY.equals(realDevice.getDeviceType())) {
|
||||
continue;
|
||||
}
|
||||
String deviceCode = this.queryDeviceCodeFromConfig(realDevice);
|
||||
if (Objects.nonNull(deviceCode)) {
|
||||
this.groupSimulationService.connectDevice(simulation.getId(),
|
||||
deviceCode, realDevice.getProjectDevice().getId());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("仿真加载真实设备异常", e);
|
||||
// 清理仿真
|
||||
this.groupSimulationService.clearSimulation(simulation.getId(), simulation.getCreator());
|
||||
throw BusinessExceptionAssertEnum.TRAINING_ROOM_SIMULATION_LOAD_DEVICE_ERROR.exception(e);
|
||||
}
|
||||
}
|
||||
|
||||
private String queryDeviceCodeFromConfig(RealDeviceConfig config) {
|
||||
return config.findDeviceCode();
|
||||
// switch (config.getProject()) {
|
||||
// case "HEB": {
|
||||
// switch (config.getDeviceType()) {
|
||||
// case IBP:
|
||||
// return ((Heb1IbpConfig) config).getConfig().getStationCode();
|
||||
// case PSL:
|
||||
// return ((Heb1PslConfig) config).getConfig().getPsdCode();
|
||||
// case PSC:
|
||||
// return ((Heb1PscConfig) config).getConfig().getPsdCode();
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// case "XTY": {
|
||||
// switch (config.getDeviceType()) {
|
||||
// case PSD:
|
||||
// return ((XtyPsdConfig) config).getConfig().getPsdCode();
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// case "RICHOR_JOINT": {
|
||||
// switch (config.getDeviceType()) {
|
||||
// case IBP:
|
||||
// return ((ZjdIbpConfig) config).getConfigVO().getIbpCode();
|
||||
// case PSL:
|
||||
// return ((ZjdPslConfig) config).getConfigVO().getPslCode();
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// case "SR_SANDBOX": {
|
||||
// switch (config.getDeviceType()) {
|
||||
// case SIGNAL:
|
||||
// return ((SrSignalConfig) config).getConfigVO().getVrCode();
|
||||
// case SECTION:
|
||||
// return ((SrSectionConfig) config).getConfigVO().getVrCode();
|
||||
// case SWITCH:
|
||||
// return ((SrSwitchConfig) config).getConfigVO().getVrCode();
|
||||
// case TRAIN:
|
||||
// return ((SrTrainConfig) config).getConfigVO().getVrCode();
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// case "RICHOR_HHCJ": {
|
||||
// switch (config.getDeviceType()) {
|
||||
// case IBP:
|
||||
// return ((HhcjIbpConfig) config).getConfigVO().getIbpCode();
|
||||
// case PSD:
|
||||
// return ((HhcjPsdConfig) config).getConfigVO().getPsdCode();
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// case "SAY": {
|
||||
// return config.findDeviceCode();
|
||||
// switch (config.getDeviceType()) {
|
||||
// case IBP:
|
||||
// return ((SayIbpConfig) config).getConfigVO().getIbpCode();
|
||||
// case PSD:
|
||||
// return ((SayPsdConfig) config).getConfigVO().getPsdCode();
|
||||
// case SIGNAL:
|
||||
// return ((SaySignalConfig) config).getConfigVO().getSignalCode();
|
||||
// case SWITCH:
|
||||
// return ((SaySwitchConfig) config).getConfigVO().getSwitchCode();
|
||||
// case SECTION:
|
||||
// return config.findDeviceCode();
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// return null;
|
||||
}
|
||||
|
||||
private Simulation queryProjectSimulation(String project) {
|
||||
Simulation simulation = projectSimulationMap.get(project);
|
||||
return simulation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Simulation getProjectSimulation(String project) {
|
||||
Simulation simulation = projectSimulationMap.get(project);
|
||||
BusinessExceptionAssertEnum.TRAINING_ROOM_SIMULATION_NOT_EXIST
|
||||
.assertNotNull(simulation, String.format("项目[%s]实训室仿真不存在", project));
|
||||
return simulation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Simulation getSimulationByProject(ProjectVO project) {
|
||||
Simulation simulation = simulationService.querySimulation(project.getMapId(), project.getFunctionId());
|
||||
|
@ -219,52 +53,6 @@ public class ProjectJointSimulationServiceImpl implements ProjectJointSimulation
|
|||
simulation.addSimulationUser(simulationUser);
|
||||
SimulationUserEnterEvent userEnterEvent = new SimulationUserEnterEvent(this, simulation, simulationUser);
|
||||
this.applicationContext.publishEvent(userEnterEvent);
|
||||
// switch (deviceVO.getType()) {
|
||||
// case LW: {
|
||||
// // 暂时默认先按配置的车站创建成员
|
||||
// LwConfigVO lwConfigVO = deviceVO.buildLwConfig();
|
||||
// Station station = simulation.getRepository().getByCode(lwConfigVO.getStationCode(), Station.class);
|
||||
// SimulationMember member = simulation.getSimulationMember(station, SimulationMember.Type.STATION_SUPERVISOR);
|
||||
// this.memberManager.playRole(simulation, loginUserInfo.getAccountVO().getId(), member.getId());
|
||||
// // 现地工作站
|
||||
// break;
|
||||
// }
|
||||
// case CW: {
|
||||
// // 行调工作站
|
||||
// List<SimulationMember> dispatcherList = simulation.querySimulationMembersOfRole(SimulationMember.Type.DISPATCHER);
|
||||
// SimulationMember dispatcher = null;
|
||||
// for (SimulationMember member : dispatcherList) {
|
||||
// if (member.isRobot()) {
|
||||
// dispatcher = member;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// if (Objects.isNull(dispatcher)) {
|
||||
// // 行调都被占用,添加新的行调
|
||||
// dispatcher = this.memberManager.addRole(simulation, SimulationMember.Type.DISPATCHER);
|
||||
// }
|
||||
// this.memberManager.playRole(simulation, loginUserInfo.getAccountVO().getId(), dispatcher.getId());
|
||||
// break;
|
||||
// }
|
||||
// case DEPOT: {
|
||||
// List<SimulationMember> depoterList = simulation.querySimulationMembersOfRole(SimulationMember.Type.DEPOT_DISPATCHER);
|
||||
// SimulationMember depoter = null;
|
||||
// for (SimulationMember member : depoterList) {
|
||||
// if (member.isRobot()) {
|
||||
// depoter = member;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// if (Objects.isNull(depoter)) {
|
||||
// depoter = this.memberManager.addRole(simulation, SimulationMember.Type.DEPOT_DISPATCHER);
|
||||
// }
|
||||
// this.memberManager.playRole(simulation, loginUserInfo.getAccountVO().getId(), depoter.getId());
|
||||
// break;
|
||||
// }
|
||||
// case SCHEDULING: {
|
||||
//
|
||||
// }
|
||||
// }
|
||||
loginUserInfo.setGroup(simulation.getId());
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -6,7 +6,11 @@ import club.joylink.rtss.simulation.cbtc.constant.RunLevel;
|
|||
import club.joylink.rtss.simulation.cbtc.constant.SimulationConstants;
|
||||
import club.joylink.rtss.simulation.cbtc.constant.TrainTBControl;
|
||||
import club.joylink.rtss.simulation.cbtc.data.CalculateService;
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.*;
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.MapElement;
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.Section;
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.Signal;
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.Stand;
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.Station;
|
||||
import club.joylink.rtss.simulation.cbtc.data.plan.TripPlan;
|
||||
import club.joylink.rtss.simulation.cbtc.data.support.MovementAuthority;
|
||||
import club.joylink.rtss.simulation.cbtc.data.support.SectionPosition;
|
||||
|
@ -14,15 +18,14 @@ import club.joylink.rtss.simulation.cbtc.exception.SimulationException;
|
|||
import club.joylink.rtss.simulation.cbtc.exception.SimulationExceptionType;
|
||||
import club.joylink.rtss.vo.client.operation.DriveParamVO;
|
||||
import club.joylink.rtss.vo.ws.TrainPosition;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* 虚拟真实列车
|
||||
|
@ -1188,6 +1191,10 @@ public class VirtualRealityTrain extends VirtualRealityDevice {
|
|||
return robotDriveParam.needStop();
|
||||
}
|
||||
|
||||
public boolean isRobotStopControl() {
|
||||
return robotDriveParam.isStopControl();
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public static class Door extends ControllableVrDevice<Door.Operation> {
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
package club.joylink.rtss.simulation.cbtc.device.real.udp.sr;
|
||||
package club.joylink.rtss.simulation.cbtc.device.real.udp;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public class SrTrainControlParam {
|
||||
public class SandTableTrainControlParam {
|
||||
@NotBlank(message = "车组号不能为空")
|
||||
private String groupNumber;
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
package club.joylink.rtss.simulation.cbtc.device.real.udp;
|
||||
|
||||
import club.joylink.rtss.constants.ProjectCode;
|
||||
import club.joylink.rtss.dao.MapDataDAO;
|
||||
import club.joylink.rtss.entity.MapDataExample;
|
||||
import club.joylink.rtss.entity.MapDataWithBLOBs;
|
||||
import club.joylink.rtss.simulation.cbtc.GroupSimulationService;
|
||||
import club.joylink.rtss.simulation.cbtc.Simulation;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.service.SrTrainServiceImpl;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.service.ThailandTrainServiceImpl;
|
||||
import club.joylink.rtss.util.JsonUtils;
|
||||
import club.joylink.rtss.vo.map.MapLogicDataNewVO;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/sandTable")
|
||||
public class SandTableTrainController {
|
||||
|
||||
@Autowired
|
||||
private GroupSimulationService groupSimulationService;
|
||||
@Autowired
|
||||
private ThailandTrainServiceImpl thailandTrainService;
|
||||
@Autowired
|
||||
private SrTrainServiceImpl srTrainService;
|
||||
|
||||
@PutMapping("/{simulationId}/control")
|
||||
public void control(@PathVariable String simulationId, String groupNumber, boolean right,
|
||||
int speed) {
|
||||
Simulation simulation = groupSimulationService.getSimulationByGroup(simulationId);
|
||||
switch (simulation.getProject()) {
|
||||
case ProjectCode.THAILAND_SANDBOX:
|
||||
thailandTrainService.controlTrain(simulationId, groupNumber, right, speed);
|
||||
break;
|
||||
case ProjectCode.SR_SANDBOX:
|
||||
srTrainService.controlTrain(simulationId, groupNumber, right, speed);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private MapDataDAO mapDataDAO;
|
||||
|
||||
@PutMapping("/handle")
|
||||
public void handle() {
|
||||
MapDataExample example = new MapDataExample();
|
||||
example.setOrderByClause("id desc");
|
||||
example.setLimit(1);
|
||||
MapDataWithBLOBs data = mapDataDAO.selectByExampleWithBLOBs(example).get(0);
|
||||
MapLogicDataNewVO logicDataNewVO = JsonUtils.read(data.getLogicData(), MapLogicDataNewVO.class);
|
||||
logicDataNewVO.getRouteList().stream()
|
||||
.filter(route -> route.getStartSignalCode().equals("X542") || route.getStartSignalCode()
|
||||
.equals("X11357")
|
||||
|| route.getStartSignalCode().equals("X47820") || route.getStartSignalCode()
|
||||
.equals("X4371")
|
||||
|| route.getStartSignalCode().equals("X21134") || route.getStartSignalCode()
|
||||
.equals("X99402")
|
||||
|| route.getStartSignalCode().equals("X2670") || route.getStartSignalCode()
|
||||
.equals("X49087"))
|
||||
.forEach(route -> {
|
||||
route.setSignalAspect(3);
|
||||
});
|
||||
data.setLogicData(JsonUtils.writeValueAsString(logicDataNewVO));
|
||||
mapDataDAO.updateByPrimaryKeyWithBLOBs(data);
|
||||
}
|
||||
}
|
|
@ -10,6 +10,9 @@ import io.netty.channel.ChannelInitializer;
|
|||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.DatagramPacket;
|
||||
import io.netty.channel.socket.nio.NioDatagramChannel;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -18,73 +21,74 @@ import org.springframework.boot.ApplicationRunner;
|
|||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class UDPClient implements ApplicationRunner {
|
||||
@Autowired
|
||||
private UDPConfig udpConfig;
|
||||
|
||||
private Channel channel;
|
||||
@Autowired
|
||||
private UDPConfig udpConfig;
|
||||
|
||||
private final ConcurrentLinkedQueue<Msg> msgQueue = new ConcurrentLinkedQueue<>();
|
||||
private Channel channel;
|
||||
|
||||
@Override
|
||||
public void run(ApplicationArguments args) throws Exception {
|
||||
this.start();
|
||||
private final ConcurrentLinkedQueue<Msg> msgQueue = new ConcurrentLinkedQueue<>();
|
||||
|
||||
@Override
|
||||
public void run(ApplicationArguments args) throws Exception {
|
||||
this.start();
|
||||
}
|
||||
|
||||
public void start() throws InterruptedException {
|
||||
Bootstrap bootstrap = new Bootstrap();
|
||||
NioEventLoopGroup group = new NioEventLoopGroup();
|
||||
bootstrap.group(group)
|
||||
.channel(NioDatagramChannel.class)
|
||||
.handler(new ChannelInitializer<NioDatagramChannel>() {
|
||||
@Override
|
||||
protected void initChannel(NioDatagramChannel channel) {
|
||||
}
|
||||
});
|
||||
ChannelFuture future = bootstrap.bind(udpConfig.getClientPort()).sync();
|
||||
Channel channel = future.channel();
|
||||
this.channel = channel;
|
||||
if (future.isSuccess()) {
|
||||
log.info(String.format("udp client start on port [%s]", this.udpConfig.getClientPort()));
|
||||
} else {
|
||||
log.error("udp server start failed", future.cause());
|
||||
}
|
||||
}
|
||||
|
||||
public void start() throws InterruptedException {
|
||||
Bootstrap bootstrap = new Bootstrap();
|
||||
NioEventLoopGroup group = new NioEventLoopGroup();
|
||||
bootstrap.group(group)
|
||||
.channel(NioDatagramChannel.class)
|
||||
.handler(new ChannelInitializer<NioDatagramChannel>() {
|
||||
@Override
|
||||
protected void initChannel(NioDatagramChannel channel) {
|
||||
}
|
||||
});
|
||||
ChannelFuture future = bootstrap.bind(udpConfig.getClientPort()).sync();
|
||||
Channel channel = future.channel();
|
||||
this.channel = channel;
|
||||
if (future.isSuccess()) {
|
||||
log.info(String.format("udp client start on port [%s]", this.udpConfig.getClientPort()));
|
||||
} else {
|
||||
log.error("udp server start failed", future.cause());
|
||||
}
|
||||
public void write(InetSocketAddress addr, byte[] msg) {
|
||||
if (msg != null) {
|
||||
msgQueue.add(new Msg(addr, msg));
|
||||
System.out.println(LocalDateTime.now());
|
||||
}
|
||||
}
|
||||
|
||||
public void write(InetSocketAddress addr, byte[] msg) {
|
||||
msgQueue.add(new Msg(addr, msg));
|
||||
@Scheduled(fixedRate = 10)
|
||||
public void send() {
|
||||
Msg msg = msgQueue.poll();
|
||||
if (msg == null) {
|
||||
return;
|
||||
}
|
||||
InetSocketAddress addr = msg.getAddr();
|
||||
byte[] data = msg.getData();
|
||||
if (channel != null && channel.isWritable() && addr != null && data != null) {
|
||||
ByteBuf byteBuf = Unpooled.copiedBuffer(data);
|
||||
DatagramPacket datagramPacket = new DatagramPacket(byteBuf, addr);
|
||||
channel.writeAndFlush(datagramPacket);
|
||||
}
|
||||
}
|
||||
|
||||
@Scheduled(fixedRate = 10)
|
||||
public void send() {
|
||||
Msg msg = msgQueue.poll();
|
||||
if (msg == null)
|
||||
return;
|
||||
InetSocketAddress addr = msg.getAddr();
|
||||
byte[] data = msg.getData();
|
||||
if (channel != null && channel.isWritable() && addr != null && data != null) {
|
||||
ByteBuf byteBuf = Unpooled.copiedBuffer(data);
|
||||
DatagramPacket datagramPacket = new DatagramPacket(byteBuf, addr);
|
||||
channel.writeAndFlush(datagramPacket);
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
class Msg {
|
||||
private InetSocketAddress addr;
|
||||
|
||||
private byte[] data;
|
||||
|
||||
public Msg(InetSocketAddress addr, byte[] data) {
|
||||
this.addr = addr;
|
||||
this.data = data;
|
||||
}
|
||||
@Getter
|
||||
class Msg {
|
||||
|
||||
private InetSocketAddress addr;
|
||||
|
||||
private byte[] data;
|
||||
|
||||
public Msg(InetSocketAddress addr, byte[] data) {
|
||||
this.addr = addr;
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,12 +5,11 @@ import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.device.RealDevice
|
|||
import club.joylink.rtss.util.JsonUtils;
|
||||
import club.joylink.rtss.vo.client.project.ProjectDeviceVO;
|
||||
import club.joylink.rtss.vo.client.project.UDPLowConfigVO;
|
||||
import lombok.Getter;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import lombok.Getter;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
public class UDPLowConfig extends RealDeviceConfig {
|
||||
@Getter
|
||||
|
@ -53,4 +52,8 @@ public class UDPLowConfig extends RealDeviceConfig {
|
|||
public String findDeviceCode() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return configVO == null ? null : configVO.getName();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,10 @@ import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.device.RealDevice
|
|||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
public interface UDPRealDeviceService {
|
||||
default boolean isMatch(UDPLowConfig udpLowConfig) {
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean isMatch(RealDeviceConfig realDevice);
|
||||
|
||||
void run(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice);
|
||||
|
|
|
@ -3,93 +3,104 @@ package club.joylink.rtss.simulation.cbtc.device.real.udp;
|
|||
import club.joylink.rtss.constants.ProjectDeviceType;
|
||||
import club.joylink.rtss.simulation.cbtc.GroupSimulationService;
|
||||
import club.joylink.rtss.simulation.cbtc.Simulation;
|
||||
import club.joylink.rtss.simulation.cbtc.constant.SimulationConstants;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.device.PlcGateway;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.device.RealDeviceConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.event.SimulationResetEvent;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import java.util.List;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class UDPRealDeviceThread {
|
||||
@Autowired
|
||||
private UDPRealDeviceServiceManager udpRealDeviceServiceManager;
|
||||
|
||||
@Autowired
|
||||
private GroupSimulationService groupSimulationService;
|
||||
/**
|
||||
* 真是设备逻辑执行频率。
|
||||
* <p>
|
||||
* 因沙盘对延迟要求较高,所以将频率提高
|
||||
*/
|
||||
public static final int RATE = 10;
|
||||
|
||||
@EventListener
|
||||
public void simulationReset(SimulationResetEvent event) {
|
||||
Simulation simulation = event.getSimulation();
|
||||
List<RealDeviceConfig> realDeviceList = simulation.getRealDeviceList();
|
||||
if (CollectionUtils.isEmpty(realDeviceList))
|
||||
return;
|
||||
UDPLowConfig udpConfig = (UDPLowConfig) simulation.queryOneRealDevice(ProjectDeviceType.UDP_LOW);
|
||||
if (udpConfig == null)
|
||||
return;
|
||||
for (RealDeviceConfig realDevice : realDeviceList) {
|
||||
if (realDevice instanceof PlcGateway) {
|
||||
continue;
|
||||
}
|
||||
for (UDPRealDeviceService realDeviceService : this.udpRealDeviceServiceManager.getServiceList()) {
|
||||
if (realDeviceService.isMatch(realDevice)) {
|
||||
realDeviceService.init(simulation, udpConfig, realDevice);
|
||||
}
|
||||
}
|
||||
}
|
||||
@Autowired
|
||||
private UDPRealDeviceServiceManager udpRealDeviceServiceManager;
|
||||
|
||||
@Autowired
|
||||
private GroupSimulationService groupSimulationService;
|
||||
|
||||
@EventListener
|
||||
public void simulationReset(SimulationResetEvent event) {
|
||||
Simulation simulation = event.getSimulation();
|
||||
List<RealDeviceConfig> realDeviceList = simulation.getRealDeviceList();
|
||||
if (CollectionUtils.isEmpty(realDeviceList)) {
|
||||
return;
|
||||
}
|
||||
|
||||
public void run(Simulation simulation) {
|
||||
List<RealDeviceConfig> realDeviceList = simulation.getRealDeviceList();
|
||||
if (CollectionUtils.isEmpty(realDeviceList))
|
||||
return;
|
||||
List<UDPRealDeviceService> serviceList = udpRealDeviceServiceManager.getServiceList();
|
||||
if (CollectionUtils.isEmpty(serviceList))
|
||||
return;
|
||||
UDPLowConfig udpLowConfig = null;
|
||||
for (RealDeviceConfig realDeviceConfig : realDeviceList) {
|
||||
if (ProjectDeviceType.UDP_LOW.equals(realDeviceConfig.getDeviceType())) {
|
||||
udpLowConfig = (UDPLowConfig) realDeviceConfig;
|
||||
break;
|
||||
}
|
||||
UDPLowConfig udpConfig = (UDPLowConfig) simulation.queryOneRealDevice(
|
||||
ProjectDeviceType.UDP_LOW);
|
||||
if (udpConfig == null) {
|
||||
return;
|
||||
}
|
||||
for (RealDeviceConfig realDevice : realDeviceList) {
|
||||
if (realDevice instanceof PlcGateway) {
|
||||
continue;
|
||||
}
|
||||
for (UDPRealDeviceService realDeviceService : this.udpRealDeviceServiceManager.getServiceList()) {
|
||||
if (realDeviceService.isMatch(realDevice)) {
|
||||
realDeviceService.init(simulation, udpConfig, realDevice);
|
||||
}
|
||||
for (RealDeviceConfig config : realDeviceList) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void run(Simulation simulation) {
|
||||
List<RealDeviceConfig> realDeviceList = simulation.getRealDeviceList();
|
||||
if (CollectionUtils.isEmpty(realDeviceList)) {
|
||||
return;
|
||||
}
|
||||
List<UDPRealDeviceService> serviceList = udpRealDeviceServiceManager.getServiceList();
|
||||
if (CollectionUtils.isEmpty(serviceList)) {
|
||||
return;
|
||||
}
|
||||
realDeviceList.stream()
|
||||
.filter(
|
||||
realDeviceConfig -> ProjectDeviceType.UDP_LOW.equals(realDeviceConfig.getDeviceType()))
|
||||
.map(realDeviceConfig -> (UDPLowConfig) realDeviceConfig)
|
||||
.forEach(udpLowConfig -> {
|
||||
for (RealDeviceConfig config : realDeviceList) {
|
||||
for (UDPRealDeviceService service : serviceList) {
|
||||
if (service.isMatch(config) && config.getMapElement() != null) {
|
||||
service.run(simulation, udpLowConfig, config);
|
||||
}
|
||||
if (service.isMatch(udpLowConfig) && service.isMatch(config)
|
||||
&& config.getMapElement() != null) {
|
||||
service.run(simulation, udpLowConfig, config);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void handleData(String ip, int port, ByteBuf data) {
|
||||
List<Simulation> simulations = groupSimulationService.querySimulations();
|
||||
for (Simulation simulation : simulations) {
|
||||
List<RealDeviceConfig> realDeviceList = simulation.getRealDeviceList();
|
||||
if (CollectionUtils.isEmpty(realDeviceList))
|
||||
continue;
|
||||
UDPClientConfig udpClientConfig = (UDPClientConfig) simulation.queryOneRealDevice(ProjectDeviceType.UDP_CLIENT);
|
||||
if (udpClientConfig != null && Objects.equals(ip, udpClientConfig.getConfigVO().getIp())
|
||||
&& Objects.equals(port, udpClientConfig.getConfigVO().getPort())) {
|
||||
for (UDPRealDeviceService udpRealDeviceService : this.udpRealDeviceServiceManager.getServiceList()) {
|
||||
if (udpRealDeviceService.isMatch(udpClientConfig)) {
|
||||
udpRealDeviceService.handle(simulation, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
public void handleData(String ip, int port, ByteBuf data) {
|
||||
List<Simulation> simulations = groupSimulationService.querySimulations();
|
||||
for (Simulation simulation : simulations) {
|
||||
List<RealDeviceConfig> realDeviceList = simulation.getRealDeviceList();
|
||||
if (CollectionUtils.isEmpty(realDeviceList)) {
|
||||
continue;
|
||||
}
|
||||
UDPClientConfig udpClientConfig = (UDPClientConfig) simulation.queryOneRealDevice(
|
||||
ProjectDeviceType.UDP_CLIENT);
|
||||
if (udpClientConfig != null /*&& Objects.equals(ip, udpClientConfig.getConfigVO().getIp())
|
||||
&& Objects.equals(port, udpClientConfig.getConfigVO().getPort())*/) {
|
||||
for (UDPRealDeviceService udpRealDeviceService : this.udpRealDeviceServiceManager.getServiceList()) {
|
||||
if (udpRealDeviceService.isMatch(udpClientConfig)) {
|
||||
udpRealDeviceService.handle(simulation, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addJobs(Simulation simulation) {
|
||||
simulation.addFixedRateJob(Simulation.JobName.udpRealDevice,
|
||||
() -> this.run(simulation), SimulationConstants.VRD_LOOP_RATE);
|
||||
}
|
||||
public void addJobs(Simulation simulation) {
|
||||
simulation.addFixedRateJob(Simulation.JobName.udpRealDevice, () -> this.run(simulation), RATE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
package club.joylink.rtss.simulation.cbtc.device.real.udp.sr;
|
||||
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.service.SrTrainServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/sr")
|
||||
public class SrTrainController {
|
||||
@Autowired
|
||||
private SrTrainServiceImpl srTrainService;
|
||||
|
||||
// @PutMapping("/{simulationId}/control")
|
||||
// public void control(@PathVariable String simulationId, @RequestBody @Validated SrTrainControlParam controlParam) {
|
||||
// srTrainService.control(simulationId, controlParam.getGroupNumber(), controlParam.getRight(), controlParam.getSpeed());
|
||||
// }
|
||||
|
||||
@PutMapping("/{simulationId}/control")
|
||||
public void control(@PathVariable String simulationId, String groupNumber, boolean right, int speed) {
|
||||
srTrainService.controlTrain(simulationId, groupNumber, right, speed);
|
||||
}
|
||||
}
|
|
@ -15,10 +15,6 @@ import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPRealDeviceService;
|
|||
import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config.SrSectionConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config.SrTrainConfig;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@ -26,167 +22,187 @@ import java.util.Map;
|
|||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class SrSectionServiceImpl implements UDPRealDeviceService {
|
||||
@Autowired
|
||||
private SrTrainServiceImpl srTrainService;
|
||||
|
||||
@Autowired
|
||||
private MaService maService;
|
||||
public static final String PROJECT_CODE = "SR_SANDBOX";
|
||||
|
||||
@Override
|
||||
public boolean isMatch(RealDeviceConfig realDevice) {
|
||||
return realDevice instanceof UDPClientConfig;
|
||||
@Autowired
|
||||
private MaService maService;
|
||||
|
||||
@Override
|
||||
public boolean isMatch(RealDeviceConfig realDevice) {
|
||||
return realDevice instanceof UDPClientConfig && PROJECT_CODE
|
||||
.equals(realDevice.getProject());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Simulation simulation, ByteBuf msg) {
|
||||
//检查数据
|
||||
byte[] data = new byte[msg.readableBytes()];
|
||||
if (data.length < 4) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
|
||||
|
||||
msg.readBytes(data);
|
||||
if (Byte.toUnsignedInt(data[1]) != 137) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Simulation simulation, ByteBuf msg) {
|
||||
//检查数据
|
||||
byte[] data = new byte[msg.readableBytes()];
|
||||
if (data.length < 4)
|
||||
return;
|
||||
msg.readBytes(data);
|
||||
if (Byte.toUnsignedInt(data[1]) != 137) {
|
||||
return;
|
||||
//处理数据
|
||||
Map<String, SrSectionConfig> configMap = simulation.queryAllRealDevice(
|
||||
ProjectDeviceType.SECTION).stream()
|
||||
.map(config -> (SrSectionConfig) config)
|
||||
.collect(
|
||||
Collectors.toMap(config -> config.getConfigVO().getSandboxCode(), Function.identity()));
|
||||
for (int i = 3, dataLength = data.length; i < dataLength; i += 2) {
|
||||
int code = Byte.toUnsignedInt(data[i - 1]);
|
||||
String key = String.valueOf(code);
|
||||
SrSectionConfig config = configMap.get(key);
|
||||
if (config == null) {
|
||||
continue;
|
||||
}
|
||||
VirtualRealitySectionAxleCounter axle = (VirtualRealitySectionAxleCounter) config.getMapElement();
|
||||
if (axle != null) {
|
||||
int n = Byte.toUnsignedInt(data[i]);
|
||||
if (n == 170) {
|
||||
updateTrainPosition(simulation, axle);
|
||||
config.setTimesOfRelease(0);
|
||||
axle.setOccupy(true);
|
||||
} else if (n == 85) {
|
||||
config.setTimesOfRelease(config.getTimesOfRelease() + 1);
|
||||
if (config.getTimesOfRelease() > 3) { //连续4次该计轴都是无占用状态,才视为确实无占用
|
||||
config.setTimesOfRelease(0);
|
||||
axle.clear();
|
||||
}
|
||||
}
|
||||
//处理数据
|
||||
Map<String, SrSectionConfig> configMap = simulation.queryAllRealDevice(ProjectDeviceType.SECTION).stream()
|
||||
.map(config -> (SrSectionConfig) config)
|
||||
.collect(Collectors.toMap(config -> config.getConfigVO().getSandboxCode(), Function.identity()));
|
||||
for (int i = 3, dataLength = data.length; i < dataLength; i += 2) {
|
||||
int code = Byte.toUnsignedInt(data[i - 1]);
|
||||
String key = String.valueOf(code);
|
||||
SrSectionConfig config = configMap.get(key);
|
||||
if (config == null)
|
||||
continue;
|
||||
VirtualRealitySectionAxleCounter axle = (VirtualRealitySectionAxleCounter) config.getMapElement();
|
||||
if (axle != null) {
|
||||
int n = Byte.toUnsignedInt(data[i]);
|
||||
if (n == 170) {
|
||||
updateTrainPosition(simulation, axle);
|
||||
config.setTimesOfRelease(0);
|
||||
axle.setOccupy(true);
|
||||
} else if (n == 85) {
|
||||
config.setTimesOfRelease(config.getTimesOfRelease() + 1);
|
||||
if (config.getTimesOfRelease() > 3) { //连续4次该计轴都是无占用状态,才视为确实无占用
|
||||
config.setTimesOfRelease(0);
|
||||
axle.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//设置停车信息
|
||||
stop(simulation);
|
||||
}
|
||||
}
|
||||
//设置停车信息
|
||||
stop(simulation);
|
||||
}
|
||||
|
||||
/**
|
||||
* 列车到达特殊轨道,设置延迟停车时间
|
||||
*/
|
||||
private void stop(Simulation simulation) {
|
||||
for (VirtualRealityTrain train : simulation.getRepository().getOnlineTrainList()) {
|
||||
Section headSection = train.getHeadPosition().getSection();
|
||||
/**
|
||||
* 列车到达特殊轨道,设置延迟停车时间
|
||||
*/
|
||||
private void stop(Simulation simulation) {
|
||||
for (VirtualRealityTrain train : simulation.getRepository().getOnlineTrainList()) {
|
||||
Section headSection = train.getHeadPosition().getSection();
|
||||
SrTrainConfig config = (SrTrainConfig) train.getRealDevice();
|
||||
if (!Objects.equals(headSection, config.getHeadSection())) //列车无需在该站台停车
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (config.getTimeOfStop() != null) //已经设置过停车时间
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!headSection.isFunctionTrack()) {
|
||||
continue;
|
||||
}
|
||||
VirtualRealitySectionAxleCounter headAxle = headSection.findAxle();
|
||||
if (headAxle == null) {
|
||||
continue;
|
||||
}
|
||||
SrSectionConfig sectionConfig = (SrSectionConfig) headAxle.getRealDevice();
|
||||
//设置延时停车时间
|
||||
long m = 1000000000;
|
||||
long nanos;
|
||||
if (sectionConfig.getConfigVO().getHeadDelayTime() != null) {
|
||||
nanos = (long) (sectionConfig.getConfigVO().getHeadDelayTime() * m);
|
||||
config.setTimeOfStop(LocalDateTime.now().plusNanos(nanos));
|
||||
continue;
|
||||
}
|
||||
//以前一个区段无占用作为停车标志的区段
|
||||
boolean right = train.isRight();
|
||||
Section behindSection = headSection.getNextRunningSectionOf(!right);
|
||||
if (behindSection == null) {
|
||||
continue;
|
||||
}
|
||||
VirtualRealitySectionAxleCounter behindAxle = behindSection.findAxle();
|
||||
if (behindAxle == null) {
|
||||
continue;
|
||||
}
|
||||
if (!behindAxle.isOccupy()) { //车头后方区段所属计轴无占用状态
|
||||
nanos = 0;
|
||||
if (sectionConfig.getConfigVO().getTailDelayTime() != null) {
|
||||
nanos = (long) (sectionConfig.getConfigVO().getTailDelayTime() * m);
|
||||
}
|
||||
if (nanos == 0) {
|
||||
train.setHeadPosition(headSection.buildStopPointPosition(right));
|
||||
} else {
|
||||
config.setTimeOfStop(LocalDateTime.now().plusNanos(nanos));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTrainPosition(Simulation simulation, VirtualRealitySectionAxleCounter axle) {
|
||||
for (Section section : simulation.getRepository().getAxleSectionList()) {
|
||||
if (section.getVirtualAxleCounter().equals(axle)) {
|
||||
List<Section> pSection;
|
||||
if (section.isPhysical()) {
|
||||
pSection = Collections.singletonList(section);
|
||||
} else if (section.isSwitchAxleCounterSection()) {
|
||||
pSection = section.findConnectedSections();
|
||||
} else {
|
||||
pSection = Collections.emptyList();
|
||||
}
|
||||
for (Section sec : pSection) {
|
||||
check4UpdateHeadPosition(simulation, sec, false);
|
||||
check4UpdateHeadPosition(simulation, sec, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否有right向的列车可以更新车头位置
|
||||
*/
|
||||
private void check4UpdateHeadPosition(Simulation simulation, Section occupiedSection,
|
||||
boolean right) {
|
||||
Section section = occupiedSection.getNextRunningSectionOf(!right); //找反向的区段
|
||||
if (section != null) {
|
||||
for (VirtualRealityTrain train : simulation.getRepository().getOnlineTrainList()) {
|
||||
Section headSection = train.getHeadPosition().getSection();
|
||||
boolean trainRight = train.isRight();
|
||||
if (trainRight == right && section.equals(headSection)) { //列车到达occupiedSection
|
||||
//判断更新ITC ma
|
||||
if (headSection.getSignalOf(trainRight) != null) {
|
||||
maService.calculateAndUpdateItcMa(simulation, train);
|
||||
}
|
||||
//更新位置
|
||||
SectionPosition headPosition;
|
||||
SectionPosition stopPointPosition;
|
||||
if (occupiedSection.isFunctionTrack()) {
|
||||
stopPointPosition = occupiedSection.buildStopPointPosition(right);
|
||||
headPosition = CalculateService.calculateNextPositionByStartAndLen(stopPointPosition,
|
||||
!right, 1, true);
|
||||
} else {
|
||||
stopPointPosition = new SectionPosition(occupiedSection,
|
||||
occupiedSection.getEndOffsetByDirection(right));
|
||||
headPosition = CalculateService.calculateNextPositionByStartAndLen(stopPointPosition,
|
||||
!right, 3, true);
|
||||
}
|
||||
train.setHeadPosition(headPosition); //更新位置
|
||||
if (occupiedSection.isFunctionTrack()) { //功能轨可能需要停车
|
||||
SrTrainConfig config = (SrTrainConfig) train.getRealDevice();
|
||||
if (!Objects.equals(headSection, config.getHeadSection())) //列车无需在该站台停车
|
||||
continue;
|
||||
if (config.getTimeOfStop() != null) //已经设置过停车时间
|
||||
continue;
|
||||
if (!headSection.isFunctionTrack())
|
||||
continue;
|
||||
VirtualRealitySectionAxleCounter headAxle = headSection.findAxle();
|
||||
if (headAxle == null)
|
||||
continue;
|
||||
SrSectionConfig sectionConfig = (SrSectionConfig) headAxle.getRealDevice();
|
||||
//设置延时停车时间
|
||||
long m = 1000000000;
|
||||
long nanos;
|
||||
if (sectionConfig.getConfigVO().getHeadDelayTime() != null) {
|
||||
nanos = (long) (sectionConfig.getConfigVO().getHeadDelayTime() * m);
|
||||
config.setTimeOfStop(LocalDateTime.now().plusNanos(nanos));
|
||||
continue;
|
||||
}
|
||||
//以前一个区段无占用作为停车标志的区段
|
||||
boolean right = train.isRight();
|
||||
Section behindSection = headSection.getNextRunningSectionOf(!right);
|
||||
if (behindSection == null)
|
||||
continue;
|
||||
VirtualRealitySectionAxleCounter behindAxle = behindSection.findAxle();
|
||||
if (behindAxle == null)
|
||||
continue;
|
||||
if (!behindAxle.isOccupy()) { //车头后方区段所属计轴无占用状态
|
||||
nanos = 0;
|
||||
if (sectionConfig.getConfigVO().getTailDelayTime() != null) {
|
||||
nanos = (long) (sectionConfig.getConfigVO().getTailDelayTime() * m);
|
||||
}
|
||||
if (nanos == 0) {
|
||||
train.setHeadPosition(headSection.buildStopPointPosition(right));
|
||||
} else {
|
||||
config.setTimeOfStop(LocalDateTime.now().plusNanos(nanos));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTrainPosition(Simulation simulation, VirtualRealitySectionAxleCounter axle) {
|
||||
for (Section section : simulation.getRepository().getAxleSectionList()) {
|
||||
if (section.getVirtualAxleCounter().equals(axle)) {
|
||||
List<Section> pSection;
|
||||
if (section.isPhysical()) {
|
||||
pSection = Collections.singletonList(section);
|
||||
} else if (section.isSwitchAxleCounterSection()) {
|
||||
pSection = section.findConnectedSections();
|
||||
} else {
|
||||
pSection = Collections.emptyList();
|
||||
}
|
||||
for (Section sec : pSection) {
|
||||
check4UpdateHeadPosition(simulation, sec, false);
|
||||
check4UpdateHeadPosition(simulation, sec, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否有right向的列车可以更新车头位置
|
||||
*/
|
||||
private void check4UpdateHeadPosition(Simulation simulation, Section occupiedSection, boolean right) {
|
||||
Section section = occupiedSection.getNextRunningSectionOf(!right); //找反向的区段
|
||||
if (section != null) {
|
||||
for (VirtualRealityTrain train : simulation.getRepository().getOnlineTrainList()) {
|
||||
Section headSection = train.getHeadPosition().getSection();
|
||||
boolean trainRight = train.isRight();
|
||||
if (trainRight == right && section.equals(headSection)) { //列车到达occupiedSection
|
||||
//判断更新ITC ma
|
||||
if (headSection.getSignalOf(trainRight) != null) {
|
||||
maService.calculateAndUpdateItcMa(simulation, train);
|
||||
}
|
||||
//更新位置
|
||||
SectionPosition headPosition;
|
||||
SectionPosition stopPointPosition;
|
||||
if (occupiedSection.isFunctionTrack()) {
|
||||
stopPointPosition = occupiedSection.buildStopPointPosition(right);
|
||||
headPosition = CalculateService.calculateNextPositionByStartAndLen(stopPointPosition, !right, 1, true);
|
||||
} else {
|
||||
stopPointPosition = new SectionPosition(occupiedSection, occupiedSection.getEndOffsetByDirection(right));
|
||||
headPosition = CalculateService.calculateNextPositionByStartAndLen(stopPointPosition, !right, 3, true);
|
||||
}
|
||||
train.setHeadPosition(headPosition); //更新位置
|
||||
if (occupiedSection.isFunctionTrack()) { //功能轨可能需要停车
|
||||
SrTrainConfig config = (SrTrainConfig) train.getRealDevice();
|
||||
config.updateHeadSection(occupiedSection);
|
||||
}
|
||||
}
|
||||
}
|
||||
config.updateHeadSection(occupiedSection);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
package club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.config;
|
||||
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.device.RealDeviceConfig;
|
||||
import club.joylink.rtss.util.JsonUtils;
|
||||
import club.joylink.rtss.vo.client.project.ProjectDeviceVO;
|
||||
import club.joylink.rtss.vo.client.project.thailand.ThailandSectionConfigVO;
|
||||
import java.util.Objects;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
public class ThailandSectionConfig extends RealDeviceConfig {
|
||||
private ThailandSectionConfigVO configVO;
|
||||
|
||||
/**
|
||||
* 连续无占用次数
|
||||
*/
|
||||
@Setter
|
||||
private int timesOfRelease;
|
||||
|
||||
public ThailandSectionConfig(ProjectDeviceVO projectDevice) {
|
||||
super(projectDevice);
|
||||
if (Objects.nonNull(projectDevice.getConfig())) {
|
||||
this.configVO = JsonUtils.read(projectDevice.getConfig(), ThailandSectionConfigVO.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String findDeviceCode() {
|
||||
return configVO.findDeviceCode();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.config;
|
||||
|
||||
import club.joylink.rtss.simulation.cbtc.constant.SignalAspect;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.device.RealDeviceConfig;
|
||||
import club.joylink.rtss.util.JsonUtils;
|
||||
import club.joylink.rtss.vo.client.project.ProjectDeviceVO;
|
||||
import club.joylink.rtss.vo.client.project.thailand.ThailandSignalConfigVO;
|
||||
import java.util.Objects;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
public class ThailandSignalConfig extends RealDeviceConfig {
|
||||
private ThailandSignalConfigVO configVO;
|
||||
|
||||
@Setter
|
||||
private SignalAspect aspect;
|
||||
|
||||
public ThailandSignalConfig(ProjectDeviceVO projectDevice) {
|
||||
super(projectDevice);
|
||||
if (Objects.nonNull(projectDevice.getConfig())) {
|
||||
this.configVO = JsonUtils.read(projectDevice.getConfig(), ThailandSignalConfigVO.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String findDeviceCode() {
|
||||
return configVO.findDeviceCode();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.config;
|
||||
|
||||
import club.joylink.rtss.simulation.cbtc.constant.SwitchIndication;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.device.RealDeviceConfig;
|
||||
import club.joylink.rtss.util.JsonUtils;
|
||||
import club.joylink.rtss.vo.client.project.ProjectDeviceVO;
|
||||
import club.joylink.rtss.vo.client.project.thailand.ThailandSwitchConfigVO;
|
||||
import java.util.Objects;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
public class ThailandSwitchConfig extends RealDeviceConfig {
|
||||
private ThailandSwitchConfigVO configVO;
|
||||
|
||||
@Setter
|
||||
private SwitchIndication p;
|
||||
public ThailandSwitchConfig(ProjectDeviceVO projectDevice) {
|
||||
super(projectDevice);
|
||||
if (Objects.nonNull(projectDevice.getConfig())) {
|
||||
this.configVO = JsonUtils.read(projectDevice.getConfig(), ThailandSwitchConfigVO.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String findDeviceCode() {
|
||||
return configVO.findDeviceCode();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.config;
|
||||
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.Section;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.device.RealDeviceConfig;
|
||||
import club.joylink.rtss.util.JsonUtils;
|
||||
import club.joylink.rtss.vo.client.project.ProjectDeviceVO;
|
||||
import club.joylink.rtss.vo.client.project.thailand.ThailandTrainConfigVO;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Objects;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
public class ThailandTrainConfig extends RealDeviceConfig {
|
||||
|
||||
private ThailandTrainConfigVO configVO;
|
||||
|
||||
@Setter
|
||||
private Integer gear;
|
||||
|
||||
/**
|
||||
* 列车需要在这个轨道停车
|
||||
*/
|
||||
private Section headSection;
|
||||
|
||||
/**
|
||||
* 列车抵达停车点的时间。
|
||||
* <p>
|
||||
* 当走到这个时间时,需要将列车的车头位置更新至当前区段的停车点。
|
||||
* <p>
|
||||
* 上述停车点指代一切可能需要停车的位置,比如站台轨的停车点、信号机2m前、轨道尽头10m前。
|
||||
*/
|
||||
@Setter
|
||||
private LocalDateTime timeOfArriveStopPoint;
|
||||
|
||||
/**
|
||||
* 人为驾驶的档位
|
||||
*/
|
||||
@Setter
|
||||
private Integer manualGear;
|
||||
|
||||
public void updateHeadSection(Section headSection) {
|
||||
this.headSection = headSection;
|
||||
this.timeOfArriveStopPoint = null;
|
||||
}
|
||||
|
||||
public ThailandTrainConfig(ProjectDeviceVO projectDevice) {
|
||||
super(projectDevice);
|
||||
if (Objects.nonNull(projectDevice.getConfig())) {
|
||||
this.configVO = JsonUtils.read(projectDevice.getConfig(), ThailandTrainConfigVO.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String findDeviceCode() {
|
||||
return configVO.findDeviceCode();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
package club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.service;
|
||||
|
||||
import club.joylink.rtss.constants.ProjectCode;
|
||||
import club.joylink.rtss.constants.ProjectDeviceType;
|
||||
import club.joylink.rtss.simulation.cbtc.ATP.ground.MaService;
|
||||
import club.joylink.rtss.simulation.cbtc.Simulation;
|
||||
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealitySectionAxleCounter;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.device.RealDeviceConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPClientConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPLowConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPRealDeviceService;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.config.ThailandSectionConfig;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class ThailandSectionServiceImpl implements UDPRealDeviceService {
|
||||
|
||||
@Autowired
|
||||
private MaService maService;
|
||||
@Autowired
|
||||
private ThailandTrainServiceImpl thailandTrainService;
|
||||
|
||||
@Override
|
||||
public boolean isMatch(RealDeviceConfig realDevice) {
|
||||
return realDevice instanceof UDPClientConfig && ProjectCode.THAILAND_SANDBOX
|
||||
.equals(realDevice.getProject());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
|
||||
//沙盘不需要停太长时间
|
||||
simulation.getRepository().getStandList().forEach(stand -> stand.setParkingTime(15));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Simulation simulation, ByteBuf msg) {
|
||||
//检查数据
|
||||
byte[] data = new byte[msg.readableBytes()];
|
||||
if (data.length < 4) {
|
||||
return;
|
||||
}
|
||||
msg.readBytes(data);
|
||||
if (Byte.toUnsignedInt(data[1]) != 137) {
|
||||
return;
|
||||
}
|
||||
//处理数据
|
||||
Map<String, ThailandSectionConfig> configMap = simulation.queryAllRealDevice(
|
||||
ProjectDeviceType.SECTION).stream()
|
||||
.map(config -> (ThailandSectionConfig) config)
|
||||
.collect(
|
||||
Collectors.toMap(config -> config.getConfigVO().getSandboxCode(), Function.identity()));
|
||||
for (int i = 3, dataLength = data.length; i < dataLength; i += 2) {
|
||||
int code = Byte.toUnsignedInt(data[i - 1]);
|
||||
String key = String.valueOf(code);
|
||||
ThailandSectionConfig config = configMap.get(key);
|
||||
if (config == null) {
|
||||
continue;
|
||||
}
|
||||
VirtualRealitySectionAxleCounter axle = (VirtualRealitySectionAxleCounter) config.getMapElement();
|
||||
if (axle != null) {
|
||||
int n = Byte.toUnsignedInt(data[i]);
|
||||
if (n == 170) {
|
||||
config.setTimesOfRelease(0);
|
||||
axle.setOccupy(true);
|
||||
} else if (n == 85) {
|
||||
config.setTimesOfRelease(config.getTimesOfRelease() + 1);
|
||||
if (config.getTimesOfRelease() > 2) { //连续3次该计轴都是无占用状态,才视为确实无占用
|
||||
config.setTimesOfRelease(0);
|
||||
axle.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
package club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.service;
|
||||
|
||||
import club.joylink.rtss.simulation.cbtc.Simulation;
|
||||
import club.joylink.rtss.simulation.cbtc.constant.SignalAspect;
|
||||
import club.joylink.rtss.simulation.cbtc.constant.SimulationConstants;
|
||||
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealitySignal;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.device.RealDeviceConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPClient;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPLowConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPRealDeviceService;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.config.ThailandSignalConfig;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import java.util.Objects;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class ThailandSignalServiceImpl implements UDPRealDeviceService {
|
||||
public static final String NAME = "SIGNAL";
|
||||
|
||||
@Autowired
|
||||
private UDPClient udpClient;
|
||||
|
||||
@Override
|
||||
public boolean isMatch(UDPLowConfig udpLowConfig) {
|
||||
return NAME.equals(udpLowConfig.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMatch(RealDeviceConfig realDevice) {
|
||||
return realDevice instanceof ThailandSignalConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
|
||||
ThailandSignalConfig config = (ThailandSignalConfig) realDevice;
|
||||
//控制vr设备
|
||||
VirtualRealitySignal vrSignal = (VirtualRealitySignal) realDevice.getMapElement();
|
||||
SignalAspect aspect = vrSignal.getAspect();
|
||||
SignalAspect command = vrSignal.getCommand();
|
||||
if (Objects.equals(aspect, command)) {
|
||||
return;
|
||||
}
|
||||
if (vrSignal.isTurning()) {
|
||||
vrSignal.turning(SimulationConstants.VRD_LOOP_RATE);
|
||||
}
|
||||
//控制沙盘设备
|
||||
aspect = vrSignal.getAspect();
|
||||
if (aspect == null || udpLowConfig == null || Objects.equals(aspect, config.getAspect())) {
|
||||
return;
|
||||
}
|
||||
byte[] data = buildData(aspect, config);
|
||||
if (data == null)
|
||||
return;
|
||||
udpClient.write(udpLowConfig.getAddr(), data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Simulation simulation, ByteBuf msg) {
|
||||
|
||||
}
|
||||
|
||||
private byte[] buildData(SignalAspect aspect, ThailandSignalConfig config) {
|
||||
if (aspect == null)
|
||||
return null;
|
||||
config.setAspect(aspect);
|
||||
byte[] data = new byte[5];
|
||||
data[1] = (byte) 203;
|
||||
data[2] = (byte) Integer.parseInt(config.getConfigVO().getSandboxCode());
|
||||
switch (aspect) {
|
||||
case No:
|
||||
case R:
|
||||
case RF:
|
||||
data[3] = (byte) 0;
|
||||
break;
|
||||
case G:
|
||||
case GF:
|
||||
data[3] = (byte) 1;
|
||||
break;
|
||||
case Y:
|
||||
case YF:
|
||||
data[3] = (byte) 2;
|
||||
break;
|
||||
case W:
|
||||
case WF:
|
||||
data[3] = (byte) 6;
|
||||
break;
|
||||
case B:
|
||||
data[3] = (byte) 7;
|
||||
break;
|
||||
case GG:
|
||||
data[3] = (byte) 5;
|
||||
break;
|
||||
case GY:
|
||||
data[3] = (byte) 4;
|
||||
break;
|
||||
case YY:
|
||||
data[3] = (byte) 3;
|
||||
break;
|
||||
case RY:
|
||||
case RW:
|
||||
return null;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
switch (aspect) {
|
||||
case No:
|
||||
case R:
|
||||
case G:
|
||||
case Y:
|
||||
case W:
|
||||
case B:
|
||||
case RY:
|
||||
case RW:
|
||||
case GG:
|
||||
case GY:
|
||||
case YY:
|
||||
data[4] = (byte) 0;
|
||||
break;
|
||||
case RF:
|
||||
case YF:
|
||||
case GF:
|
||||
case WF:
|
||||
data[4] = (byte) 1;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unexpected value: " + aspect);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
package club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.service;
|
||||
|
||||
import club.joylink.rtss.simulation.cbtc.Simulation;
|
||||
import club.joylink.rtss.simulation.cbtc.constant.SimulationConstants;
|
||||
import club.joylink.rtss.simulation.cbtc.constant.SwitchIndication;
|
||||
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealitySwitch;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.device.RealDeviceConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPClient;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPLowConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPRealDeviceService;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.config.ThailandSwitchConfig;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import java.util.Objects;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class ThailandSwitchServiceImpl implements UDPRealDeviceService {
|
||||
public static final String NAME = "SWITCH-TRAIN";
|
||||
|
||||
@Autowired
|
||||
private UDPClient udpClient;
|
||||
|
||||
@Override
|
||||
public boolean isMatch(UDPLowConfig udpLowConfig) {
|
||||
return NAME.equals(udpLowConfig.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMatch(RealDeviceConfig realDevice) {
|
||||
return realDevice instanceof ThailandSwitchConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
|
||||
ThailandSwitchConfig config = (ThailandSwitchConfig) realDevice;
|
||||
//控制vr设备
|
||||
VirtualRealitySwitch vrSwitch = (VirtualRealitySwitch) realDevice.getMapElement();
|
||||
if (vrSwitch.isTurning()) {
|
||||
vrSwitch.turning(SimulationConstants.VRD_LOOP_RATE);
|
||||
}
|
||||
//控制沙盘设备
|
||||
SwitchIndication p = vrSwitch.getP();
|
||||
if (p == null || udpLowConfig == null || Objects.equals(p, config.getP())) {
|
||||
return;
|
||||
}
|
||||
byte[] data = buildData(p, config);
|
||||
if (data == null)
|
||||
return;
|
||||
udpClient.write(udpLowConfig.getAddr(), data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Simulation simulation, ByteBuf msg) {
|
||||
|
||||
}
|
||||
|
||||
private byte[] buildData(SwitchIndication p, ThailandSwitchConfig config) {
|
||||
if (p == null)
|
||||
return null;
|
||||
config.setP(p);
|
||||
byte[] data = new byte[4];
|
||||
data[1] = (byte) 208;
|
||||
data[2] = (byte) Integer.parseInt(config.getConfigVO().getSandboxCode());
|
||||
switch (p) {
|
||||
case N:
|
||||
data[3] = (byte) 0;
|
||||
break;
|
||||
case R:
|
||||
data[3] = (byte) 1;
|
||||
break;
|
||||
case NO:
|
||||
case EX:
|
||||
return null;
|
||||
default:
|
||||
throw new IllegalStateException("Unexpected value: " + p);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,373 @@
|
|||
package club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.service;
|
||||
|
||||
import club.joylink.rtss.constants.ProjectDeviceType;
|
||||
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
|
||||
import club.joylink.rtss.simulation.cbtc.ATS.service.AtsTrainLoadService;
|
||||
import club.joylink.rtss.simulation.cbtc.GroupSimulationService;
|
||||
import club.joylink.rtss.simulation.cbtc.Simulation;
|
||||
import club.joylink.rtss.simulation.cbtc.constant.SimulationConstants;
|
||||
import club.joylink.rtss.simulation.cbtc.data.CalculateService;
|
||||
import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository;
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.Section;
|
||||
import club.joylink.rtss.simulation.cbtc.data.support.SectionPosition;
|
||||
import club.joylink.rtss.simulation.cbtc.data.vo.TrainInfo;
|
||||
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealitySectionAxleCounter;
|
||||
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.device.RealDeviceConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPClient;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPLowConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPRealDeviceService;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.config.ThailandSectionConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.config.ThailandTrainConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.onboard.ATP.ATPService;
|
||||
import club.joylink.rtss.simulation.cbtc.robot.SimulationRobotService;
|
||||
import club.joylink.rtss.vo.client.project.thailand.ThailandSectionConfigVO;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class ThailandTrainServiceImpl implements UDPRealDeviceService {
|
||||
|
||||
public static final String NAME = ThailandSwitchServiceImpl.NAME;
|
||||
|
||||
@Autowired
|
||||
private UDPClient udpClient;
|
||||
@Autowired
|
||||
private ATPService atpService;
|
||||
@Autowired
|
||||
private GroupSimulationService groupSimulationService;
|
||||
@Autowired
|
||||
private AtsTrainLoadService atsTrainLoadService;
|
||||
@Autowired
|
||||
private SimulationRobotService simulationRobotService;
|
||||
|
||||
@Override
|
||||
public boolean isMatch(UDPLowConfig udpLowConfig) {
|
||||
return NAME.equals(udpLowConfig.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMatch(RealDeviceConfig realDevice) {
|
||||
return realDevice instanceof ThailandTrainConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
|
||||
ThailandTrainConfig config = (ThailandTrainConfig) realDevice;
|
||||
//控制vr设备
|
||||
VirtualRealityTrain train = (VirtualRealityTrain) config.getMapElement();
|
||||
SimulationDataRepository repository = simulation.getRepository();
|
||||
String groupNumber = train.getGroupNumber();
|
||||
if (repository.isVrTrainOnline(groupNumber)) {
|
||||
removeVrTrainIfNotSupervised(repository, groupNumber);
|
||||
if (!train.isRobotStopControl() && config.getManualGear() != null) {
|
||||
config.setManualGear(null);
|
||||
config.setGear(null);
|
||||
}
|
||||
updateTrainPositionAndSpeed(simulation, train, config);
|
||||
//减少关门后的延迟发车时间
|
||||
if (train.getDelayTime() > 3000) {
|
||||
train.setDelayTime(3000);
|
||||
}
|
||||
//控制沙盘设备
|
||||
byte[] data = buildData(train, config);
|
||||
udpClient.write(udpLowConfig.getAddr(), data);
|
||||
} else {
|
||||
addVrTrainIfSupervised(simulation, repository, groupNumber);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新列车位置。
|
||||
* <p>
|
||||
* 1.如果列车占压新的区段,则先将列车车头位置更新至该区段的停车点之前(保证列车可以继续运行)。 2.根据区段的配置信息,决定列车何时将车头位置更新至停车点
|
||||
* 3.根据上一步设置的停车时间,判断执行更新车头位置至停车点逻辑(触发列车停车逻辑)
|
||||
*/
|
||||
private void updateTrainPositionAndSpeed(Simulation simulation, VirtualRealityTrain train,
|
||||
ThailandTrainConfig config) {
|
||||
//判断列车是否到达新区段
|
||||
boolean right = train.isRight(); //车头方向
|
||||
Section headSection = train.getHeadPosition().getSection(); //车头区段
|
||||
Section previousSection = null; //车头方向的上一个区段
|
||||
Section nextSection = headSection.getNextRunningSectionOf(right); //车头方向的下一个区段
|
||||
ThailandSectionConfig sectionConfig = (ThailandSectionConfig) headSection.findAxle()
|
||||
.getRealDevice(); //车头区段的配置
|
||||
if (nextSection != null) {
|
||||
VirtualRealitySectionAxleCounter nextAxle = nextSection.findAxle();
|
||||
if (nextAxle.isOccupy()) {
|
||||
train.setHeadPosition(
|
||||
new SectionPosition(nextSection, right ? 0 : nextSection.getMaxOffset()));
|
||||
config.setTimeOfArriveStopPoint(null);
|
||||
sectionConfig = (ThailandSectionConfig) nextAxle.getRealDevice();
|
||||
//更新变量
|
||||
previousSection = headSection;
|
||||
headSection = train.getHeadPosition().getSection();
|
||||
nextSection = null;
|
||||
}
|
||||
}
|
||||
//根据区段的配置信息,设置车头位置更新至停车点的时间
|
||||
// fill(headSection, sectionConfig.getConfigVO());
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
if (config.getTimeOfArriveStopPoint() == null) {
|
||||
int rate = 1000000000; //秒到纳秒的换算比例
|
||||
Long delayOfNano = null; //延迟时间的纳秒表示
|
||||
if (sectionConfig.getConfigVO().getHeadDelayTime() != null) { //车头占压延时停车
|
||||
delayOfNano = (long) (sectionConfig.getConfigVO().getHeadDelayTime() * rate);
|
||||
} else if (sectionConfig.getConfigVO().getTailDelayTime() != null) { //车尾出清延时停车
|
||||
if (previousSection == null) {
|
||||
previousSection = headSection.getNextRunningSectionOf(!right);
|
||||
}
|
||||
if (previousSection != null && !previousSection.isOccupied()) {
|
||||
delayOfNano = (long) (sectionConfig.getConfigVO().getTailDelayTime() * rate);
|
||||
}
|
||||
} else { //未设置则认为车头占压即刻停车
|
||||
delayOfNano = 0L;
|
||||
}
|
||||
if (delayOfNano != null) {
|
||||
config.setTimeOfArriveStopPoint(now.plusNanos(delayOfNano));
|
||||
}
|
||||
}
|
||||
//根据当前时间,判断更新车头位置至停车点
|
||||
LocalDateTime timeOfArriveStopPoint = config.getTimeOfArriveStopPoint();
|
||||
Optional<SectionPosition> stopPositionOptional = simulationRobotService.calculateTargetPosition(
|
||||
simulation, train);
|
||||
SectionPosition stopPosition = stopPositionOptional.orElse(null);
|
||||
if (timeOfArriveStopPoint != null && !now.isBefore(timeOfArriveStopPoint)) {
|
||||
if (stopPosition != null && stopPosition.getSection().equals(headSection)) {
|
||||
train.setHeadPosition(stopPosition);
|
||||
} else {
|
||||
float offset = right ? headSection.getMaxOffset() : 0;
|
||||
train.setHeadPosition(new SectionPosition(headSection, offset));
|
||||
}
|
||||
}
|
||||
//更新速度。由于沙盘对延时要求很高,机器人驾驶逻辑频率有点低,所以选择不利用机器人驾驶的逻辑
|
||||
if (config.getManualGear() != null) {
|
||||
return;
|
||||
}
|
||||
if (stopPosition != null) {
|
||||
Float distance = CalculateService.calculateDistance(train.getHeadPosition(), stopPosition,
|
||||
right, false);
|
||||
if (distance == null || distance <= SimulationConstants.PARK_POINT_MAX_OFFSET) {
|
||||
train.setSpeed(0);
|
||||
return;
|
||||
}
|
||||
float highSpeed = 20 / 3.6f;
|
||||
float lowSpeed = 10 / 3.6f;
|
||||
if (headSection.isStandTrack()) {
|
||||
train.setSpeed(lowSpeed);
|
||||
return;
|
||||
}
|
||||
if (stopPosition.getSection().isStandTrack()) {
|
||||
Section stopPreviousSection = stopPosition.getSection().getNextRunningSectionOf(!right);
|
||||
if (stopPreviousSection != null && Objects.equals(stopPreviousSection.findAxle(),
|
||||
headSection.findAxle())) { //当前车头在站台轨的前一个计轴区段
|
||||
train.setSpeed(lowSpeed);
|
||||
return;
|
||||
}
|
||||
}
|
||||
train.setSpeed(highSpeed);
|
||||
} else {
|
||||
train.setSpeed(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果有监控,添加一个vrTrain
|
||||
*/
|
||||
private void addVrTrainIfSupervised(Simulation simulation, SimulationDataRepository repository,
|
||||
String groupNumber) {
|
||||
TrainInfo trainInfo = repository.findSupervisedTrainByGroup(groupNumber);
|
||||
if (trainInfo != null) {
|
||||
Section section = repository.getByCode(trainInfo.getSection(), Section.class);
|
||||
if (section.isSwitchAxleCounterSection()) {
|
||||
section = section.getLogicList().get(0).getRelSwitch().getA();
|
||||
}
|
||||
atsTrainLoadService.loadSpareTrain(simulation, groupNumber, section.getCode(), false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除vrTrain,如果没有被监控
|
||||
*/
|
||||
private void removeVrTrainIfNotSupervised(SimulationDataRepository repository,
|
||||
String groupNumber) {
|
||||
TrainInfo trainInfo = repository.findSupervisedTrainByGroup(groupNumber);
|
||||
if (trainInfo == null) {
|
||||
repository.deleteOnlineTrain(groupNumber);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Simulation simulation, UDPLowConfig udpLowConfig, RealDeviceConfig realDevice) {
|
||||
ThailandTrainConfig config = (ThailandTrainConfig) realDevice;
|
||||
//控制vr设备
|
||||
VirtualRealityTrain train = (VirtualRealityTrain) config.getMapElement();
|
||||
//控制沙盘设备
|
||||
byte[] data = buildData(train, config);
|
||||
udpClient.write(udpLowConfig.getAddr(), data);
|
||||
//清除状态
|
||||
config.updateHeadSection(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Simulation simulation, ByteBuf msg) {
|
||||
|
||||
}
|
||||
|
||||
private byte[] buildData(VirtualRealityTrain train, ThailandTrainConfig config) {
|
||||
int gear;
|
||||
if (train.isStop()) {
|
||||
gear = 0;
|
||||
} else {
|
||||
float speedKmPh = train.getSpeedKmPh();
|
||||
if (train.isStop()) {
|
||||
gear = 0;
|
||||
} else {
|
||||
gear = (int) Math.ceil(speedKmPh / 10);
|
||||
gear = Math.max(1, gear);
|
||||
}
|
||||
if (train.isRight()) { //档位1-5是正向,6-10是反向
|
||||
gear += 5;
|
||||
}
|
||||
}
|
||||
if (Objects.equals(config.getGear(), gear)) {
|
||||
return null;
|
||||
}
|
||||
config.setGear(gear);
|
||||
byte[] data = new byte[4];
|
||||
data[1] = (byte) 1;
|
||||
data[2] = (byte) Integer.parseInt(config.getConfigVO().getSandboxCode());
|
||||
data[3] = (byte) gear;
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 此方法用于调试,调试完成后方法内的数据请保存到项目设备配置
|
||||
*/
|
||||
public void fill(Section section, ThailandSectionConfigVO configVO) {
|
||||
Float headDelayTime = null;
|
||||
Float tailDelayTime = null;
|
||||
if (section.isStandTrack()) { //站台轨默认为车尾出清立即停车
|
||||
headDelayTime = 5f;
|
||||
}
|
||||
switch (section.getCode()) {
|
||||
case "T233": //X302G
|
||||
headDelayTime = 7.3f;
|
||||
break;
|
||||
case "T232": //X303G
|
||||
headDelayTime = 6.5f;
|
||||
break;
|
||||
case "T231": //X304G
|
||||
headDelayTime = 5.5f;
|
||||
break;
|
||||
case "T178": //4站-3G
|
||||
headDelayTime = 5.2f;
|
||||
break;
|
||||
case "T177": //4站-IG
|
||||
headDelayTime = 5.4f;
|
||||
break;
|
||||
case "T175": //4站-IIG
|
||||
headDelayTime = 6.6f;
|
||||
break;
|
||||
case "T174": //4站-4G
|
||||
headDelayTime = 6.2f;
|
||||
break;
|
||||
case "T176": //4站-6G
|
||||
headDelayTime = 5.9f;
|
||||
break;
|
||||
case "T179": //4站-5G
|
||||
headDelayTime = 6.5f;
|
||||
break;
|
||||
case "T123": //3站-3G
|
||||
headDelayTime = 5.2f;
|
||||
break;
|
||||
case "T122": //3站-IG
|
||||
headDelayTime = 5.3f;
|
||||
break;
|
||||
case "T121": //3站-IIG
|
||||
headDelayTime = 5.9f;
|
||||
break;
|
||||
case "T120": //3站-4G
|
||||
headDelayTime = 5.5f;
|
||||
break;
|
||||
case "T78": //2站-IG
|
||||
headDelayTime = 5.5f;
|
||||
break;
|
||||
case "T77": //2站-IIG
|
||||
headDelayTime = 5.9f;
|
||||
break;
|
||||
case "T76": //2站-4G
|
||||
headDelayTime = 5.7f;
|
||||
break;
|
||||
case "T22": //1站-1G
|
||||
headDelayTime = 5.3f;
|
||||
break;
|
||||
case "T23": //1站-IIG
|
||||
headDelayTime = 5.1f;
|
||||
break;
|
||||
case "T27": //1站-5G
|
||||
headDelayTime = 4.9f;
|
||||
break;
|
||||
case "T26": //1站-3G
|
||||
headDelayTime = 4.8f;
|
||||
break;
|
||||
case "T24": //1站-4G
|
||||
headDelayTime = 5.1f;
|
||||
break;
|
||||
case "T25": //1站-6G
|
||||
headDelayTime = 5.1f;
|
||||
break;
|
||||
case "T145": //QX04
|
||||
headDelayTime = 1.9f;
|
||||
break;
|
||||
case "T146": //QS04
|
||||
headDelayTime = 2.7f;
|
||||
break;
|
||||
case "T104": //QX03
|
||||
tailDelayTime = 0f;
|
||||
break;
|
||||
case "T105": //QS03
|
||||
tailDelayTime = 0f;
|
||||
break;
|
||||
case "T62": //QX02
|
||||
tailDelayTime = 0f;
|
||||
break;
|
||||
case "T63": //QS02
|
||||
tailDelayTime = 0f;
|
||||
break;
|
||||
}
|
||||
configVO.setHeadDelayTime(headDelayTime);
|
||||
configVO.setTailDelayTime(tailDelayTime);
|
||||
}
|
||||
|
||||
public void controlTrain(String simulationId, String groupNumber, boolean right, int speed) {
|
||||
Simulation simulation = groupSimulationService.getSimulationByGroup(simulationId);
|
||||
VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber);
|
||||
ThailandTrainConfig config = (ThailandTrainConfig) train.getRealDevice();
|
||||
if (right != train.isRight()) { //调头
|
||||
BusinessExceptionAssertEnum.OPERATION_NOT_SUPPORTED
|
||||
.assertTrue(train.getSpeed() == 0, "换端需先停车");
|
||||
atpService.turnDirectionImmediately(train);
|
||||
}
|
||||
train.setRobotTargetPosition(null); //终止机器人司机驾驶
|
||||
//加减速
|
||||
if (train.isEB()) {
|
||||
return;
|
||||
}
|
||||
atpService.changeGear(train, VirtualRealityTrain.Handwheel.MANUAL);
|
||||
int manualGear = speed / 10;
|
||||
config.setManualGear(manualGear);
|
||||
train.setSpeed(speed / 3.6f);
|
||||
train.getRobotDriveParam().stopControl();
|
||||
byte[] data = buildData(train, config);
|
||||
UDPLowConfig udpLowConfig = (UDPLowConfig) simulation.queryOneRealDevice(
|
||||
ProjectDeviceType.UDP_LOW);
|
||||
udpClient.write(udpLowConfig.getAddr(), data);
|
||||
}
|
||||
}
|
|
@ -9,14 +9,18 @@ import club.joylink.rtss.simulation.cbtc.data.support.SectionPosition;
|
|||
import club.joylink.rtss.simulation.cbtc.data.vr.VirtualRealityTrain;
|
||||
import club.joylink.rtss.simulation.cbtc.exception.SimulationException;
|
||||
import club.joylink.rtss.simulation.cbtc.exception.SimulationExceptionType;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 目标速度-距离曲线
|
||||
*/
|
||||
|
@ -315,75 +319,6 @@ public class SpeedCurve {
|
|||
return speedCurve;
|
||||
}
|
||||
|
||||
// public static SpeedCurve buildTargetSpeedCurve(SectionPosition headPosition,
|
||||
// SectionPosition tailPosition, boolean right,
|
||||
// float totalLen, float v0, float recommendedSpeedMax) {
|
||||
// if (totalLen <= 0) {
|
||||
// return SpeedCurve.ZERO;
|
||||
// }
|
||||
// Section base = tailPosition.getSection();
|
||||
// Section headSection = headPosition.getSection();
|
||||
// float limitSpeed = recommendedSpeedMax;
|
||||
// boolean limit = false;
|
||||
// if (Objects.nonNull(tailPosition.getSection().getNeedLimitSpeed())) {
|
||||
// limitSpeed = Math.min(limitSpeed, tailPosition.getSection().getNeedLimitSpeed() * 0.9f);
|
||||
// limit = true;
|
||||
// } else if (Objects.nonNull(headPosition.getSection().getNeedLimitSpeed())) {
|
||||
// limitSpeed = Math.min(limitSpeed, headPosition.getSection().getNeedLimitSpeed() * 0.9f);
|
||||
// limit = true;
|
||||
// }
|
||||
// SectionPosition endPosition = null;
|
||||
// boolean ahead = false;
|
||||
// float vt = 0;
|
||||
// int count = 0;
|
||||
// if (!limit) {
|
||||
// // 无限速,找前方限速
|
||||
// while (Objects.nonNull(base) && count < 20) {
|
||||
// ++count;
|
||||
// Float limitSpeed1 = base.getNeedLimitSpeed();
|
||||
// if (limitSpeed1 == null && !CollectionUtils.isEmpty(base.getLogicList())) { //兼容逻辑区段设置限速
|
||||
// float distanceBetweenLogicAndPhysical = 0; //逻辑区段距物理区段端点的距离(同向端点)
|
||||
// for (Section section : base.getLogicList()) {
|
||||
// limitSpeed1 = section.getNeedLimitSpeed();
|
||||
// if (limitSpeed1 != null) {
|
||||
// float offsetOfLogicSectionOnPhysicalSection = distanceBetweenLogicAndPhysical + (right ? section.getLen() : 0); //逻辑区段的端点在物理区段上的偏移量
|
||||
// SectionPosition logicSectionPosition = new SectionPosition(base, offsetOfLogicSectionOnPhysicalSection);
|
||||
// if (logicSectionPosition.isAheadOf(tailPosition, right)) {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// distanceBetweenLogicAndPhysical += section.getLen();
|
||||
// }
|
||||
// }
|
||||
// if (Objects.nonNull(limitSpeed1)) {
|
||||
// if (ahead) {
|
||||
// // 车头前方
|
||||
// vt = Math.min(limitSpeed, limitSpeed1 * 0.9f);
|
||||
// endPosition = new SectionPosition(base, right ? 0 : base.getLen());
|
||||
// break;
|
||||
// } else {
|
||||
// limitSpeed = Math.min(limitSpeed, limitSpeed1 * 0.9f);
|
||||
// }
|
||||
// }
|
||||
// if (Objects.equals(base, headSection)) {
|
||||
// ahead = true;
|
||||
// }
|
||||
// base = base.getNextRunningSectionOf(right);
|
||||
// }
|
||||
// }
|
||||
// SpeedCurve normalSpeedCurve = buildTargetSpeedCurve(totalLen, v0, 0, limitSpeed);
|
||||
// if (endPosition != null) {
|
||||
// Float distance = CalculateService.calculateDistance(headPosition, endPosition, right);
|
||||
// if (distance != null && distance < totalLen) {
|
||||
// SpeedCurve limitSpeedCurve = buildTargetSpeedCurve(distance, v0, vt, limitSpeed);
|
||||
// float normalStartSpeed = normalSpeedCurve.getSpeedOf(normalSpeedCurve.getTotalDistance());
|
||||
// float limitStartSpeed = limitSpeedCurve.getSpeedOf(limitSpeedCurve.getTotalDistance());
|
||||
// return normalStartSpeed < limitStartSpeed ? normalSpeedCurve : limitSpeedCurve;
|
||||
// }
|
||||
// }
|
||||
// return normalSpeedCurve;
|
||||
// }
|
||||
|
||||
/**
|
||||
* 构建目标速度曲线
|
||||
*
|
||||
|
|
|
@ -552,11 +552,11 @@ public class ATPService {
|
|||
public void inbound(Simulation simulation, String groupNumber) {
|
||||
VirtualRealityTrain train = simulation.getRepository().getOnlineTrainBy(groupNumber);
|
||||
Section headSection = train.getHeadPosition().getSection();
|
||||
if (headSection.isTurnBackTrack() && train.isStop()) { //列车停在折返轨
|
||||
if (headSection.isTransferTrack() && train.isStop()) { //列车停在转换轨
|
||||
SimulationDataRepository repository = simulation.getRepository();
|
||||
TrainInfo trainInfo = repository.getSupervisedTrainByGroup(train.getGroupNumber());
|
||||
List<RoutePath> routePathList = repository.queryRoutePathsByEnd(headSection);
|
||||
if (routePathList.get(0).isRight() == trainInfo.getRight()) { //准备回库
|
||||
if (routePathList.stream().anyMatch(routePath -> routePath.isRight() == trainInfo.getRight())) { //准备回库
|
||||
trainInfo.finishPlanPrepareInbound();
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,9 +1,12 @@
|
|||
package club.joylink.rtss.simulation.cbtc.work;
|
||||
|
||||
import club.joylink.rtss.constants.ProjectDeviceType;
|
||||
import club.joylink.rtss.entity.Ibp;
|
||||
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
|
||||
import club.joylink.rtss.services.*;
|
||||
import club.joylink.rtss.services.ICommandService;
|
||||
import club.joylink.rtss.services.ILoadPlanService;
|
||||
import club.joylink.rtss.services.IMapService;
|
||||
import club.joylink.rtss.services.IRunPlanTemplateService;
|
||||
import club.joylink.rtss.services.IVirtualRealityIbpService;
|
||||
import club.joylink.rtss.services.iscs.IscsDeviceService;
|
||||
import club.joylink.rtss.services.iscs.IscsSystemResourcesService;
|
||||
import club.joylink.rtss.services.project.DeviceService;
|
||||
|
@ -15,12 +18,16 @@ import club.joylink.rtss.services.simulation.SchedulingService;
|
|||
import club.joylink.rtss.services.training.ITrainingV1Service;
|
||||
import club.joylink.rtss.simulation.cbtc.ATS.ATSLogicLoop;
|
||||
import club.joylink.rtss.simulation.cbtc.ATS.ATSMessageCollectAndDispatcher;
|
||||
import club.joylink.rtss.simulation.cbtc.ATS.service.alarm.NccAlarmService;
|
||||
import club.joylink.rtss.simulation.cbtc.ATS.ATSTrainMessageDiagram;
|
||||
import club.joylink.rtss.simulation.cbtc.ATS.service.alarm.NccAlarmService;
|
||||
import club.joylink.rtss.simulation.cbtc.CI.CiLogic;
|
||||
import club.joylink.rtss.simulation.cbtc.*;
|
||||
import club.joylink.rtss.simulation.cbtc.DeviceStatusService;
|
||||
import club.joylink.rtss.simulation.cbtc.GroupSimulationService;
|
||||
import club.joylink.rtss.simulation.cbtc.ISCS.IscsLogicLoop;
|
||||
import club.joylink.rtss.simulation.cbtc.ISCS.IscsMessageCollectAndDispatcher;
|
||||
import club.joylink.rtss.simulation.cbtc.PowerSupplyService;
|
||||
import club.joylink.rtss.simulation.cbtc.Simulation;
|
||||
import club.joylink.rtss.simulation.cbtc.SimulationLifeCycleService;
|
||||
import club.joylink.rtss.simulation.cbtc.build.SimulationBuildParams;
|
||||
import club.joylink.rtss.simulation.cbtc.build.SimulationBuilder;
|
||||
import club.joylink.rtss.simulation.cbtc.build.UserConfigDataBuilder;
|
||||
|
@ -28,7 +35,6 @@ import club.joylink.rtss.simulation.cbtc.communication.Joylink3DMessageService;
|
|||
import club.joylink.rtss.simulation.cbtc.constant.SimulationConstants;
|
||||
import club.joylink.rtss.simulation.cbtc.depot.DepotService;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.SimulationRealDeviceThread;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.device.RealDeviceConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPRealDeviceThread;
|
||||
import club.joylink.rtss.simulation.cbtc.device.virtual.VRDeviceLogicLoop;
|
||||
import club.joylink.rtss.simulation.cbtc.device.virtual.VRTrainRunningService;
|
||||
|
@ -48,7 +54,6 @@ import club.joylink.rtss.vo.client.CommandDefinitionVO;
|
|||
import club.joylink.rtss.vo.client.iscs.device.IscsDeviceVO;
|
||||
import club.joylink.rtss.vo.client.iscs.systemRes.IscsSystemResourcesQueryVO;
|
||||
import club.joylink.rtss.vo.client.iscs.systemRes.IscsSystemResourcesVO;
|
||||
import club.joylink.rtss.vo.client.project.ProjectDeviceVO;
|
||||
import club.joylink.rtss.vo.client.runplan.RunPlanLoadVO;
|
||||
import club.joylink.rtss.vo.client.runplan.RunPlanVO;
|
||||
import club.joylink.rtss.vo.client.runplan.user.RunPlanParkingTimeVO;
|
||||
|
@ -56,18 +61,16 @@ import club.joylink.rtss.vo.client.runplan.user.RunPlanRunlevelVO;
|
|||
import club.joylink.rtss.vo.client.schedulingNew.SchedulingPlanNewVO;
|
||||
import club.joylink.rtss.vo.client.simulationv1.RunAsPlanParam;
|
||||
import club.joylink.rtss.vo.map.MapVO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
|
@ -190,12 +193,7 @@ public class MetroSimulationWorkServiceImpl implements SimulationWorkService {
|
|||
simulationWorkServiceManager.buildMember(simulation);
|
||||
// 添加项目设备
|
||||
if (buildParams.getWorkParamVO().containsRealDeviceItem()) {
|
||||
List<ProjectDeviceVO> projectDeviceList = this.deviceService
|
||||
.queryDetailByTypes(ProjectDeviceType.PlcDeviceList(), buildParams.getMap().getProjectCode());
|
||||
List<RealDeviceConfig> realDeviceList = ProjectDeviceVO.convert2RealDeviceList(projectDeviceList);
|
||||
log.info(String.format("load project device list: [%s]",
|
||||
realDeviceList.stream().map(Object::toString).collect(Collectors.joining(","))));
|
||||
this.loadRealDevices(simulation, realDeviceList);
|
||||
simulationWorkServiceManager.loadRealDevices(simulation);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -491,29 +489,4 @@ public class MetroSimulationWorkServiceImpl implements SimulationWorkService {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void loadRealDevices(Simulation simulation, List<RealDeviceConfig> realDeviceList) {
|
||||
try {
|
||||
simulation.setRealDeviceList(realDeviceList);
|
||||
if (!CollectionUtils.isEmpty(realDeviceList)) {
|
||||
simulationRealDeviceThread.addJobs(simulation);
|
||||
udpRealDeviceThread.addJobs(simulation);
|
||||
}
|
||||
for (RealDeviceConfig realDevice : realDeviceList) {
|
||||
if (ProjectDeviceType.PLC_GATEWAY.equals(realDevice.getDeviceType())) {
|
||||
continue;
|
||||
}
|
||||
String deviceCode = realDevice.findDeviceCode();
|
||||
if (Objects.nonNull(deviceCode)) {
|
||||
this.groupSimulationService.connectDevice(simulation.getId(),
|
||||
deviceCode, realDevice.getProjectDevice().getId());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("仿真加载真实设备异常", e);
|
||||
// 清理仿真
|
||||
this.groupSimulationService.clearSimulation(simulation.getId(), simulation.getCreator());
|
||||
throw BusinessExceptionAssertEnum.TRAINING_ROOM_SIMULATION_LOAD_DEVICE_ERROR.exception(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,17 +33,16 @@ import club.joylink.rtss.vo.map.MapGraphDataNewVO;
|
|||
import club.joylink.rtss.vo.map.MapLogicDataNewVO;
|
||||
import club.joylink.rtss.vo.map.MapVO;
|
||||
import club.joylink.rtss.websocket.StompMessageService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
|
@ -101,16 +100,20 @@ public class RailwaySimulationWorkServiceImpl implements SimulationWorkService {
|
|||
|
||||
@Override
|
||||
public void loadData(Simulation simulation) {
|
||||
SimulationBuildParams params = simulation.getBuildParams();
|
||||
SimulationBuildParams buildParams = simulation.getBuildParams();
|
||||
// 加载地图数据
|
||||
loadMapData(simulation);
|
||||
// // 车辆段
|
||||
// depotService.loadDepotTrain(simulation);
|
||||
// 添加仿真用户
|
||||
SimulationUser creator = SimulationUser.buildCreator(simulation, params.getLoginUserInfo());
|
||||
SimulationUser creator = SimulationUser.buildCreator(simulation, buildParams.getLoginUserInfo());
|
||||
simulation.addSimulationUser(creator);
|
||||
// 添加仿真成员
|
||||
simulationWorkServiceManager.buildMember(simulation);
|
||||
// 添加项目设备
|
||||
if (buildParams.getWorkParamVO().containsRealDeviceItem()) {
|
||||
simulationWorkServiceManager.loadRealDevices(simulation);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,13 +1,26 @@
|
|||
package club.joylink.rtss.simulation.cbtc.work;
|
||||
|
||||
import club.joylink.rtss.constants.ProjectDeviceType;
|
||||
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
|
||||
import club.joylink.rtss.services.project.DeviceService;
|
||||
import club.joylink.rtss.simulation.cbtc.GroupSimulationService;
|
||||
import club.joylink.rtss.simulation.cbtc.Simulation;
|
||||
import club.joylink.rtss.simulation.cbtc.build.SimulationBuildParams;
|
||||
import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository;
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.MapElement;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.SimulationRealDeviceThread;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.device.RealDeviceConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.UDPRealDeviceThread;
|
||||
import club.joylink.rtss.simulation.cbtc.event.SimulationUserEnterEvent;
|
||||
import club.joylink.rtss.simulation.cbtc.member.MemberManager;
|
||||
import club.joylink.rtss.simulation.cbtc.member.SimulationUser;
|
||||
import club.joylink.rtss.vo.client.project.ProjectDeviceVO;
|
||||
import club.joylink.rtss.vo.map.graph.MapMemberVO;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.NonNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeansException;
|
||||
|
@ -18,11 +31,11 @@ import org.springframework.stereotype.Component;
|
|||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 仿真工作服务管理。
|
||||
* 1.管理仿真工作服务的实现类
|
||||
* 2.各种仿真的公共方法
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class SimulationWorkServiceManager implements ApplicationContextAware {
|
||||
|
@ -30,6 +43,14 @@ public class SimulationWorkServiceManager implements ApplicationContextAware {
|
|||
private MemberManager memberManager;
|
||||
@Autowired
|
||||
private ApplicationContext applicationContext;
|
||||
@Autowired
|
||||
private DeviceService deviceService;
|
||||
@Autowired
|
||||
private GroupSimulationService groupSimulationService;
|
||||
@Autowired
|
||||
private SimulationRealDeviceThread simulationRealDeviceThread;
|
||||
@Autowired
|
||||
private UDPRealDeviceThread udpRealDeviceThread;
|
||||
|
||||
private Map<Simulation.Type, SimulationWorkService> map;
|
||||
|
||||
|
@ -95,4 +116,39 @@ public class SimulationWorkServiceManager implements ApplicationContextAware {
|
|||
SimulationUserEnterEvent userEnterEvent = new SimulationUserEnterEvent(this, simulation, simulationUser);
|
||||
this.applicationContext.publishEvent(userEnterEvent);
|
||||
}
|
||||
|
||||
public void loadRealDevices(Simulation simulation) {
|
||||
SimulationBuildParams buildParams = simulation.getBuildParams();
|
||||
List<ProjectDeviceVO> projectDeviceList = this.deviceService
|
||||
.queryDetailByTypes(ProjectDeviceType.PlcDeviceList(), buildParams.getMap().getProjectCode());
|
||||
List<RealDeviceConfig> realDeviceList = ProjectDeviceVO.convert2RealDeviceList(projectDeviceList);
|
||||
log.info(String.format("load project device list: [%s]",
|
||||
realDeviceList.stream().map(Object::toString).collect(Collectors.joining(","))));
|
||||
this.loadRealDevices(simulation, realDeviceList);
|
||||
}
|
||||
|
||||
private void loadRealDevices(Simulation simulation, List<RealDeviceConfig> realDeviceList) {
|
||||
try {
|
||||
simulation.setRealDeviceList(realDeviceList);
|
||||
if (!CollectionUtils.isEmpty(realDeviceList)) {
|
||||
simulationRealDeviceThread.addJobs(simulation);
|
||||
udpRealDeviceThread.addJobs(simulation);
|
||||
}
|
||||
for (RealDeviceConfig realDevice : realDeviceList) {
|
||||
if (ProjectDeviceType.PLC_GATEWAY.equals(realDevice.getDeviceType())) {
|
||||
continue;
|
||||
}
|
||||
String deviceCode = realDevice.findDeviceCode();
|
||||
if (Objects.nonNull(deviceCode)) {
|
||||
this.groupSimulationService.connectDevice(simulation.getId(),
|
||||
deviceCode, realDevice.getProjectDevice().getId());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("仿真加载真实设备异常", e);
|
||||
// 清理仿真
|
||||
this.groupSimulationService.clearSimulation(simulation.getId(), simulation.getCreator());
|
||||
throw BusinessExceptionAssertEnum.TRAINING_ROOM_SIMULATION_LOAD_DEVICE_ERROR.exception(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,107 +16,135 @@ import lombok.Setter;
|
|||
@Setter
|
||||
@NoArgsConstructor
|
||||
public class DriveParamVO {
|
||||
/**
|
||||
* 限速值(km/h)
|
||||
*/
|
||||
private Float speedLimit;
|
||||
|
||||
/**
|
||||
* 限速值(m/s)
|
||||
*/
|
||||
@JsonIgnore
|
||||
@Setter(value = AccessLevel.NONE)
|
||||
private float speedLimitInMs = Float.MAX_VALUE;
|
||||
/**
|
||||
* 限速值(km/h)
|
||||
*/
|
||||
private Float speedLimit;
|
||||
|
||||
/**
|
||||
* 下令停车(优先级比运行高)
|
||||
*/
|
||||
@JsonIgnore
|
||||
private boolean stop;
|
||||
/**
|
||||
* 限速值(m/s)
|
||||
*/
|
||||
@JsonIgnore
|
||||
@Setter(value = AccessLevel.NONE)
|
||||
private float speedLimitInMs = Float.MAX_VALUE;
|
||||
|
||||
/**
|
||||
* 下令驾驶
|
||||
*/
|
||||
@JsonIgnore
|
||||
private boolean run = true;
|
||||
/**
|
||||
* 下令停车(优先级比运行高)
|
||||
*/
|
||||
@JsonIgnore
|
||||
private boolean stop;
|
||||
|
||||
/**
|
||||
* 目标设备code(用于确定目标位置)
|
||||
*/
|
||||
private String targetDeviceCode;
|
||||
/**
|
||||
* 下令驾驶
|
||||
*/
|
||||
@JsonIgnore
|
||||
private boolean run = true;
|
||||
|
||||
/**
|
||||
* 根据目标设备code计算出的目标位置
|
||||
*/
|
||||
@JsonIgnore
|
||||
private SectionPosition targetPosition;
|
||||
/**
|
||||
* 目标设备code(用于确定目标位置)
|
||||
*/
|
||||
private String targetDeviceCode;
|
||||
|
||||
/**
|
||||
* 越过信号机
|
||||
*/
|
||||
private int through;
|
||||
/**
|
||||
* 根据目标设备code计算出的目标位置
|
||||
*/
|
||||
@JsonIgnore
|
||||
private SectionPosition targetPosition;
|
||||
|
||||
public static final int NO = 0;
|
||||
public static final int RED_SIGNAL = 1;
|
||||
public static final int GUIDE_SIGNAL = 2;
|
||||
public static final int DRIVER_NEXT_STAND = 3;
|
||||
public static final int DRIVER_ROUTE_BLOCK = 4;
|
||||
/**
|
||||
* 越过信号机
|
||||
*/
|
||||
private int through;
|
||||
|
||||
/**
|
||||
* 要越过的信号机
|
||||
*/
|
||||
@JsonIgnore
|
||||
private Signal throughSignal;
|
||||
public static final int NO = 0;
|
||||
public static final int RED_SIGNAL = 1;
|
||||
public static final int GUIDE_SIGNAL = 2;
|
||||
public static final int DRIVER_NEXT_STAND = 3;
|
||||
public static final int DRIVER_ROUTE_BLOCK = 4;
|
||||
|
||||
/**
|
||||
* 要越过的信号
|
||||
*/
|
||||
@JsonIgnore
|
||||
private SignalAspect throughSignalAspect;
|
||||
/**
|
||||
* 解除EB(目的是在且仅在每次进行驾驶操作后自动缓解当时存在的EB)
|
||||
*/
|
||||
@JsonIgnore
|
||||
private boolean releaseEB = true;
|
||||
/**
|
||||
* 要越过的信号机
|
||||
*/
|
||||
@JsonIgnore
|
||||
private Signal throughSignal;
|
||||
|
||||
public void setSpeedLimit(Float speedLimit) {
|
||||
this.speedLimit = speedLimit;
|
||||
this.speedLimitInMs = speedLimit == null ? Float.MAX_VALUE : speedLimit / 3.6f;
|
||||
/**
|
||||
* 要越过的信号
|
||||
*/
|
||||
@JsonIgnore
|
||||
private SignalAspect throughSignalAspect;
|
||||
/**
|
||||
* 解除EB(目的是在且仅在每次进行驾驶操作后自动缓解当时存在的EB)
|
||||
*/
|
||||
@JsonIgnore
|
||||
private boolean releaseEB = true;
|
||||
|
||||
public void setSpeedLimit(Float speedLimit) {
|
||||
this.speedLimit = speedLimit;
|
||||
this.speedLimitInMs = speedLimit == null ? Float.MAX_VALUE : speedLimit / 3.6f;
|
||||
}
|
||||
|
||||
/**
|
||||
* 让机器人驾驶逻辑停止控制该列车
|
||||
*/
|
||||
public void stopControl() {
|
||||
stop = false;
|
||||
run = false;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public boolean isStopControl() {
|
||||
return !stop && !run;
|
||||
}
|
||||
|
||||
public boolean needStop() {
|
||||
return stop;
|
||||
}
|
||||
|
||||
public boolean needRun() {
|
||||
return !stop && run;
|
||||
}
|
||||
|
||||
public void setThrough(int v) {
|
||||
this.through = v;
|
||||
if (through == NO) {
|
||||
throughSignal = null;
|
||||
throughSignalAspect = null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean needStop() {
|
||||
return stop;
|
||||
}
|
||||
@JsonIgnore
|
||||
public boolean isThroughRedSignal() {
|
||||
return RED_SIGNAL == through;
|
||||
}
|
||||
|
||||
public boolean needRun() {
|
||||
return !stop && run;
|
||||
}
|
||||
@JsonIgnore
|
||||
public boolean isThroughGuideSignal() {
|
||||
return GUIDE_SIGNAL == through;
|
||||
}
|
||||
|
||||
public void setThrough(int v) {
|
||||
this.through = v;
|
||||
if (through == NO) {
|
||||
throughSignal = null;
|
||||
throughSignalAspect = null;
|
||||
}
|
||||
}
|
||||
@JsonIgnore
|
||||
public boolean isDriverNextStand() {
|
||||
return DRIVER_NEXT_STAND == through;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public boolean isThroughRedSignal() {
|
||||
return RED_SIGNAL == through;
|
||||
}
|
||||
@JsonIgnore
|
||||
public boolean isRouteBlockDriver() {
|
||||
return DRIVER_ROUTE_BLOCK == through;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public boolean isThroughGuideSignal() {
|
||||
return GUIDE_SIGNAL == through;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public boolean isDriverNextStand() {
|
||||
return DRIVER_NEXT_STAND == through;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public boolean isRouteBlockDriver() {
|
||||
return DRIVER_ROUTE_BLOCK == through;
|
||||
}
|
||||
public DriveParamVO cloneParamVO() {
|
||||
DriveParamVO paramVO = new DriveParamVO();
|
||||
paramVO.setSpeedLimit(speedLimit);
|
||||
paramVO.setStop(this.stop);
|
||||
paramVO.setRun(this.run);
|
||||
paramVO.setTargetDeviceCode(targetDeviceCode);
|
||||
paramVO.setTargetPosition(this.targetPosition);
|
||||
paramVO.setThrough(this.through);
|
||||
paramVO.setThroughSignal(this.throughSignal);
|
||||
paramVO.setThroughSignalAspect(this.throughSignalAspect);
|
||||
paramVO.setReleaseEB(this.releaseEB);
|
||||
return paramVO;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package club.joylink.rtss.vo.client.project;
|
||||
|
||||
import club.joylink.rtss.constants.ProjectCode;
|
||||
import club.joylink.rtss.constants.ProjectDeviceType;
|
||||
import club.joylink.rtss.entity.ProjectDevice;
|
||||
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
|
||||
|
@ -9,10 +10,18 @@ import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.gxsd.GxsdSignalCo
|
|||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.gxsd.GxsdSwitchConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.gzb.GzbSignalConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.gzb.GzbSwitchConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.heb.device.*;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.heb.device.Heb1IbpConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.heb.device.Heb1PscConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.heb.device.Heb1PslConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.heb.device.Heb1SignalConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.heb.device.Heb1SwitchConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.hhcj.HhcjIbpConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.hhcj.HhcjPsdConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.say.*;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.say.SayIbpConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.say.SayPsdConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.say.SaySectionConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.say.SaySignalConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.say.SaySwitchConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.sdy.SdyPsdConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.sdy.SdyPslConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.modbustcp.xty.XtyPsdConfig;
|
||||
|
@ -25,8 +34,17 @@ import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config.SrSectionConf
|
|||
import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config.SrSignalConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config.SrSwitchConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.sr.config.SrTrainConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.config.ThailandSectionConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.config.ThailandSignalConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.config.ThailandSwitchConfig;
|
||||
import club.joylink.rtss.simulation.cbtc.device.real.udp.thailand.config.ThailandTrainConfig;
|
||||
import club.joylink.rtss.util.JsonUtils;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
@ -34,12 +52,6 @@ import lombok.extern.slf4j.Slf4j;
|
|||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 项目设备对象
|
||||
*/
|
||||
|
@ -104,8 +116,7 @@ public class ProjectDeviceVO {
|
|||
List<RealDeviceConfig> list = new ArrayList<>();
|
||||
if (!CollectionUtils.isEmpty(voList)) {
|
||||
String project = voList.get(0).getProject();
|
||||
String projectCode = StringUtils.hasText(project) ? project.toUpperCase() : "";
|
||||
switch (projectCode) {
|
||||
switch (project) {
|
||||
case "XTY": {
|
||||
return xtyDeviceConfigConvert(voList);
|
||||
}
|
||||
|
@ -121,7 +132,7 @@ public class ProjectDeviceVO {
|
|||
case "RICHOR_JOINT": {
|
||||
return zjdDeviceConfigConvert(voList);
|
||||
}
|
||||
case "SR_SANDBOX": {
|
||||
case ProjectCode.SR_SANDBOX: {
|
||||
return srSandboxDeviceConfigConvert(voList);
|
||||
}
|
||||
case "RICHOR_HHCJ": {
|
||||
|
@ -130,6 +141,9 @@ public class ProjectDeviceVO {
|
|||
case "SAY": {
|
||||
return sayDeviceConfigConvert(voList);
|
||||
}
|
||||
case ProjectCode.THAILAND_SANDBOX: {
|
||||
return thailandSandboxDeviceConfigConvert(voList);
|
||||
}
|
||||
case "GXSD": {
|
||||
return gxsdDeviceConfigConvert(voList);
|
||||
}
|
||||
|
@ -139,6 +153,34 @@ public class ProjectDeviceVO {
|
|||
return list;
|
||||
}
|
||||
|
||||
private static List<RealDeviceConfig> thailandSandboxDeviceConfigConvert(
|
||||
List<ProjectDeviceVO> voList) {
|
||||
List<RealDeviceConfig> list = new ArrayList<>();
|
||||
for (ProjectDeviceVO deviceVO : voList) {
|
||||
switch (deviceVO.getType()) {
|
||||
case UDP_LOW:
|
||||
list.add(new UDPLowConfig(deviceVO));
|
||||
break;
|
||||
case UDP_CLIENT:
|
||||
list.add(new UDPClientConfig(deviceVO));
|
||||
break;
|
||||
case SIGNAL:
|
||||
list.add(new ThailandSignalConfig(deviceVO));
|
||||
break;
|
||||
case SECTION:
|
||||
list.add(new ThailandSectionConfig(deviceVO));
|
||||
break;
|
||||
case SWITCH:
|
||||
list.add(new ThailandSwitchConfig(deviceVO));
|
||||
break;
|
||||
case TRAIN:
|
||||
list.add(new ThailandTrainConfig(deviceVO));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private static List<RealDeviceConfig> gxsdDeviceConfigConvert(List<ProjectDeviceVO> voList) {
|
||||
List<RealDeviceConfig> list = new ArrayList<>();
|
||||
for (ProjectDeviceVO deviceVO : voList) {
|
||||
|
|
|
@ -12,6 +12,12 @@ import lombok.Setter;
|
|||
@Setter
|
||||
@NoArgsConstructor
|
||||
public class UDPLowConfigVO {
|
||||
/**
|
||||
* 名称。
|
||||
* 泰国沙盘下位机有两个接收数据的端口,一个用于接收信号机控制指令;一个用于接收道岔和区段控制指令。
|
||||
*/
|
||||
private String name;
|
||||
|
||||
private String ip;
|
||||
|
||||
private Integer port;
|
||||
|
@ -21,6 +27,11 @@ public class UDPLowConfigVO {
|
|||
this.port = port;
|
||||
}
|
||||
|
||||
public UDPLowConfigVO(String name, String ip, Integer port) {
|
||||
this(ip, port);
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String toJson() {
|
||||
return JsonUtils.writeValueAsString(this);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package club.joylink.rtss.vo.client.project.thailand;
|
||||
|
||||
import club.joylink.rtss.vo.client.project.RealConfigVO;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class ThailandSectionConfigVO extends RealConfigVO {
|
||||
private String vrCode;
|
||||
|
||||
private String sandboxCode;
|
||||
|
||||
/**
|
||||
* 车头到达区段延迟停车时间/s
|
||||
*/
|
||||
private Float headDelayTime;
|
||||
|
||||
/**
|
||||
* 车尾解除占用延迟停车时间/s
|
||||
*/
|
||||
private Float tailDelayTime;
|
||||
|
||||
public ThailandSectionConfigVO() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public ThailandSectionConfigVO(String vrCode, String sandboxCode) {
|
||||
this();
|
||||
this.vrCode = vrCode;
|
||||
this.sandboxCode = sandboxCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String findDeviceCode() {
|
||||
return vrCode;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package club.joylink.rtss.vo.client.project.thailand;
|
||||
|
||||
import club.joylink.rtss.vo.client.project.RealConfigVO;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class ThailandSignalConfigVO extends RealConfigVO {
|
||||
private String vrCode;
|
||||
|
||||
private String sandboxCode;
|
||||
|
||||
public ThailandSignalConfigVO() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public ThailandSignalConfigVO(String vrCode, String sandboxCode) {
|
||||
this();
|
||||
this.vrCode = vrCode;
|
||||
this.sandboxCode = sandboxCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String findDeviceCode() {
|
||||
return vrCode;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package club.joylink.rtss.vo.client.project.thailand;
|
||||
|
||||
import club.joylink.rtss.vo.client.project.RealConfigVO;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class ThailandSwitchConfigVO extends RealConfigVO {
|
||||
private String vrCode;
|
||||
|
||||
private String sandboxCode;
|
||||
|
||||
public ThailandSwitchConfigVO() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public ThailandSwitchConfigVO(String vrCode, String sandboxCode) {
|
||||
this();
|
||||
this.vrCode = vrCode;
|
||||
this.sandboxCode = sandboxCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String findDeviceCode() {
|
||||
return vrCode;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package club.joylink.rtss.vo.client.project.thailand;
|
||||
|
||||
import club.joylink.rtss.vo.client.project.RealConfigVO;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class ThailandTrainConfigVO extends RealConfigVO {
|
||||
private String vrCode;
|
||||
|
||||
private String sandboxCode;
|
||||
|
||||
public ThailandTrainConfigVO() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public ThailandTrainConfigVO(String vrCode, String sandboxCode) {
|
||||
this();
|
||||
this.vrCode = vrCode;
|
||||
this.sandboxCode = sandboxCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String findDeviceCode() {
|
||||
return vrCode;
|
||||
}
|
||||
}
|
|
@ -215,7 +215,7 @@ common:
|
|||
spring:
|
||||
profiles: local
|
||||
datasource:
|
||||
url: jdbc:mysql://192.168.1.254:3306/joylink?useSSL=false&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
|
||||
url: jdbc:mysql://192.168.53.11:3306/joylink?useSSL=false&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
|
||||
username: root
|
||||
password: localdb
|
||||
|
||||
|
|
Loading…
Reference in New Issue