新仿真逻辑——虚拟真实设备逻辑开发
This commit is contained in:
parent
9681255916
commit
8da937e941
@ -42,7 +42,7 @@ public abstract class Simulation<U extends SimulationUser, M extends Simulation
|
|||||||
* 仿真状态
|
* 仿真状态
|
||||||
*/
|
*/
|
||||||
private final AtomicInteger state = new AtomicInteger(PAUSE);
|
private final AtomicInteger state = new AtomicInteger(PAUSE);
|
||||||
private static final int RUNNING = 1;
|
private static final int START = 1;
|
||||||
private static final int PAUSE = 0;
|
private static final int PAUSE = 0;
|
||||||
private static final int ERROR = -1;
|
private static final int ERROR = -1;
|
||||||
/**
|
/**
|
||||||
@ -84,29 +84,11 @@ public abstract class Simulation<U extends SimulationUser, M extends Simulation
|
|||||||
this.id = id;
|
this.id = id;
|
||||||
this.speed = speed;
|
this.speed = speed;
|
||||||
this.systemTime = LocalDateTime.now();
|
this.systemTime = LocalDateTime.now();
|
||||||
|
this.runAsSpeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
Simulation simulation = new Simulation("1") {
|
|
||||||
@Override
|
|
||||||
public String debugStr() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
simulation.addJob("b", () -> {
|
|
||||||
log.info("logic");
|
|
||||||
}, 500);
|
|
||||||
simulation.addFixedRateJob("c", () -> {
|
|
||||||
log.warn("fixed");
|
|
||||||
}, 1000);
|
|
||||||
simulation.updateSpeed(5);
|
|
||||||
simulation.start();
|
|
||||||
}
|
|
||||||
private void runAsSpeed() {
|
private void runAsSpeed() {
|
||||||
if (this.future == null) {
|
if (this.future == null) {
|
||||||
// if (!this.future.cancel(false)) {
|
|
||||||
// log.error(String.format("仿真旧主线程无法取消"));
|
|
||||||
// }
|
|
||||||
ScheduledFuture<?> scheduledFuture = EXECUTOR.scheduleAtFixedRate(()->this.logic(),
|
ScheduledFuture<?> scheduledFuture = EXECUTOR.scheduleAtFixedRate(()->this.logic(),
|
||||||
this.SYSTEM_TIME_RATE, this.SYSTEM_TIME_RATE, TimeUnit.MILLISECONDS);
|
this.SYSTEM_TIME_RATE, this.SYSTEM_TIME_RATE, TimeUnit.MILLISECONDS);
|
||||||
this.future = scheduledFuture;
|
this.future = scheduledFuture;
|
||||||
@ -119,7 +101,7 @@ public abstract class Simulation<U extends SimulationUser, M extends Simulation
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void logic() {
|
private void logic() {
|
||||||
if (!this.isRunning()) {
|
if (!this.isStart() || this.isRunning()) { // 仿真未开始或者之前逻辑运行未结束,确保仿真不同步执行
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@ -145,6 +127,10 @@ public abstract class Simulation<U extends SimulationUser, M extends Simulation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isRunning() {
|
||||||
|
return this.mainLogicRunning.get();
|
||||||
|
}
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
@ -235,8 +221,7 @@ public abstract class Simulation<U extends SimulationUser, M extends Simulation
|
|||||||
* 控制-开始
|
* 控制-开始
|
||||||
*/
|
*/
|
||||||
public void start() {
|
public void start() {
|
||||||
this.state.set(RUNNING);
|
this.state.set(START);
|
||||||
this.runAsSpeed();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -260,8 +245,8 @@ public abstract class Simulation<U extends SimulationUser, M extends Simulation
|
|||||||
return this.state.get();
|
return this.state.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRunning() {
|
public boolean isStart() {
|
||||||
return this.state.get() == RUNNING;
|
return this.state.get() == START;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -279,7 +264,7 @@ public abstract class Simulation<U extends SimulationUser, M extends Simulation
|
|||||||
this.speed = speed;
|
this.speed = speed;
|
||||||
int state = this.state.get();
|
int state = this.state.get();
|
||||||
this.pause();
|
this.pause();
|
||||||
this.runAsSpeed();
|
this.updateTimeUpdateSpeed(this.speed);
|
||||||
for (SimulationScheduledJob job : this.scheduledJobMap.values()) {
|
for (SimulationScheduledJob job : this.scheduledJobMap.values()) {
|
||||||
job.updateRunPeriod(speed);
|
job.updateRunPeriod(speed);
|
||||||
}
|
}
|
||||||
|
@ -7,12 +7,16 @@ import club.joylink.rtss.vo.client.map.MapVO;
|
|||||||
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.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
public class SrdService {
|
public class SrdService {
|
||||||
public static final int TRAIN_RUN_RATE = 20;
|
public static final int TRAIN_RUN_RATE = 20; // 列车运行逻辑频率
|
||||||
|
public static final int DEVICE_RUN_RATE = 500; // 其他设备逻辑频率
|
||||||
|
|
||||||
public void buildRepository(RtSimulation rtSimulation, MapVO mapVO) {
|
public void buildRepository(RtSimulation rtSimulation, MapVO mapVO) {
|
||||||
SrdRepository srdRepository = SrdRepositoryBuilder.buildFrom(mapVO);
|
SrdRepository srdRepository = SrdRepositoryBuilder.buildFrom(mapVO);
|
||||||
@ -23,6 +27,42 @@ public class SrdService {
|
|||||||
rtSimulation.addJob("srTrainRun",
|
rtSimulation.addJob("srTrainRun",
|
||||||
() -> this.srTrainRun(rtSimulation.getRepository(SrdRepository.NAME, SrdRepository.class)),
|
() -> this.srTrainRun(rtSimulation.getRepository(SrdRepository.NAME, SrdRepository.class)),
|
||||||
TRAIN_RUN_RATE);
|
TRAIN_RUN_RATE);
|
||||||
|
rtSimulation.addJob("srDeviceLogic",
|
||||||
|
() -> this.srDeviceLogic(rtSimulation.getRepository(SrdRepository.NAME, SrdRepository.class), rtSimulation.getSystemTime()),
|
||||||
|
DEVICE_RUN_RATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void srDeviceLogic(SrdRepository repository, LocalDateTime systemTime) {
|
||||||
|
// 道岔转动
|
||||||
|
List<SrTurnout> turnoutList = repository.getTurnoutList();
|
||||||
|
for (SrTurnout turnout : turnoutList) {
|
||||||
|
if (turnout.isControlByReal()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (turnout.isTurning()) {
|
||||||
|
turnout.tryFinishTurning(systemTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 屏蔽门开/闭
|
||||||
|
List<SrPSD> psdList = repository.getPsdList();
|
||||||
|
for (SrPSD psd : psdList) {
|
||||||
|
if (psd.isControlByReal()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (psd.isTurning()) {
|
||||||
|
psd.tryFinishTurning(systemTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 信号机控制
|
||||||
|
List<SrSignal> signalList = repository.getSignalList();
|
||||||
|
for (SrSignal signal : signalList) {
|
||||||
|
if (signal.isControlByReal()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (signal.isTurning()) {
|
||||||
|
signal.tryFinishTurning(systemTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void srTrainRun(SrdRepository repository) {
|
public void srTrainRun(SrdRepository repository) {
|
||||||
@ -31,20 +71,35 @@ public class SrdService {
|
|||||||
if (!srTrain.isUsing()) {
|
if (!srTrain.isUsing()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
TrackPosition position = srTrain.getHeadPosition();
|
// 计算列车加速度,更新列车速度,计算列车运行距离,更新列车位置
|
||||||
boolean right = srTrain.isRight();
|
boolean right = srTrain.isRight();
|
||||||
|
TrackPosition position = srTrain.getHeadPosition();
|
||||||
int cv = this.calculateSpeed(srTrain);
|
int cv = this.calculateSpeed(srTrain);
|
||||||
int s = this.calculateLen(cv, TRAIN_RUN_RATE);
|
int s = this.calculateLen(srTrain, cv, TRAIN_RUN_RATE);
|
||||||
TrackPosition np = calculatePosition(position, s, right);
|
TrackPosition np = calculatePosition(position, s, right, new HashSet<>());
|
||||||
if (np.equals(position) && cv != 0) {
|
if (np.equals(position) && cv != 0) {
|
||||||
cv = 0;
|
cv = 0;
|
||||||
}
|
}
|
||||||
srTrain.updatePositionAndSpeed(np, cv);
|
Set<SrTrack> occupiedTrackSet = new HashSet<>();
|
||||||
|
TrackPosition tailPosition = this.calculatePosition(np, srTrain.getLen(), !right, occupiedTrackSet);
|
||||||
|
srTrain.updatePositionAndSpeed(np, tailPosition, cv);
|
||||||
|
// 更新计轴占用
|
||||||
|
Set<SrTrack> oldOccupiedTrackSet = new HashSet<>();
|
||||||
|
this.calculatePosition(position, srTrain.getLen(), !right, oldOccupiedTrackSet);
|
||||||
|
Set<SrTrack> clearList = new HashSet<>(oldOccupiedTrackSet);
|
||||||
|
clearList.removeAll(occupiedTrackSet);
|
||||||
|
for (SrTrack srTrack : clearList) {
|
||||||
|
srTrack.getAxc().clear();
|
||||||
|
}
|
||||||
|
for (SrTrack srTrack : occupiedTrackSet) {
|
||||||
|
srTrack.getAxc().occupy();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int calculateLen(int cv, int time) {
|
private int calculateLen(SrTrain srTrain, int cv, int time) {
|
||||||
return cv * time;
|
int s = cv * time;
|
||||||
|
return s * srTrain.getGear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int calculateSpeed(SrTrain srTrain) {
|
private int calculateSpeed(SrTrain srTrain) {
|
||||||
@ -61,10 +116,21 @@ public class SrdService {
|
|||||||
if (cv < 0) {
|
if (cv < 0) {
|
||||||
cv = 0;
|
cv = 0;
|
||||||
}
|
}
|
||||||
|
if (srTrain.isNeutralGear() && cv > 0) { // 空档位
|
||||||
|
cv = 0;
|
||||||
|
}
|
||||||
return cv;
|
return cv;
|
||||||
}
|
}
|
||||||
|
|
||||||
private TrackPosition calculatePosition(TrackPosition position, int s, boolean right) {
|
/**
|
||||||
|
*
|
||||||
|
* @param position 起始位置
|
||||||
|
* @param s 距离
|
||||||
|
* @param right 方向
|
||||||
|
* @param trackSet 从position往方向[right]经过距离[s]所经过的轨道列表
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private TrackPosition calculatePosition(TrackPosition position, int s, boolean right, Set<SrTrack> trackSet) {
|
||||||
if (s == 0) {
|
if (s == 0) {
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
@ -76,7 +142,11 @@ public class SrdService {
|
|||||||
offset -= s;
|
offset -= s;
|
||||||
}
|
}
|
||||||
SrTrack base = track;
|
SrTrack base = track;
|
||||||
|
trackSet.add(base);
|
||||||
|
int iter = 0;
|
||||||
while (offset < 0 || offset > base.getLen()) {
|
while (offset < 0 || offset > base.getLen()) {
|
||||||
|
BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.assertTrue(iter < 10);
|
||||||
|
++iter;
|
||||||
SrTrack nextTrack = base.queryNextTrack(right);
|
SrTrack nextTrack = base.queryNextTrack(right);
|
||||||
if (nextTrack == null) { // 下一区段为空,到达尽头或道岔失表处
|
if (nextTrack == null) { // 下一区段为空,到达尽头或道岔失表处
|
||||||
log.debug(String.format("区段[%s][%s]区段不存在",base.debugStr(), right?"右向":"左向"));
|
log.debug(String.format("区段[%s][%s]区段不存在",base.debugStr(), right?"右向":"左向"));
|
||||||
@ -95,6 +165,7 @@ public class SrdService {
|
|||||||
offset += nextTrack.getLen();
|
offset += nextTrack.getLen();
|
||||||
}
|
}
|
||||||
base = nextTrack;
|
base = nextTrack;
|
||||||
|
trackSet.add(nextTrack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new TrackPosition(base, offset);
|
return new TrackPosition(base, offset);
|
||||||
|
@ -14,4 +14,19 @@ public class SrAXC extends SrDevice {
|
|||||||
public SrAXC(String id) {
|
public SrAXC(String id) {
|
||||||
super(id, DeviceType.AXC);
|
super(id, DeviceType.AXC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
this.state.set(OFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void occupy() {
|
||||||
|
if (this.state.get() != ON) {
|
||||||
|
this.state.set(ON);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyState(int state) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,8 @@ package club.joylink.rtss.simulation.rt.srd.bo;
|
|||||||
import club.joylink.rtss.simulation.Debug;
|
import club.joylink.rtss.simulation.Debug;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 虚拟真实设备抽象父类
|
* 虚拟真实设备抽象父类
|
||||||
*/
|
*/
|
||||||
@ -10,6 +12,10 @@ import lombok.Getter;
|
|||||||
public abstract class SrDevice implements Debug {
|
public abstract class SrDevice implements Debug {
|
||||||
String id;
|
String id;
|
||||||
DeviceType deviceType;
|
DeviceType deviceType;
|
||||||
|
/**
|
||||||
|
* 是否由真实设备控制
|
||||||
|
*/
|
||||||
|
boolean controlByReal;
|
||||||
|
|
||||||
public SrDevice() {}
|
public SrDevice() {}
|
||||||
|
|
||||||
@ -18,8 +24,23 @@ public abstract class SrDevice implements Debug {
|
|||||||
this.deviceType = deviceType;
|
this.deviceType = deviceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract void applyState(int state);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String debugStr() {
|
public String debugStr() {
|
||||||
return String.format("%s:%s", this.deviceType, this.id);
|
return String.format("%s:%s", this.deviceType, this.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
SrDevice srDevice = (SrDevice) o;
|
||||||
|
return Objects.equals(id, srDevice.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package club.joylink.rtss.simulation.rt.srd.bo;
|
package club.joylink.rtss.simulation.rt.srd.bo;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -11,19 +13,56 @@ public class SrPSD extends SrDevice {
|
|||||||
AtomicInteger state = new AtomicInteger(CLOSE_LOCK);
|
AtomicInteger state = new AtomicInteger(CLOSE_LOCK);
|
||||||
public static final int CLOSE_LOCK = 1;//关闭且锁闭
|
public static final int CLOSE_LOCK = 1;//关闭且锁闭
|
||||||
public static final int CLOSED = 2;//关闭未锁闭
|
public static final int CLOSED = 2;//关闭未锁闭
|
||||||
public static final int OPEN = 3;//打开未到位
|
public static final int TURNING = 3;//转换中
|
||||||
public static final int OPEN_FINISH = 4;//打开到位
|
public static final int OPEN_FINISH = 4;//打开到位
|
||||||
|
|
||||||
AtomicInteger command = new AtomicInteger(NONE);
|
AtomicInteger command = new AtomicInteger(NONE);
|
||||||
public static final int NONE = 0;//无动作
|
public static final int NONE = 0;//无动作
|
||||||
public static final int C_OPEN = 1;//控制开门
|
|
||||||
public static final int C_CLOSE = 2;//控制关门
|
|
||||||
/**
|
/**
|
||||||
* 剩余动作时间
|
* 转换完成时间
|
||||||
*/
|
*/
|
||||||
int remain;
|
LocalDateTime finishTime;
|
||||||
|
|
||||||
public SrPSD(String id) {
|
public SrPSD(String id) {
|
||||||
super(id, DeviceType.PSD);
|
super(id, DeviceType.PSD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isTurning() {
|
||||||
|
return NONE != this.command.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void open(LocalDateTime systemTime) {
|
||||||
|
this.startTurn(systemTime, OPEN_FINISH);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close(LocalDateTime systemTime) {
|
||||||
|
this.startTurn(systemTime, CLOSE_LOCK);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startTurn(LocalDateTime systemTime, int command) {
|
||||||
|
this.finishTime = systemTime.plusNanos(TimeUnit.MILLISECONDS.toNanos(turnTime));
|
||||||
|
this.command.set(command);
|
||||||
|
this.state.set(TURNING);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tryFinishTurning(LocalDateTime systemTime) {
|
||||||
|
if (this.finishTime != null && systemTime.compareTo(this.finishTime) >= 0) {
|
||||||
|
this.turnFinish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void turnFinish() {
|
||||||
|
this.state.set(this.command.get());
|
||||||
|
this.command.set(NONE);
|
||||||
|
this.finishTime = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyState(int state) {
|
||||||
|
if (CLOSE_LOCK == state || CLOSED == state || TURNING == state || OPEN_FINISH == state) {
|
||||||
|
this.state.set(state);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException(String.format("无效的屏蔽门状态:[%s]", state));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@ package club.joylink.rtss.simulation.rt.srd.bo;
|
|||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -9,6 +11,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
public class SrSignal extends SrDevice {
|
public class SrSignal extends SrDevice {
|
||||||
|
public static final int turnTime = 500; // 默认转换时间,单位ms
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 所在区段
|
* 所在区段
|
||||||
@ -20,19 +23,18 @@ public class SrSignal extends SrDevice {
|
|||||||
int offset;
|
int offset;
|
||||||
|
|
||||||
AtomicInteger state = new AtomicInteger(CLOSE);
|
AtomicInteger state = new AtomicInteger(CLOSE);
|
||||||
public static final int CLOSE = 1;
|
public static final int CLOSE = 1; // 关闭
|
||||||
public static final int RED = 2;
|
public static final int RED = 2; // 红灯信号(禁止信号)
|
||||||
public static final int GREEN = 3;
|
public static final int GREEN = 3; // 绿灯信号(直向通行)
|
||||||
public static final int YELLOW = 4;
|
public static final int YELLOW = 4; // 黄灯信号(侧向通行)
|
||||||
public static final int RED_YELLOW = 5;
|
public static final int GUIDE = 5; // 引导信号(正线为黄红)
|
||||||
|
|
||||||
AtomicInteger command = new AtomicInteger(C_NONE);
|
AtomicInteger command = new AtomicInteger(NONE);
|
||||||
public static final int C_NONE = 0;
|
public static final int NONE = 0;
|
||||||
public static final int C_CLOSE = 1;
|
/**
|
||||||
public static final int C_RED = 2;
|
* 转换完成时间
|
||||||
public static final int C_GREEN = 3;
|
*/
|
||||||
public static final int C_YELLOW = 4;
|
LocalDateTime finishTime;
|
||||||
public static final int C_RED_YELLOW = 5;
|
|
||||||
|
|
||||||
public SrSignal(String id) {
|
public SrSignal(String id) {
|
||||||
super(id, DeviceType.SIGNAL);
|
super(id, DeviceType.SIGNAL);
|
||||||
@ -42,4 +44,53 @@ public class SrSignal extends SrDevice {
|
|||||||
this.track = srTrack;
|
this.track = srTrack;
|
||||||
this.offset = offset;
|
this.offset = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isTurning() {
|
||||||
|
return NONE != this.command.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close(LocalDateTime systemTime) {
|
||||||
|
this.startTurn(systemTime, CLOSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void openRed(LocalDateTime systemTime) {
|
||||||
|
this.startTurn(systemTime, RED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void openGreen(LocalDateTime systemTime) {
|
||||||
|
this.startTurn(systemTime, GREEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void openYellow(LocalDateTime systemTime) {
|
||||||
|
this.startTurn(systemTime, YELLOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void openGuide(LocalDateTime systemTime) {
|
||||||
|
this.startTurn(systemTime, GUIDE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startTurn(LocalDateTime systemTime, int command) {
|
||||||
|
this.finishTime = systemTime.plusNanos(TimeUnit.MILLISECONDS.toNanos(turnTime));
|
||||||
|
this.command.set(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tryFinishTurning(LocalDateTime systemTime) {
|
||||||
|
if (this.finishTime != null && systemTime.compareTo(this.finishTime) >= 0) {
|
||||||
|
this.turnFinish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void turnFinish() {
|
||||||
|
this.state.set(this.command.get());
|
||||||
|
this.command.set(NONE);
|
||||||
|
this.finishTime = null;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void applyState(int state) {
|
||||||
|
if (CLOSE == state || RED == state || GREEN == state || YELLOW == state || GUIDE == state) {
|
||||||
|
this.state.set(state);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException(String.format("无效的道岔状态:[%s]", state));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,14 +14,6 @@ public class SrTrack extends SrDevice implements Debug {
|
|||||||
* 轨道长度,单位mm
|
* 轨道长度,单位mm
|
||||||
*/
|
*/
|
||||||
int len;
|
int len;
|
||||||
/**
|
|
||||||
* 左停车点,单位mm
|
|
||||||
*/
|
|
||||||
int leftPs;
|
|
||||||
/**
|
|
||||||
* 右停车点,单位mm
|
|
||||||
*/
|
|
||||||
int rightPs;
|
|
||||||
/**
|
/**
|
||||||
* 计轴器
|
* 计轴器
|
||||||
*/
|
*/
|
||||||
@ -104,8 +96,14 @@ public class SrTrack extends SrDevice implements Debug {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyState(int state) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String debugStr() {
|
public String debugStr() {
|
||||||
return String.format("%s(%s)", this.name, this.id);
|
return String.format("%s(%s)", this.name, this.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ public class SrTrain extends SrDevice {
|
|||||||
/**
|
/**
|
||||||
* 档位
|
* 档位
|
||||||
*/
|
*/
|
||||||
int gear = NEUTRAL;
|
int gear;
|
||||||
public static final int NEUTRAL = 0; //空挡
|
public static final int NEUTRAL = 0; //空挡
|
||||||
public static final int FORWARD = 1; //前进挡
|
public static final int FORWARD = 1; //前进挡
|
||||||
public static final int REVERSE = -1; //后退档
|
public static final int REVERSE = -1; //后退档
|
||||||
@ -72,8 +72,14 @@ public class SrTrain extends SrDevice {
|
|||||||
return NEUTRAL == this.gear;
|
return NEUTRAL == this.gear;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updatePositionAndSpeed(TrackPosition position, int v) {
|
public void updatePositionAndSpeed(TrackPosition headPosition, TrackPosition tailPosition, int v) {
|
||||||
this.headPosition = position;
|
this.headPosition = headPosition;
|
||||||
|
this.tailPosition = tailPosition;
|
||||||
this.speed = v;
|
this.speed = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyState(int state) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package club.joylink.rtss.simulation.rt.srd.bo;
|
package club.joylink.rtss.simulation.rt.srd.bo;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -19,12 +21,10 @@ public class SrTurnout extends SrDevice {
|
|||||||
|
|
||||||
AtomicInteger command = new AtomicInteger(NONE);
|
AtomicInteger command = new AtomicInteger(NONE);
|
||||||
public static final int NONE = 0;
|
public static final int NONE = 0;
|
||||||
public static final int TN = 1; // 定操/转动到定位
|
|
||||||
public static final int TR = 2; // 反操/转动到反位
|
|
||||||
/**
|
/**
|
||||||
* 转换剩余时间,单位ms
|
* 转换完成时间
|
||||||
*/
|
*/
|
||||||
int remain;
|
LocalDateTime finishTime;
|
||||||
|
|
||||||
public SrTurnout(String id) {
|
public SrTurnout(String id) {
|
||||||
super(id, DeviceType.TURNOUT);
|
super(id, DeviceType.TURNOUT);
|
||||||
@ -53,4 +53,43 @@ public class SrTurnout extends SrDevice {
|
|||||||
public boolean isReversePosition() {
|
public boolean isReversePosition() {
|
||||||
return REVERSE == this.state.get();
|
return REVERSE == this.state.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isTurning() {
|
||||||
|
return NONE != this.command.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void turnToNormal(LocalDateTime systemTime) {
|
||||||
|
this.startTurn(systemTime, NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void turnToReverse(LocalDateTime systemTime) {
|
||||||
|
this.startTurn(systemTime, REVERSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startTurn(LocalDateTime systemTime, int command) {
|
||||||
|
this.finishTime = systemTime.plusNanos(TimeUnit.MILLISECONDS.toNanos(turnTime));
|
||||||
|
this.command.set(command);
|
||||||
|
this.state.set(TURNING);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tryFinishTurning(LocalDateTime systemTime) {
|
||||||
|
if (this.finishTime != null && systemTime.compareTo(this.finishTime) >= 0) {
|
||||||
|
this.turnFinish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void turnFinish() {
|
||||||
|
this.state.set(this.command.get());
|
||||||
|
this.command.set(NONE);
|
||||||
|
this.finishTime = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyState(int state) {
|
||||||
|
if (NORMAL == state || REVERSE == state || TURNING == state) {
|
||||||
|
this.state.set(state);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException(String.format("无效的道岔状态:[%s]", state));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,18 @@ public class SrdRepository extends SimulationRepository {
|
|||||||
return new ArrayList<>(this.trainMap.values());
|
return new ArrayList<>(this.trainMap.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<SrTurnout> getTurnoutList() {
|
||||||
|
return new ArrayList<>(this.turnoutMap.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SrPSD> getPsdList() {
|
||||||
|
return new ArrayList<>(this.psdMap.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SrSignal> getSignalList() {
|
||||||
|
return new ArrayList<>(this.signalMap.values());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initState() {
|
public void initState() {
|
||||||
|
|
||||||
|
@ -2,6 +2,9 @@ package club.joylink.rtss.simulation.rt.srd.bo;
|
|||||||
|
|
||||||
public class TrackPosition {
|
public class TrackPosition {
|
||||||
SrTrack track;
|
SrTrack track;
|
||||||
|
/**
|
||||||
|
* 轨道偏移量,单位mm
|
||||||
|
*/
|
||||||
int offset;
|
int offset;
|
||||||
|
|
||||||
public TrackPosition(SrTrack track, int offset) {
|
public TrackPosition(SrTrack track, int offset) {
|
||||||
|
@ -5,6 +5,7 @@ import club.joylink.rtss.services.LoginSessionManager;
|
|||||||
import club.joylink.rtss.vo.LoginUserInfoVO;
|
import club.joylink.rtss.vo.LoginUserInfoVO;
|
||||||
import club.joylink.rtss.vo.UserVO;
|
import club.joylink.rtss.vo.UserVO;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.server.ServerHttpRequest;
|
import org.springframework.http.server.ServerHttpRequest;
|
||||||
import org.springframework.http.server.ServerHttpResponse;
|
import org.springframework.http.server.ServerHttpResponse;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
@ -34,6 +35,7 @@ public class SessionAuthHandshakeInterceptor implements HandshakeInterceptor {
|
|||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
log.error("未登录或登陆已过期", e);
|
log.error("未登录或登陆已过期", e);
|
||||||
}
|
}
|
||||||
|
response.setStatusCode(HttpStatus.UNAUTHORIZED);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,5 +73,6 @@ public class SessionAuthHandshakeInterceptor implements HandshakeInterceptor {
|
|||||||
@Override
|
@Override
|
||||||
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
|
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
|
||||||
Exception exception) {
|
Exception exception) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
package club.joylink.rtss.websocket.client;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.messaging.simp.stomp.StompCommand;
|
||||||
|
import org.springframework.messaging.simp.stomp.StompHeaders;
|
||||||
|
import org.springframework.messaging.simp.stomp.StompSession;
|
||||||
|
import org.springframework.messaging.simp.stomp.StompSessionHandler;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class SimulationSessionHandler implements StompSessionHandler {
|
||||||
|
@Override
|
||||||
|
public void afterConnected(StompSession session, StompHeaders connectedHeaders) {
|
||||||
|
log.debug(String.format("stomp websocket connected"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleException(StompSession session, StompCommand command, StompHeaders headers, byte[] payload, Throwable exception) {
|
||||||
|
log.error("stomp handle exception", exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleTransportError(StompSession session, Throwable exception) {
|
||||||
|
log.error("stomp handle transport error", exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getPayloadType(StompHeaders headers) {
|
||||||
|
return String.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleFrame(StompHeaders headers, Object payload) {
|
||||||
|
String json = (String) payload;
|
||||||
|
log.debug(String.format("receive frame:%s", json));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package club.joylink.rtss.websocket.client;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.messaging.simp.stomp.StompSession;
|
||||||
|
import org.springframework.util.concurrent.ListenableFuture;
|
||||||
|
import org.springframework.web.socket.client.standard.StandardWebSocketClient;
|
||||||
|
import org.springframework.web.socket.messaging.WebSocketStompClient;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class StompClientManager {
|
||||||
|
|
||||||
|
// private static final Map<String, StompClientSupport> stompClientMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public static void main(String[] args) throws ExecutionException, InterruptedException {
|
||||||
|
StandardWebSocketClient socketClient = new StandardWebSocketClient();
|
||||||
|
WebSocketStompClient stompClient = new WebSocketStompClient(socketClient);
|
||||||
|
SimulationSessionHandler handler = new SimulationSessionHandler();
|
||||||
|
ListenableFuture<StompSession> future = stompClient
|
||||||
|
.connect("ws://192.168.8.129:9000/joylink-websocket?token=aaa",
|
||||||
|
handler, "null");
|
||||||
|
StompSession stompSession = future.get();
|
||||||
|
stompSession.subscribe("/user/queue/simulation/1/", handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user