调度命令

This commit is contained in:
xzb 2022-09-06 16:59:28 +08:00
parent 8ac5de29eb
commit e9cc4510b4
11 changed files with 350 additions and 43 deletions

View File

@ -113,6 +113,10 @@ public class CtcRepository {
* 调度命令id生成器 * 调度命令id生成器
*/ */
private AtomicInteger dispatchCommandIdGenerator = new AtomicInteger(0); private AtomicInteger dispatchCommandIdGenerator = new AtomicInteger(0);
/**
* 调度命令受令单位id生成器
*/
private AtomicInteger disCmdRcvCompanyIdGenerator = new AtomicInteger(0);
/** /**
* 新版调度命令 * 新版调度命令
* k - 调度命令id * k - 调度命令id

View File

@ -1,7 +1,5 @@
package club.joylink.rtss.simulation.cbtc.CTC.rail.cmd; package club.joylink.rtss.simulation.cbtc.CTC.rail.cmd;
import club.joylink.rtss.simulation.cbtc.member.SimulationMember;
import lombok.Data; import lombok.Data;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.List;
@ -38,7 +36,7 @@ public class DisCmd {
/** /**
* 值班主任(仿真成员) * 值班主任(仿真成员)
*/ */
private SimulationMember chiefOnDuty; private String chiefOnDuty;
/** /**
* 需值班主任授权 * 需值班主任授权
*/ */
@ -54,7 +52,7 @@ public class DisCmd {
/** /**
* 审核人(仿真成员) * 审核人(仿真成员)
*/ */
private SimulationMember reviewer; private String reviewer;
/** /**
* 日计划号 * 日计划号
*/ */
@ -91,5 +89,6 @@ public class DisCmd {
*/ */
NORMAL, NORMAL,
; ;
} }
} }

View File

@ -1,7 +1,7 @@
package club.joylink.rtss.simulation.cbtc.CTC.rail.cmd; package club.joylink.rtss.simulation.cbtc.CTC.rail.cmd;
import club.joylink.rtss.simulation.cbtc.member.SimulationMember;
import lombok.Data; import lombok.Data;
import java.time.LocalDateTime; import java.time.LocalDateTime;
/** /**
@ -10,77 +10,107 @@ import java.time.LocalDateTime;
@Data @Data
public class DisCmdRcvCompany { public class DisCmdRcvCompany {
/**
* 调度命令号(唯一)
*/
private String disCmdCode;
/**
* 唯一id,记录id
*/
private String id;
/** /**
* 受令单位类型 * 受令单位类型
*/ */
private Type type; private Type type;
/** /**
* 受令单位名称 * 受令单位名称
*/ */
private String name; private String name;
//////////////////受令者///////////////////// //////////////////受令者/////////////////////
/** /**
* 车站受令者code * 车站受令者code
*/ */
private String stationCode; private String stationCode;
/** /**
* 调度台受令者code * 调度台受令者code
*/ */
private String disCode; private String disCode;
/** /**
* 列控服务器受令者code * 列控服务器受令者code
*/ */
private String tsrCode; private String tsrCode;
//////////////////受令者train//////////////////////// //////////////////受令者train////////////////////////
/** /**
* 无线调度命令true-通过手机移动网络直接发送false-通过车站专有网络发送 * 无线调度命令true-通过手机移动网络直接发送false-通过车站专有网络发送
*/ */
private Boolean trainViaGsmR = true; private Boolean trainViaGsmR = true;
/** /**
* 中转车站code * 中转车站code
* <p> * <p>
* 当trainViaGsmR=false时不为空 * 当trainViaGsmR=false时不为空
*/ */
private String transStationCode; private String transStationCode;
/** /**
* 车次号 * 车次号
*/ */
private String trainNum; private String trainNum;
/** /**
* 机车号(train code) * 机车号(train code)
*/ */
private String trainCode; private String trainCode;
/////////////////////运行时数据////////////////// /////////////////////运行时数据//////////////////
/** /**
* 最终受令端对于调度命令的状态 * 最终受令端对于调度命令的状态
*/ */
private Status state; private Status state;
/** /**
* 最终受令端对于调度命令的接收时间 * 最终受令端对于调度命令的接收时间
*/ */
private LocalDateTime receiveTime; private LocalDateTime receiveTime;
/** /**
* 最终受令端对于调度命令的签收时间 * 最终受令端对于调度命令的签收时间
*/ */
private LocalDateTime signTime; private LocalDateTime signTime;
/**
* 最终受令端对于调度命令的实际签收人
*/
private SimulationMember signByReal;
/** /**
* 无线调度命令的中转站对调度命令的状态 * 无线调度命令的中转站对调度命令的状态
*/ */
private TransStatus transStatus; private TransStatus transStatus;
/** /**
* 无线调度命令的中转站对调度命令的接收时间 * 无线调度命令的中转站对调度命令的接收时间
*/ */
private LocalDateTime transReceiveTime; private LocalDateTime transReceiveTime;
/** /**
* 无线调度命令的中转站对调度命令的发送时间 * 无线调度命令的中转站对调度命令的发送时间
*/ */
private LocalDateTime transSendTime; private LocalDateTime transSendTime;
/**
* 自律机是否执行转发调度命令
*/
private boolean exeTransSend = false;
/**
* 向最终受令单位的前端推送通知的次数,前端签收后将停止推送通知
*/
private int countForReceiveNotify = 0;
/**
* 下一次向前端推送通知的时刻注意使用的是计时机系统时间而不是仿真系统时间
* <p>
* 单位为毫秒
*/
private long timeForNextReceiveNotify = System.currentTimeMillis();
/**
* 记录上次向前端推送签收调度命的通知的时间
*/
private LocalDateTime lastSendReceiveNotifyTime;
/////////////////////////////////////////////// ///////////////////////////////////////////////
/** /**
* 发令单位类型 * 发令单位类型
*/ */
public static enum Type { public enum Type {
Dispatcher,//调度台 Dispatcher,//调度台
Station,//车站 Station,//车站
Train,//无线 Train,//无线

View File

@ -9,32 +9,39 @@ import java.time.LocalDateTime;
*/ */
@Data @Data
public class DisCmdSendCompany { public class DisCmdSendCompany {
/** /**
* 发令单位类型 * 发令单位类型
*/ */
private Type type; private Type type;
/** /**
* 发令单位名称 * 发令单位名称
*/ */
private String name; private String name;
/**
* 发令单位code
*/
private String code;
/**
* 调度命令号(唯一)
*/
private String disCmdCode;
//////////////////运行时数据//////////////// //////////////////运行时数据////////////////
/** /**
* 调度命令对应发令单的状态 * 调度命令对应发令单的状态
*/ */
private Status state; private Status state;
/** /**
* 发令时间 * 发令时间
*/ */
private LocalDateTime sendTime; private LocalDateTime sendTime;
/** /**
* 是否执行过发令(非业务状态) * 是否执行过发令(非业务状态)
*/ */
private boolean exeSend = false; private boolean exeSend = false;
/** /**
* 签收完成时间 * 签收完成时间
*/ */
private LocalDateTime signedTime; private LocalDateTime signedTime;
////////////////////////////////////////// //////////////////////////////////////////
/** /**

View File

@ -2,7 +2,12 @@ package club.joylink.rtss.simulation.cbtc.CTC.rail.cmd;
import club.joylink.rtss.exception.BusinessExceptionAssertEnum; import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.simulation.cbtc.CTC.data.CtcRepository; import club.joylink.rtss.simulation.cbtc.CTC.data.CtcRepository;
import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.convertor.DisCmdConvertor;
import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo.DisCmdHolderEnum;
import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo.DisCmdVo;
import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo.FindAllDisCmdForHolderRspVo;
import club.joylink.rtss.simulation.cbtc.Simulation; import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.member.SimulationMember;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@ -31,7 +36,7 @@ public class DisCmdService {
disCmd.getSendCompany().setState(DisCmdSendCompany.Status.Cache); disCmd.getSendCompany().setState(DisCmdSendCompany.Status.Cache);
} }
/** /**
* 发送调度命令 * 发送调度命令给通信服务器
* @param disCmdCode 调度命令号 * @param disCmdCode 调度命令号
*/ */
public void send(Simulation simulation,String disCmdCode){ public void send(Simulation simulation,String disCmdCode){
@ -46,13 +51,13 @@ public class DisCmdService {
sc.setSendTime(this.getNow(simulation)); sc.setSendTime(this.getNow(simulation));
} }
/** /**
* 接收调度命令 * 通信服务器分发调度命令
*/ */
public void receiveLoop(Simulation simulation){ public void distributeLoop(Simulation simulation){
CtcRepository ctcRepository = simulation.getCtcRepository(); CtcRepository ctcRepository = simulation.getCtcRepository();
List<DisCmd> cmdList= ctcRepository.getDisCmdMap().values().stream().filter(cmd->{ List<DisCmd> cmdList = ctcRepository.getDisCmdMap().values().stream().filter(cmd->{
return DisCmdSendCompany.Status.Send.equals(cmd.getSendCompany().getState()) return DisCmdSendCompany.Status.Send.equals(cmd.getSendCompany().getState())
&&!cmd.getSendCompany().isExeSend();//令但未执行 &&!cmd.getSendCompany().isExeSend();//送但未分发
}).collect(Collectors.toList()); }).collect(Collectors.toList());
if(null!=cmdList){ if(null!=cmdList){
cmdList.forEach(cmd->{ cmdList.forEach(cmd->{
@ -87,7 +92,26 @@ public class DisCmdService {
* 车站自律机根据策略发送无线调令 * 车站自律机根据策略发送无线调令
*/ */
public void srmSendLoop(Simulation simulation){ public void srmSendLoop(Simulation simulation){
CtcRepository ctcRepository = simulation.getCtcRepository();
ctcRepository.getDisCmdMap().values().forEach(cmd->{
List<DisCmdRcvCompany> rcs= cmd.getRcvCompanies().stream().filter(rc->{
return DisCmdRcvCompany.Type.Train.equals(rc.getType())//无线调令
&&!rc.getTrainViaGsmR()//通过自律机中转
&&DisCmdRcvCompany.TransStatus.Received.equals(rc.getTransStatus())//已经到自律机收令箱
&&!rc.isExeTransSend();//尚未执行发送给机车
}).collect(Collectors.toList());
if(null!=rcs){
rcs.forEach(rc->{
//机车在自律机车站内
if(this.checkTrainInStation(simulation,rc.getTrainNum(),rc.getTrainCode(),rc.getTransStationCode())){
//自律机将调令转发给机车收令箱
rc.setExeTransSend(true);
rc.setState(DisCmdRcvCompany.Status.Received);
rc.setReceiveTime(this.getNow(simulation));
}
});
}
});
} }
/** /**
* 受令方收件箱收到调令后向前端发送通知来签收调令 * 受令方收件箱收到调令后向前端发送通知来签收调令
@ -95,34 +119,172 @@ public class DisCmdService {
* 注意当在一定时间内没有签收则须重发通知 * 注意当在一定时间内没有签收则须重发通知
*/ */
public void sendNotifyLoop(Simulation simulation){ public void sendNotifyLoop(Simulation simulation){
CtcRepository ctcRepository = simulation.getCtcRepository();
ctcRepository.getDisCmdMap().values().forEach(cmd->{
cmd.getRcvCompanies().forEach(rc->{
if(DisCmdRcvCompany.Status.Received.equals(rc.getState())){//未签收后调令
if(System.currentTimeMillis()>=rc.getTimeForNextReceiveNotify()){
rc.setLastSendReceiveNotifyTime(this.getNow(simulation));
rc.setCountForReceiveNotify(rc.getCountForReceiveNotify()+1);
rc.setTimeForNextReceiveNotify(System.currentTimeMillis()+10*1000);//10秒计算机系统时间间隔
this.sendNotifyToRcvCompany(simulation,rc);
}
}
});
});
} }
/** /**
* 处理前端发送来的签收指令 * 处理前端发送来的签收指令
* @param disCmdCode 调度命令号
* @param rcId 对于该调度命令的受令单位id
* @param signer 实际签收人(仿真成员)
*/ */
public void sign(Simulation simulation,String disCmdCode){ public void sign(Simulation simulation, String disCmdCode, String rcId, SimulationMember signer) {
DisCmd cmd = simulation.getCtcRepository().getDisCmdMap().get(disCmdCode);
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertTrue(null != cmd, String.format("仿真(%s),调度命令(%s)不存在", simulation.getId(), disCmdCode));
List<DisCmdRcvCompany> rcs = cmd.getRcvCompanies().stream().filter(rc -> { return rcId.equals(rc.getId()); }).collect(Collectors.toList());
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertTrue(null != rcs && !rcs.isEmpty(), String.format("仿真(%s),调度命令(%s)的受令单位(%s)不存在", simulation.getId(), disCmdCode, rcId));
DisCmdRcvCompany rc = rcs.get(0);
//
rc.setState(DisCmdRcvCompany.Status.Signed);
rc.setSignTime(this.getNow(simulation));
rc.setSignByReal(signer);
} }
/** /**
* 监控签收等 * 监控调度命令
* <p> * <p>
* 修改发送单位签收状态
*/ */
public void monitorLoop(Simulation simulation){ public void monitorLoop(Simulation simulation){
simulation.getCtcRepository().getDisCmdMap().values().forEach(cmd->{
DisCmdSendCompany sendCompany = cmd.getSendCompany();
//监控受令方签收情况来更新发令方签收状态
if(!DisCmdSendCompany.Status.Signed.equals(sendCompany.getState())){
boolean signed = true;
for(DisCmdRcvCompany rc:cmd.getRcvCompanies()){
if(!DisCmdRcvCompany.Status.Signed.equals(rc.getState())){
signed = false;
break;
}
}
if(signed){
sendCompany.setState(DisCmdSendCompany.Status.Signed);
sendCompany.setSignedTime(this.getNow(simulation));
}
}
//todo: 根据监控向前端推送其他通知
});
} }
/**
* 查询与持有者相关的调度命令
* @param holderType 持有者类型
* @param holderCode 持有者code,如调度台车站列控的code列车除了有code还有车次
* @param trainNum 车次当持有者类型为机车时才有效
*/
private FindAllDisCmdForHolderRspVo findAllForHolder(Simulation simulation, DisCmdHolderEnum holderType,String holderCode,String trainNum){
FindAllDisCmdForHolderRspVo rsp = new FindAllDisCmdForHolderRspVo();
simulation.getCtcRepository().getDisCmdMap().values().forEach(cmd->{
boolean hasCmd = false;
DisCmdSendCompany sc = cmd.getSendCompany();
List<DisCmdRcvCompany> rcs = cmd.getRcvCompanies();
//
if(DisCmdHolderEnum.Dispatcher.equals(holderType)){
//该调度命令的发送单位为该调度台
if(DisCmdSendCompany.Type.Dispatcher.equals(sc.getType())){
if(holderCode.equals(sc.getCode())){
rsp.getScList().add(DisCmdConvertor.convert(sc));
hasCmd = true;
}
}
//该调度命令的受令单位为该调度台
for(DisCmdRcvCompany rc:rcs){
if(DisCmdRcvCompany.Type.Dispatcher.equals(rc.getType())){
if(holderCode.equals(rc.getDisCode())){
rsp.getRcList().add(DisCmdConvertor.convert(rc));
hasCmd = true;
}
}
}
}else if(DisCmdHolderEnum.Station.equals(holderType)){
//该调度命令的发送单位为该车站
if(DisCmdSendCompany.Type.Station.equals(sc.getType())){
if(holderCode.equals(sc.getCode())){
rsp.getScList().add(DisCmdConvertor.convert(sc));
hasCmd = true;
}
}
//该调度命令的受令单位为该车站
for(DisCmdRcvCompany rc:rcs){
if(DisCmdRcvCompany.Type.Station.equals(rc.getType())){
if(holderCode.equals(rc.getStationCode())){
rsp.getRcList().add(DisCmdConvertor.convert(rc));
hasCmd = true;
}
}
}
}else if(DisCmdHolderEnum.Tsr.equals(holderType)){
//该调度命令的受令单位为该列控服务器
for(DisCmdRcvCompany rc:rcs){
if(DisCmdRcvCompany.Type.Tsr.equals(rc.getType())){
if(holderCode.equals(rc.getTsrCode())){
rsp.getRcList().add(DisCmdConvertor.convert(rc));
hasCmd = true;
}
}
}
}else if(DisCmdHolderEnum.Train.equals(holderType)){
//该调度命令的受令单位为该机车
for(DisCmdRcvCompany rc:rcs){
if(DisCmdRcvCompany.Type.Train.equals(rc.getType())){
if(holderCode.equals(rc.getTrainCode())&&trainNum.equals(rc.getTrainNum())){
rsp.getRcList().add(DisCmdConvertor.convert(rc));
hasCmd = true;
}
}
}
}
//
if(hasCmd){
DisCmdVo cmdVo = DisCmdConvertor.convert(cmd);
rsp.getCmdMap().put(cmdVo.getCode(),cmdVo);
}
});
return rsp;
}
//////////////////////////////////工具方法//////////////////////////////// //////////////////////////////////工具方法////////////////////////////////
/**
* 向受令单位的所有客户端(前端)推送通知来签收调令(仅仅发送通知)
* <p>
* 注意如果向列控服务器推送通知则系统自动处理通知签收
*/
private void sendNotifyToRcvCompany(Simulation simulation,DisCmdRcvCompany rc){
}
/**
* 判断机车是否在该车站内(todo:暂时不考虑上下行)
* @param stationCode 车站code
* @param trainNum 车次号
* @param trainCode 机车号
* @param simulation 仿真
*/
private boolean checkTrainInStation(Simulation simulation,String trainNum,String trainCode,String stationCode){
//todo
return true;
}
/** /**
* 根据调度命令号获取调度命令 * 根据调度命令号获取调度命令
*/ */
public DisCmd find(Simulation simulation,String disCmdCode){ private DisCmd find(Simulation simulation,String disCmdCode){
CtcRepository ctcRepository = simulation.getCtcRepository(); CtcRepository ctcRepository = simulation.getCtcRepository();
return ctcRepository.getDisCmdMap().get(disCmdCode); return ctcRepository.getDisCmdMap().get(disCmdCode);
} }
/** /**
* 获取仿真当前时间(暂时) * 获取仿真当前时间
*/ */
public LocalDateTime getNow(Simulation simulation){ private LocalDateTime getNow(Simulation simulation){
return LocalDateTime.now(); return simulation.getSystemTime();
} }
} }

View File

@ -0,0 +1,24 @@
package club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.convertor;
import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.DisCmd;
import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.DisCmdRcvCompany;
import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.DisCmdSendCompany;
import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo.DisCmdRcvCompanyVo;
import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo.DisCmdSendCompanyVo;
import club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo.DisCmdVo;
public class DisCmdConvertor {
public static DisCmdVo convert(DisCmd from){
return null;
}
public static DisCmdSendCompanyVo convert(DisCmdSendCompany from){
return null;
}
public static DisCmdRcvCompanyVo convert(DisCmdRcvCompany from){
return null;
}
}

View File

@ -0,0 +1,11 @@
package club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo;
/**
* 发令或受令实体类型
*/
public enum DisCmdHolderEnum {
Dispatcher,//调度台
Station,//车站
Train,//无线
Tsr,//列控服务器
;
}

View File

@ -0,0 +1,14 @@
package club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo;
import lombok.Data;
/**
* 受令单位
*/
@Data
public class DisCmdRcvCompanyVo {
/**
* 调度命令号(唯一)
*/
private String disCmdCode;
}

View File

@ -0,0 +1,14 @@
package club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo;
import lombok.Data;
/**
* 发令单位
*/
@Data
public class DisCmdSendCompanyVo {
/**
* 调度命令号(唯一)
*/
private String disCmdCode;
}

View File

@ -0,0 +1,15 @@
package club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo;
import lombok.Data;
@Data
public class DisCmdVo {
/**
* 标题
*/
private String title;
/**
* 调度命令号(唯一)
*/
private String code;
}

View File

@ -0,0 +1,27 @@
package club.joylink.rtss.simulation.cbtc.CTC.rail.cmd.vo;
import lombok.Data;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 为某个持有者返回与其相关的所有调度命令
*/
@Data
public class FindAllDisCmdForHolderRspVo {
/**
* 调度命令列表
*/
private Map<String, DisCmdVo> cmdMap = new HashMap<>();
/**
* 调度命令发令单位
*/
private List<DisCmdSendCompanyVo> scList = new ArrayList<>();
/**
* 调度命令受令单位
*/
private List<DisCmdRcvCompanyVo> rcList = new ArrayList<>();
}