@ -21,6 +21,7 @@ import club.joylink.rtss.vo.client.WebSocketMessageType;
import club.joylink.rtss.vo.client.factory.SocketMessageFactory ;
import club.joylink.rtss.vo.client.factory.SocketMessageFactory ;
import club.joylink.rtss.websocket.StompMessageService ;
import club.joylink.rtss.websocket.StompMessageService ;
import lombok.extern.slf4j.Slf4j ;
import lombok.extern.slf4j.Slf4j ;
import org.apache.commons.lang3.StringUtils ;
import org.springframework.beans.factory.annotation.Autowired ;
import org.springframework.beans.factory.annotation.Autowired ;
import org.springframework.context.ApplicationContext ;
import org.springframework.context.ApplicationContext ;
import org.springframework.stereotype.Component ;
import org.springframework.stereotype.Component ;
@ -33,14 +34,14 @@ import java.util.stream.Collectors;
@Component
@Component
public class ATSMessageCollectAndDispatcher {
public class ATSMessageCollectAndDispatcher {
@Autowired
@Autowired
private Joylink3DMessageService joylink3DMessageService ;
private Joylink3DMessageService joylink3DMessageService ;
@Autowired
@Autowired
private StompMessageService stompMessageService ;
private StompMessageService stompMessageService ;
@Autowired
@Autowired
private ApplicationContext applicationContext ;
private ApplicationContext applicationContext ;
/ / public void run ( Simulation simulation ) {
/ / public void run ( Simulation simulation ) {
/ / / / long start = System . currentTimeMillis ( ) ;
/ / / / long start = System . currentTimeMillis ( ) ;
@ -62,222 +63,223 @@ public class ATSMessageCollectAndDispatcher {
/ / / / System . out . println ( String . format ( " 收集并发送设备状态用时: [%s ms] " , ( end - start ) ) ) ;
/ / / / System . out . println ( String . format ( " 收集并发送设备状态用时: [%s ms] " , ( end - start ) ) ) ;
/ / }
/ / }
/ * *
/ * *
* 收集仿真所有设备状态并发送给仿真用户
* 收集仿真所有设备状态并发送给仿真用户
* /
* /
public void collectAllAndSend ( Simulation simulation ) {
public void collectAllAndSend ( Simulation simulation ) {
List < DeviceStatusVO > deviceStatuses = collectAll ( simulation ) ;
List < DeviceStatusVO > deviceStatuses = collectAll ( simulation ) ;
/ / 构建并发送设备状态消息
/ / 构建并发送设备状态消息
SocketMessageVO < List < DeviceStatusVO > > deviceStatusMessage =
SocketMessageVO < List < DeviceStatusVO > > deviceStatusMessage =
SocketMessageFactory . buildSimulationDeviceStatusesMessage ( simulation . getId ( ) , deviceStatuses ) ;
SocketMessageFactory . buildSimulationDeviceStatusesMessage ( simulation . getId ( ) , deviceStatuses ) ;
Set < String > sessions = simulation . getSimulationUserIds ( ) ;
Set < String > sessions = simulation . getSimulationUserIds ( ) ;
stompMessageService . sendToUser ( sessions , deviceStatusMessage ) ;
stompMessageService . sendToUser ( sessions , deviceStatusMessage ) ;
}
}
/ * *
/ * *
* 收集仿真所有设备状态
* 收集仿真所有设备状态
* /
* /
public List < DeviceStatusVO > collectAll ( Simulation simulation ) {
public List < DeviceStatusVO > collectAll ( Simulation simulation ) {
List < DeviceStatusVO > totalList = new ArrayList < > ( ) ;
List < DeviceStatusVO > totalList = new ArrayList < > ( ) ;
SimulationDataRepository repository = simulation . getRepository ( ) ;
SimulationDataRepository repository = simulation . getRepository ( ) ;
Map < String , ? extends MapElement > deviceMap = repository . getDeviceMap ( ) ;
Map < String , ? extends MapElement > deviceMap = repository . getDeviceMap ( ) ;
deviceMap . values ( ) . forEach ( device - > {
deviceMap . values ( ) . forEach ( device - > {
DeviceStatus deviceStatus = repository . findStatusByCode ( device . getCode ( ) ) ;
DeviceStatus deviceStatus = repository . findStatusByCode ( device . getCode ( ) ) ;
if ( Objects . isNull ( deviceStatus ) ) {
if ( Objects . isNull ( deviceStatus ) ) {
deviceStatus = buildDeviceStatus ( device ) ;
deviceStatus = buildDeviceStatus ( device ) ;
if ( Objects . nonNull ( deviceStatus ) ) {
if ( Objects . nonNull ( deviceStatus ) ) {
repository . addDeviceInfo ( deviceStatus ) ;
repository . addDeviceInfo ( deviceStatus ) ;
totalList . add ( deviceStatus . convert2VO ( device ) ) ;
totalList . add ( deviceStatus . convert2VO ( device ) ) ;
}
}
} else {
} else {
DeviceStatusVO statusVO = buildDeviceStatusVO ( device ) ;
DeviceStatusVO statusVO = buildDeviceStatusVO ( device ) ;
if ( deviceStatus . compareAndChange ( device , statusVO ) ) {
if ( deviceStatus . compareAndChange ( device , statusVO ) ) {
totalList . add ( statusVO ) ;
totalList . add ( statusVO ) ;
}
}
}
}
} ) ;
} ) ;
/ / 列车状态
/ / 列车状态
List < TrainInfo > trainList = repository . getSuperviseTrainList ( ) ;
List < TrainInfo > trainList = repository . getSuperviseTrainList ( ) ;
trainList . forEach ( train - > {
trainList . forEach ( train - > {
TrainStatus trainStatus = repository . findStatusByCode ( train . getGroupNumber ( ) , TrainStatus . class ) ;
TrainStatus trainStatus = repository . findStatusByCode ( train . getGroupNumber ( ) , TrainStatus . class ) ;
if ( Objects . isNull ( trainStatus ) ) {
if ( Objects . isNull ( trainStatus ) ) {
/ / if ( simulation . getBuildParams ( ) . getProdType ( ) = = MapPrdTypeEnum . YJDDZH ) {
/ / if ( simulation . getBuildParams ( ) . getProdType ( ) = = MapPrdTypeEnum . YJDDZH ) {
if ( Objects . equals ( simulation . getProject ( ) , MapPrdTypeEnum . YJDDZH . name ( ) ) ) {
if ( Objects . equals ( simulation . getProject ( ) , MapPrdTypeEnum . YJDDZH . name ( ) ) ) {
trainStatus = new YJDDZHTrainStatus ( train ) ;
trainStatus = new YJDDZHTrainStatus ( train ) ;
} else {
} else {
trainStatus = new TrainStatus ( train ) ;
trainStatus = new TrainStatus ( train ) ;
}
}
repository . addDeviceInfo ( trainStatus ) ;
repository . addDeviceInfo ( trainStatus ) ;
totalList . add ( trainStatus . convert2VO ( train ) ) ;
totalList . add ( trainStatus . convert2VO ( train ) ) ;
} else {
} else {
DeviceStatusVO statusVO ;
DeviceStatusVO statusVO ;
/ / if ( simulation . getBuildParams ( ) . getProdType ( ) = = MapPrdTypeEnum . YJDDZH ) {
/ / if ( simulation . getBuildParams ( ) . getProdType ( ) = = MapPrdTypeEnum . YJDDZH ) {
if ( Objects . equals ( simulation . getProject ( ) , MapPrdTypeEnum . YJDDZH . name ( ) ) ) {
if ( Objects . equals ( simulation . getProject ( ) , MapPrdTypeEnum . YJDDZH . name ( ) ) ) {
statusVO = new YJDDZHTrainStatusVO ( train ) ;
statusVO = new YJDDZHTrainStatusVO ( train ) ;
} else {
} else {
statusVO = new TrainStatusVO ( train ) ;
/ / statusVO = new TrainStatusVO ( train ) ;
}
statusVO = new TrainStatusVO ( trainStatus ) ;
if ( trainStatus . compareAndChange ( train , statusVO ) ) {
totalList . add ( statusVO ) ;
}
}
} ) ;
/ / 回库删除的列车状态
List < TrainStatus > inboundTrainList = new ArrayList < > ( ) ;
List < TrainStatus > trainStatusList = repository . getTrainStatusList ( ) ;
if ( ! CollectionUtils . isEmpty ( trainStatusList ) ) {
for ( TrainStatus trainStatus : trainStatusList ) {
TrainInfo trainInfo = repository . findSupervisedTrainByGroup ( trainStatus . getGroupNumber ( ) ) ;
if ( Objects . isNull ( trainInfo ) ) {
totalList . add ( TrainStatusVO . buildDispose ( trainStatus . getGroupNumber ( ) ) ) ;
inboundTrainList . add ( trainStatus ) ;
repository . deleteDeviceStatus ( trainStatus . getCode ( ) ) ;
}
}
}
}
joylink3DMessageService . handleTrainInbound ( simulation , inboundTrainList ) ;
if ( trainStatus . compareAndChange ( train , statusVO ) ) {
return totalList ;
totalList . add ( statusVO ) ;
}
private DeviceStatus buildDeviceStatus ( MapElement device ) {
DeviceStatus status = null ;
switch ( device . getDeviceType ( ) ) {
case SECTION :
status = new SectionStatus ( ( Section ) device ) ;
break ;
case SWITCH :
status = new SwitchStatus ( ( Switch ) device ) ;
break ;
case SIGNAL :
status = new SignalStatus ( ( Signal ) device ) ;
break ;
case STATION :
status = new StationStatus ( ( Station ) device ) ;
break ;
case STAND :
status = new StandStatus ( ( Stand ) device ) ;
break ;
case PSD :
status = new PSDStatus ( ( PSD ) device ) ;
break ;
case ZC :
status = new ZCStatus ( ( ZC ) device ) ;
break ;
case ROUTE :
status = new RouteStatus ( ( Route ) device ) ;
break ;
case OVERLAP : {
status = new OverlapStatus ( ( RouteOverlap ) device ) ;
break ;
}
case CYCLE :
status = new CycleStatus ( ( Cycle ) device ) ;
break ;
case DIRECTION_ROD :
status = new DirectionRodStatus ( ( DirectionRod ) device ) ;
break ;
case CATENARY :
status = new CatenaryStatus ( ( Catenary ) device ) ;
break ;
case STATION_DIRECTION :
status = new StationDirectionStatus ( ( StationDirection ) device ) ;
break ;
}
}
return status ;
}
}
} ) ;
/ / 回库删除的列车状态
private DeviceStatusVO buildDeviceStatusVO ( MapElement device ) {
List < TrainStatus > inboundTrainList = new ArrayList < > ( ) ;
DeviceStatusVO status = null ;
List < TrainStatus > trainStatusList = repository . getTrainStatusList ( ) ;
switch ( device . getDeviceType ( ) ) {
if ( ! CollectionUtils . isEmpty ( trainStatusList ) ) {
case SECTION :
for ( TrainStatus trainStatus : trainStatusList ) {
status = new SectionStatusVO ( ( Section ) device ) ;
TrainInfo trainInfo = repository . findSupervisedTrainByGroup ( trainStatus . getGroupNumber ( ) ) ;
break ;
if ( Objects . isNull ( trainInfo ) ) {
case SWITCH :
totalList . add ( TrainStatusVO . buildDispose ( trainStatus . getGroupNumber ( ) ) ) ;
status = new SwitchStatusVO ( ( Switch ) device ) ;
inboundTrainList . add ( trainStatus ) ;
break ;
repository . deleteDeviceStatus ( trainStatus . getCode ( ) ) ;
case SIGNAL :
status = new SignalStatusVO ( ( Signal ) device ) ;
break ;
case STATION :
status = new StationStatusVO ( ( Station ) device ) ;
break ;
case STAND :
status = new StandStatusVO ( ( Stand ) device ) ;
break ;
case PSD :
status = new PSDStatusVO ( ( PSD ) device ) ;
break ;
case ZC :
status = new ZCStatusVO ( ( ZC ) device ) ;
break ;
case ROUTE :
status = new RouteStatusVO ( ( Route ) device ) ;
break ;
case OVERLAP : {
status = new OverlapStatusVO ( ( RouteOverlap ) device ) ;
break ;
}
case CYCLE :
status = new CycleStatusVO ( ( Cycle ) device ) ;
break ;
case DIRECTION_ROD :
status = new DirectionRodStatusVO ( ( DirectionRod ) device ) ;
break ;
case CATENARY :
status = new CatenaryStatusVO ( ( Catenary ) device ) ;
break ;
case STATION_DIRECTION :
status = new StationDirectionStatusVO ( ( StationDirection ) device ) ;
break ;
}
}
return status ;
}
}
}
joylink3DMessageService . handleTrainInbound ( simulation , inboundTrainList ) ;
return totalList ;
}
/ * *
private DeviceStatus buildDeviceStatus ( MapElement device ) {
* 列车运行数据
DeviceStatus status = null ;
* /
switch ( device . getDeviceType ( ) ) {
public void sendTrainRunData ( Simulation simulation , RealRun realRun ) {
case SECTION :
stompMessageService . sendToUser ( simulation . getSimulationUserIds ( ) ,
status = new SectionStatus ( ( Section ) device ) ;
SocketMessageFactory . build ( WebSocketMessageType . Simulation_RunFact ,
break ;
simulation . getId ( ) , Arrays . asList ( realRun ) ) ) ;
case SWITCH :
}
status = new SwitchStatus ( ( Switch ) device ) ;
break ;
case SIGNAL :
status = new SignalStatus ( ( Signal ) device ) ;
break ;
case STATION :
status = new StationStatus ( ( Station ) device ) ;
break ;
case STAND :
status = new StandStatus ( ( Stand ) device ) ;
break ;
case PSD :
status = new PSDStatus ( ( PSD ) device ) ;
break ;
case ZC :
status = new ZCStatus ( ( ZC ) device ) ;
break ;
case ROUTE :
status = new RouteStatus ( ( Route ) device ) ;
break ;
case OVERLAP : {
status = new OverlapStatus ( ( RouteOverlap ) device ) ;
break ;
}
case CYCLE :
status = new CycleStatus ( ( Cycle ) device ) ;
break ;
case DIRECTION_ROD :
status = new DirectionRodStatus ( ( DirectionRod ) device ) ;
break ;
case CATENARY :
status = new CatenaryStatus ( ( Catenary ) device ) ;
break ;
/ * *
case STATION_DIRECTION :
* 仿真设备操作消息
status = new StationDirectionStatus ( ( StationDirection ) device ) ;
* /
break ;
public void handlerOperateMessage ( Simulation simulation , OperationMessage operationMessage ) {
SocketMessageVO < OperationMessage > socketMessageVO =
SocketMessageFactory . build ( WebSocketMessageType . Simulation_ApplyHandle , simulation . getId ( ) , operationMessage ) ;
Set < SimulationMember > humanMembers = operationMessage . getTargetMembers ( ) . stream ( ) . filter ( m - > ! m . isRobot ( ) ) . collect ( Collectors . toSet ( ) ) ;
/ / 当在场景实训设计中 , 并且无真人成员时 , 将数据暂存 , 等待后续角色有人扮演时再发送
if ( simulation . isInSceneTraining ( ) & & CollectionUtils . isEmpty ( humanMembers ) ) {
for ( SimulationMember targetMember : operationMessage . getTargetMembers ( ) ) {
targetMember . getUnreceivedMessages ( ) . offer ( socketMessageVO ) ;
}
return ;
}
if ( CollectionUtils . isEmpty ( humanMembers ) ) {
/ / 目标都是机器人 , 选择一个机器人发送事件处理
applicationContext . publishEvent ( new SimulationOperationMessageEvent ( this , simulation , operationMessage ) ) ;
return ;
}
/ / 目标成员有真人 , 推送对应真人处理
stompMessageService . sendToUser ( humanMembers . stream ( ) . map ( SimulationMember : : getUserId ) . collect ( Collectors . toSet ( ) ) , socketMessageVO ) ;
}
}
return status ;
}
/ * *
private DeviceStatusVO buildDeviceStatusVO ( MapElement device ) {
* 同步仿真系统时间给客户端
DeviceStatusVO status = null ;
* /
switch ( device . getDeviceType ( ) ) {
public void syncTime ( Simulation simulation ) {
case SECTION :
Set < String > sessions = simulation . getSimulationUserIds ( ) ;
status = new SectionStatusVO ( ( Section ) device ) ;
SocketMessageVO < Long > timeSyncMessage = SocketMessageFactory . buildSimulationTimeSyncMessage ( simulation ) ;
break ;
stompMessageService . sendToUser ( sessions , timeSyncMessage ) ;
case SWITCH :
}
status = new SwitchStatusVO ( ( Switch ) device ) ;
break ;
case SIGNAL :
status = new SignalStatusVO ( ( Signal ) device ) ;
break ;
case STATION :
status = new StationStatusVO ( ( Station ) device ) ;
break ;
case STAND :
status = new StandStatusVO ( ( Stand ) device ) ;
break ;
case PSD :
status = new PSDStatusVO ( ( PSD ) device ) ;
break ;
case ZC :
status = new ZCStatusVO ( ( ZC ) device ) ;
break ;
case ROUTE :
status = new RouteStatusVO ( ( Route ) device ) ;
break ;
case OVERLAP : {
status = new OverlapStatusVO ( ( RouteOverlap ) device ) ;
break ;
}
case CYCLE :
status = new CycleStatusVO ( ( Cycle ) device ) ;
break ;
case DIRECTION_ROD :
status = new DirectionRodStatusVO ( ( DirectionRod ) device ) ;
break ;
case CATENARY :
status = new CatenaryStatusVO ( ( Catenary ) device ) ;
break ;
public void addJobs ( Simulation simulation ) {
case STATION_DIRECTION :
simulation . addJob ( SimulationModule . SYNC_TIME . name ( ) , ( ) - > syncTime ( simulation ) , SimulationConstants . SYNC_TIME_RATE ) ;
s tatus = new StationDirectionStatusVO ( ( StationDirection ) device ) ;
simulation . addFixedRateJob ( SimulationModule . MESSAGE . name ( ) , ( ) - > collectAllAndSend ( simulation ) , SimulationConstants . SEND_CLIENT_RATE ) ;
break ;
}
}
return status ;
}
/ * *
* 列车运行数据
* /
public void sendTrainRunData ( Simulation simulation , RealRun realRun ) {
stompMessageService . sendToUser ( simulation . getSimulationUserIds ( ) ,
SocketMessageFactory . build ( WebSocketMessageType . Simulation_RunFact ,
simulation . getId ( ) , Arrays . asList ( realRun ) ) ) ;
}
/ * *
* 仿真设备操作消息
* /
public void handlerOperateMessage ( Simulation simulation , OperationMessage operationMessage ) {
SocketMessageVO < OperationMessage > socketMessageVO =
SocketMessageFactory . build ( WebSocketMessageType . Simulation_ApplyHandle , simulation . getId ( ) , operationMessage ) ;
Set < SimulationMember > humanMembers = operationMessage . getTargetMembers ( ) . stream ( ) . filter ( m - > ! m . isRobot ( ) ) . collect ( Collectors . toSet ( ) ) ;
/ / 当在场景实训设计中 , 并且无真人成员时 , 将数据暂存 , 等待后续角色有人扮演时再发送
if ( simulation . isInSceneTraining ( ) & & CollectionUtils . isEmpty ( humanMembers ) ) {
for ( SimulationMember targetMember : operationMessage . getTargetMembers ( ) ) {
targetMember . getUnreceivedMessages ( ) . offer ( socketMessageVO ) ;
}
return ;
}
if ( CollectionUtils . isEmpty ( humanMembers ) ) {
/ / 目标都是机器人 , 选择一个机器人发送事件处理
applicationContext . publishEvent ( new SimulationOperationMessageEvent ( this , simulation , operationMessage ) ) ;
return ;
}
/ / 目标成员有真人 , 推送对应真人处理
stompMessageService . sendToUser ( humanMembers . stream ( ) . map ( SimulationMember : : getUserId ) . collect ( Collectors . toSet ( ) ) , socketMessageVO ) ;
}
/ * *
* 同步仿真系统时间给客户端
* /
public void syncTime ( Simulation simulation ) {
Set < String > sessions = simulation . getSimulationUserIds ( ) ;
SocketMessageVO < Long > timeSyncMessage = SocketMessageFactory . buildSimulationTimeSyncMessage ( simulation ) ;
stompMessageService . sendToUser ( sessions , timeSyncMessage ) ;
}
public void addJobs ( Simulation simulation ) {
simulation . addJob ( SimulationModule . SYNC_TIME . name ( ) , ( ) - > syncTime ( simulation ) , SimulationConstants . SYNC_TIME_RATE ) ;
simulation . addFixedRateJob ( SimulationModule . MESSAGE . name ( ) , ( ) - > collectAllAndSend ( simulation ) , SimulationConstants . SEND_CLIENT_RATE ) ;
}
}
}