Merge remote-tracking branch 'origin/test' into test

This commit is contained in:
joylink_zhangsai 2020-12-30 10:42:52 +08:00
commit 7dd24fd938
28 changed files with 692 additions and 65 deletions

View File

@ -0,0 +1,40 @@
package club.joylink.rtss.configuration.configProp;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix="spring.mail")
public class MailConfig {
private String host;
private String username;
private String password;
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}

View File

@ -1,5 +1,6 @@
package club.joylink.rtss.services;
import club.joylink.rtss.configuration.configProp.MailConfig;
import club.joylink.rtss.configuration.configProp.OtherConfig;
import club.joylink.rtss.constants.BusinessConsts;
import club.joylink.rtss.constants.EmailSubject;
@ -29,8 +30,8 @@ public class EmailService implements IEmailService {
@Autowired
private JavaMailSender mailSender; //自动注入的Bean
// @Autowired
// private MailConfig mailConfig;
@Autowired
private MailConfig mailConfig;
@Autowired
private ISysUserService sysUserService;
@ -41,7 +42,7 @@ public class EmailService implements IEmailService {
@Override
public void sendToOne(String toUser, String subject, String content) {
SimpleMailMessage smm = new SimpleMailMessage();
// smm.setFrom(this.mailConfig.getUsername());
smm.setFrom(this.mailConfig.getUsername());
smm.setTo(toUser);
smm.setSubject(subject);
smm.setText(content);

View File

@ -12,6 +12,7 @@ import club.joylink.rtss.services.runplan.IRunPlanUserConfigService;
import club.joylink.rtss.simulation.cbtc.GroupSimulationService;
import club.joylink.rtss.simulation.cbtc.build.RunPlanBuilder;
import club.joylink.rtss.simulation.cbtc.build.SimulationBuilder;
import club.joylink.rtss.simulation.cbtc.constant.SimulationConstants;
import club.joylink.rtss.simulation.cbtc.data.map.MapElement;
import club.joylink.rtss.util.JsonUtils;
import club.joylink.rtss.vo.LoginUserInfoVO;
@ -481,7 +482,7 @@ public class RunPlanDraftService implements IRunPlanDraftService {
RunPlanVO planVO = getRunPlanById(planId);
MapVO mapVO = this.iMapService.getMapDetail(planVO.getMapId());
if (Objects.nonNull(inputData.getDepartureInterval())) {
String max = planVO.getTripList().stream().map(RunPlanTripVO::getServiceNumber).max(Comparator.naturalOrder()).orElse("0");
String max = planVO.getTripList().stream().map(RunPlanTripVO::getServiceNumber).max(Comparator.comparingInt(Integer::parseInt)).orElse("0");
// 当前已有最大服务号
int maxServiceNumber = Integer.parseInt(max);
inputData.setServiceNumber(String.format("%03d", ++maxServiceNumber));
@ -537,7 +538,7 @@ public class RunPlanDraftService implements IRunPlanDraftService {
// 数据校验
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertTrue(serviceConfig.getTimes() > 0 && serviceConfig.getIntervals() >= 30);
RunPlanVO planVO = getRunPlanById(planId);
String max = planVO.getTripList().stream().map(RunPlanTripVO::getServiceNumber).max(Comparator.naturalOrder()).orElse("");
String max = planVO.getTripList().stream().map(RunPlanTripVO::getServiceNumber).max(Comparator.comparingInt(Integer::parseInt)).orElse("");
// 查询最大服务号
int maxServiceNumber = Integer.parseInt(max);
List<RunPlanTripVO> tripVOList = planVO.getTripList().stream()
@ -746,7 +747,12 @@ public class RunPlanDraftService implements IRunPlanDraftService {
}
tripVO.setServiceNumber(serviceNumber);
tripVO.setTripNumber(tripVO.getDirectionCode() + tripNumber);
tripConfig.getArriveConfigList().stream().map(RunPlanTripTimeVO::new).forEach(timeVO -> tripVO.getTimeList().add(timeVO));
tripConfig.getArriveConfigList().stream().map(RunPlanTripTimeVO::new).sorted(Comparator.comparing(RunPlanTripTimeVO::getArrivalTime)).forEach(timeVO -> tripVO.getTimeList().add(timeVO));
if (Objects.equals(tripVO.getEndSectionCode(), (new LinkedList<> (tripVO.getTimeList())).getLast().getSectionCode())) {
tripVO.setEndTime(tripConfig.getEndTime().minusHours(SimulationConstants.RUN_DIAGRAM_TRANS_TIME));
}
if (CollectionUtils.isEmpty(runPlanVO.getTripList())) {
runPlanVO.setTripList(new ArrayList<>());
}
@ -915,13 +921,17 @@ public class RunPlanDraftService implements IRunPlanDraftService {
return errorList;
}
MapVO map = this.iMapService.getMapDetail(planVO.getMapId());
SimulationBuilder.SimulationDeviceBuildResult buildResult = SimulationBuilder.checkAndBuildMapDeviceData(map);
SimulationBuilder.SimulationDeviceBuildResult buildResult = SimulationBuilder.checkAndBuildMapData(map);
BusinessExceptionAssertEnum.DATA_ERROR.assertCollectionEmpty(buildResult.getErrMsgList(),
"地图基础数据校验不通过");
Map<String, MapElement> deviceMap = buildResult.getDeviceMap();
RunPlanBuilder.RunPlanBuildResult runPlanBuildResult =
RunPlanBuilder.buildRunDiagram(deviceMap, planVO);
//先屏蔽掉数据检查
if(runPlanBuildResult.getErrMsgList().isEmpty()){
List<String> errMsgList = SimulationBuilder.checkRunPlanAndBuildLostRoutePaths(runPlanBuildResult.getServerTripMap(),
buildResult.getRoutePathMap());
return errMsgList;
}
return runPlanBuildResult.getErrMsgList();
}

View File

@ -333,8 +333,10 @@ public class RunPlanGenerator {
otherTripRunTime = otherTripRunTime + parkTime + runTime;
}
if (same ? true :
(temp.getLastStationDepartTime().plusSeconds(inputData.getReentryTime()/2 + inboundTripRunTime).isBefore(inputData.getOverTime())
&& temp.getLastStationDepartTime().plusSeconds(inputData.getReentryTime()/2 + outRefTripRunTime + otherTripRunTime + inboundTripRunTime).getHour()>3)) {
(temp.getLastStationDepartTime().plusSeconds(inputData.getReentryTime()/2 + inboundTripRunTime).isBefore(inputData.getOverTime()) &&
(temp.getLastStationDepartTime().plusSeconds(inputData.getReentryTime()/2).getHour()<3
|| temp.getLastStationDepartTime().plusSeconds(inputData.getReentryTime()/2 + outRefTripRunTime + otherTripRunTime + inboundTripRunTime).getHour()>3))
) {
//构建环路车次
boolean loop = false;
do {
@ -352,7 +354,8 @@ public class RunPlanGenerator {
}
}
while (temp.getLastStationDepartTime().plusSeconds(inputData.getReentryTime()/2 + inboundTripRunTime).isBefore(inputData.getOverTime())
&& temp.getLastStationDepartTime().plusSeconds(inputData.getReentryTime()/2 + outRefTripRunTime + otherTripRunTime + inboundTripRunTime).getHour()>3);
&&
(temp.getLastStationDepartTime().plusSeconds(inputData.getReentryTime()/2).getHour()<3||temp.getLastStationDepartTime().plusSeconds(inputData.getReentryTime()/2 + outRefTripRunTime + otherTripRunTime + inboundTripRunTime).getHour()>3));
}
//构建回库计划
buildServiceTrips(inputData, mapVO, inboundRouting, false, runLevelMap, parkTimeMap, userReentryData, serviceTripList, temp);

View File

@ -0,0 +1,19 @@
package club.joylink.rtss.simulation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Component;
/**
* 默认的仿真消息发布器基于webSocket STOMP协议
*/
@Component
public class DefaultMessagePublisher implements SimulationPublisher {
@Autowired
private SimpMessagingTemplate smt;
@Override
public void publishToUser(String user, String destination, Object message) {
smt.convertAndSendToUser(user, destination, message);
}
}

View File

@ -9,6 +9,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
@Slf4j
public abstract class Simulation<U extends SimulationUser> {
@ -27,7 +28,10 @@ public abstract class Simulation<U extends SimulationUser> {
/**
* 仿真状态
*/
private volatile State state;
private final AtomicInteger state = new AtomicInteger(RUNNING);
private static final int RUNNING = 1;
private static final int PAUSE = 0;
private static final int ERROR = -1;
/**
* 仿真运行发生异常时保存的异常信息
*/
@ -39,7 +43,7 @@ public abstract class Simulation<U extends SimulationUser> {
/**
* 执行线程池核心线程数量默认4所有仿真共享
*/
private static final ScheduledExecutorService EXECUTOR = Executors.newScheduledThreadPool(4);
public static final ScheduledExecutorService EXECUTOR = Executors.newScheduledThreadPool(4);
private SimulationPublisher publisher;
@ -50,10 +54,13 @@ public abstract class Simulation<U extends SimulationUser> {
}
public Simulation(String id, int speed) {
if (id == null) {
throw new IllegalArgumentException("仿真id不能为空");
}
this.id = id;
this.speed = speed;
this.systemTime = LocalDateTime.now();
this.state = State.PAUSE;
this.state.set(PAUSE);
this.addJob("systemTime", () ->
this.systemTime = this.systemTime.plusNanos(TimeUnit.MILLISECONDS.toNanos(1)), 10);
}
@ -69,9 +76,9 @@ public abstract class Simulation<U extends SimulationUser> {
return this.systemTime;
}
/**
* 仿真数据初始化由具体仿真实现
* 仿真数据状态初始化由具体仿真实现
*/
protected abstract void initData();
protected abstract void initState();
/**
* 仿真初始化
@ -80,7 +87,7 @@ public abstract class Simulation<U extends SimulationUser> {
this.pause(); // 先暂停
this.reset();
// 通知实现初始化数据
this.initData();
this.initState();
}
private void reset() {
@ -106,6 +113,16 @@ public abstract class Simulation<U extends SimulationUser> {
scheduledJob.runAsSpeed(EXECUTOR, this.speed);
}
/**
* 延时执行逻辑只执行一次
* PS:暂时不处理速度变化对延迟执行的逻辑产生影响
* @param logic
* @param delay
*/
public void delayExecute(Runnable logic, long delay) {
EXECUTOR.schedule(logic, delay, TimeUnit.MILLISECONDS);
}
/**
* 移除指定仿真任务逻辑循环
* @param name
@ -125,14 +142,14 @@ public abstract class Simulation<U extends SimulationUser> {
* 控制-开始
*/
public void start() {
this.state = State.RUNNING;
this.state.set(RUNNING);
}
/**
* 控制-暂停
*/
public void pause() {
this.state = State.PAUSE;
this.state.set(PAUSE);
while (true) {
if (this.getAllRunningJobAmount() == this.getAllFinishedJobAmount()) {
break;
@ -161,24 +178,24 @@ public abstract class Simulation<U extends SimulationUser> {
return amount;
}
public State getState() {
return this.state;
public int getState() {
return this.state.get();
}
public boolean isRunning() {
return State.RUNNING.equals(this.state);
return this.state.get() == RUNNING;
}
/**
* 更新仿真速度
* @param speed [1,10] 1<=speed<=10
* @param speed [1,8] 1<=speed<=8
*/
public void updateSpeed(int speed) {
if (speed < 1) {
throw new IllegalArgumentException("speed must big or equal than 1");
}
if (speed > 10) {
throw new IllegalArgumentException("speed must small or equal than 10");
if (speed > 8) {
throw new IllegalArgumentException("speed must small or equal than 8");
}
if (this.speed == speed) { // 速度与当前相同返回
return;
@ -191,7 +208,7 @@ public abstract class Simulation<U extends SimulationUser> {
}
public void runError(Throwable throwable) {
this.state = State.ERROR;
this.state.set(ERROR);
this.throwable = throwable;
}
@ -239,7 +256,7 @@ public abstract class Simulation<U extends SimulationUser> {
public void publishMessage(String destination, Object message) {
if (this.publisher == null) {
throw new UnsupportedOperationException(String.format("仿真[%s]没有消息发布对象", this.id));
throw new UnsupportedOperationException(String.format("仿真[%s]没有消息发布对象:publisher = null", this.id));
}
for (U simulationUser : this.simulationUserMap.values()) {
if (simulationUser.isSubscribe(destination)) {
@ -248,9 +265,5 @@ public abstract class Simulation<U extends SimulationUser> {
}
}
enum State {
RUNNING,
PAUSE,
ERROR,
}
public abstract String debugStr();
}

View File

@ -0,0 +1,11 @@
package club.joylink.rtss.simulation;
import java.util.concurrent.atomic.AtomicInteger;
public class SimulationIdGenerator {
public static final AtomicInteger sn = new AtomicInteger(0);
public static String buildId() {
return String.valueOf(sn.incrementAndGet());
}
}

View File

@ -0,0 +1,71 @@
package club.joylink.rtss.simulation;
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Component
public class SimulationManager {
public static final Map<String, Simulation> simulationCache = new ConcurrentHashMap<>();
@Autowired
private DefaultMessagePublisher defaultMessagePublisher;
public Simulation save(Simulation simulation) {
BusinessExceptionAssertEnum.DATA_ALREADY_EXIST.assertNotTrue(simulationCache.containsKey(simulation.getId()),
String.format("已经存在id为[%s]的仿真[%s]", simulation.getId(), simulation.debugStr()));
simulationCache.put(simulation.getId(), simulation);
simulation.setPublisher(this.defaultMessagePublisher); // 设置默认的消息发布器
return simulation;
}
public Simulation queryById(String id) {
return simulationCache.get(id);
}
public Simulation getById(String id) {
Simulation simulation = simulationCache.get(id);
BusinessExceptionAssertEnum.DATA_NOT_EXIST
.assertNotNull(simulation, String.format("id为[%s]的仿真不存在", id));
return simulation;
}
public <T extends Simulation> T queryById(String id, T t) {
return (T) simulationCache.get(id);
}
public <T extends Simulation> T getById(String id, T t) {
Simulation simulation = simulationCache.get(id);
BusinessExceptionAssertEnum.DATA_NOT_EXIST
.assertNotNull(simulation, String.format("id为[%s]的仿真不存在", id));
return (T) simulation;
}
public void init(String id) {
this.getById(id).init();
}
public void start(String id) {
this.getById(id).start();
}
public void pause(String id) {
this.getById(id).pause();
}
public void updateSpeed(String id, int speed) {
this.getById(id).updateSpeed(speed);
}
public Simulation destroy(String id) {
Simulation simulation = simulationCache.remove(id);
if (simulation != null) {
simulation.destroy();
}
return simulation;
}
}

View File

@ -2,7 +2,7 @@ package club.joylink.rtss.simulation;
import java.util.Set;
public class SimulationUser {
public abstract class SimulationUser {
/**
* 仿真用户唯一标识并且是发布订阅消息时的用户唯一标识
*/

View File

@ -144,7 +144,7 @@ public class SimulationBuilder {
}
}
private static List<String> checkRunPlanAndBuildLostRoutePaths(Map<String, List<TripPlan>> serverTripMap,
public static List<String> checkRunPlanAndBuildLostRoutePaths(Map<String, List<TripPlan>> serverTripMap,
Map<String, List<RoutePath>> routePathMap) {
Map<String, String> errMsgMap = new HashMap<>();
for (List<TripPlan> tripPlanList : serverTripMap.values()) {

View File

@ -0,0 +1,26 @@
package club.joylink.rtss.simulation.rt;
import club.joylink.rtss.simulation.Simulation;
import club.joylink.rtss.simulation.rt.srd.SrdRepository;
public class RtSimulation extends Simulation<RtSimulationUser> {
/**
* 模拟真实设备数据仓库
*/
SrdRepository srdRepository;
public RtSimulation(String id) {
super(id);
}
@Override
protected void initState() {
}
@Override
public String debugStr() {
return String.format("轨道交通仿真[%s]", getId());
}
}

View File

@ -0,0 +1,28 @@
package club.joylink.rtss.simulation.rt;
import club.joylink.rtss.simulation.SimulationIdGenerator;
import club.joylink.rtss.simulation.SimulationManager;
import club.joylink.rtss.vo.UserVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class RtSimulationService {
@Autowired
private SimulationManager simulationManager;
public RtSimulation create(UserVO userVO) {
RtSimulation rtSimulation = new RtSimulation(SimulationIdGenerator.buildId());
this.simulationManager.save(rtSimulation);
this.load(rtSimulation);
return rtSimulation;
}
/**
* 加载相关数据
* @param rtSimulation
*/
private void load(RtSimulation rtSimulation) {
}
}

View File

@ -0,0 +1,9 @@
package club.joylink.rtss.simulation.rt;
import club.joylink.rtss.simulation.SimulationUser;
public class RtSimulationUser extends SimulationUser {
public RtSimulationUser(String id) {
super(id);
}
}

View File

@ -0,0 +1,17 @@
package club.joylink.rtss.simulation.rt.srd;
import club.joylink.rtss.simulation.rt.RtSimulation;
import org.springframework.stereotype.Component;
@Component
public class SimulateRealDeviceLogic {
public static final int TRAIN_RUN_RATE = 2000;
public void addJobs(RtSimulation rtSimulation) {
rtSimulation.addJob("srTrainRun", () -> {this.srTrainRun(rtSimulation);}, TRAIN_RUN_RATE);
}
public void srTrainRun(RtSimulation simulation) {
}
}

View File

@ -0,0 +1,12 @@
package club.joylink.rtss.simulation.rt.srd;
import club.joylink.rtss.simulation.rt.srd.bo.SrDevice;
import java.util.HashMap;
import java.util.Map;
public class SrdRepository {
Map<String, SrDevice> deviceMap = new HashMap<>();
}

View File

@ -0,0 +1,115 @@
package club.joylink.rtss.simulation.rt.srd;
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.simulation.rt.srd.bo.*;
import club.joylink.rtss.vo.client.map.MapSwitchVO;
import club.joylink.rtss.vo.client.map.MapTrainModelVO;
import club.joylink.rtss.vo.client.map.MapTrainVO;
import club.joylink.rtss.vo.client.map.MapVO;
import club.joylink.rtss.vo.client.map.newmap.MapGraphDataNewVO;
import club.joylink.rtss.vo.client.map.newmap.MapPSDVO;
import club.joylink.rtss.vo.client.map.newmap.MapSectionNewVO;
import club.joylink.rtss.vo.client.map.newmap.MapSignalNewVO;
import org.springframework.util.StringUtils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
public class SrdRepositoryBuilder {
public static SrdRepository buildFrom(MapVO mapVO) {
SrdRepository srdRepository = new SrdRepository();
MapGraphDataNewVO graphDataNew = mapVO.getGraphDataNew();
Map<String, SrDevice> deviceMap = new HashMap<>();
deviceMap.putAll(buildTrackAndAxc(graphDataNew.getSectionList()));
deviceMap.putAll(buildTurnout(graphDataNew.getSwitchList()));
deviceMap.putAll(buildSignal(graphDataNew.getSignalList()));
deviceMap.putAll(buildSrPsd(graphDataNew.getPsdList()));
deviceMap.putAll(buildTrain(graphDataNew.getTrainList()));
// 关系构建
buildRelationOfTrackAndAxc(graphDataNew.getSectionList(), deviceMap);
return srdRepository;
}
private static void buildRelationOfTrackAndAxc(List<MapSectionNewVO> sectionList, Map<String, SrDevice> deviceMap) {
for (MapSectionNewVO sectionVO : sectionList) {
SrTrack srTrack = (SrTrack) deviceMap.get(sectionVO.getCode());
if (srTrack == null) {
continue;
}
if (StringUtils.hasText(sectionVO.getParentCode())) {
deviceMap.get(sectionVO.getParentCode());
}
}
}
private static Map<String, SrDevice> buildTrackAndAxc(List<MapSectionNewVO> sectionList) {
Map<String, SrDevice> map = new HashMap<>();
for (MapSectionNewVO sectionVO : sectionList) {
if (Objects.equals(sectionVO.getType(), "02")) { // 逻辑区段
continue;
}
if (Objects.equals(sectionVO.getType(), "04")) { // 道岔计轴
// 只创建计轴器
SrAXC srAXC = new SrAXC(sectionVO.getCode());
map.put(srAXC.getId(), srAXC);
continue;
}
// 创建轨道
SrTrack srTrack = new SrTrack(sectionVO.getCode());
map.put(srTrack.getId(), srTrack);
BusinessExceptionAssertEnum.DATA_ERROR.assertTrue(sectionVO.getLengthFact() > 0,
String.format("区段[%s(%s)]未设置实际长度或长度小于0", sectionVO.getName(), sectionVO.getCode()));
srTrack.setLen((int) (sectionVO.getLengthFact()*1000));
// 创建计轴器
SrAXC srAXC = new SrAXC(sectionVO.getCode());
map.put(srAXC.getId(), srAXC);
}
return map;
}
private static Map<String, SrDevice> buildTurnout(List<MapSwitchVO> switchList) {
Map<String, SrDevice> map = new HashMap<>();
for (MapSwitchVO switchVO : switchList) {
SrTurnout srTurnout = new SrTurnout(switchVO.getCode());
map.put(srTurnout.getId(), srTurnout);
}
return map;
}
private static Map<String, SrDevice> buildSignal(List<MapSignalNewVO> signalList) {
Map<String, SrDevice> map = new HashMap<>();
for (MapSignalNewVO signalVO : signalList) {
SrSignal srSignal = new SrSignal(signalVO.getCode());
BusinessExceptionAssertEnum.DATA_ERROR.assertTrue(signalVO.getSectionOffset() >= 0,
String.format("信号机[%s(%s)]区段偏移量小于0", signalVO.getName(), signalVO.getCode()));
srSignal.setOffset((int) (signalVO.getSectionOffset()*1000));
map.put(srSignal.getId(), srSignal);
}
return map;
}
private static Map<String, SrDevice> buildSrPsd(List<MapPSDVO> psdList) {
Map<String, SrDevice> map = new HashMap<>();
for (MapPSDVO psdVO : psdList) {
SrPSD srPSD = new SrPSD(psdVO.getCode());
map.put(srPSD.getId(), srPSD);
}
return map;
}
private static Map<String, SrDevice> buildTrain(List<MapTrainVO> trainList) {
Map<String, SrDevice> map = new HashMap<>();
for (MapTrainVO trainVO : trainList) {
SrTrain srTrain = new SrTrain(trainVO.getGroupNumber());
map.put(srTrain.getId(), srTrain);
MapTrainModelVO trainModel = trainVO.getTrainModel();
srTrain.setLen((int) (trainModel.getLength()*1000));
}
return map;
}
}

View File

@ -0,0 +1,16 @@
package club.joylink.rtss.simulation.rt.srd.bo;
public enum DeviceType {
/** 计轴器 */
AXC,
/** 道岔 */
TURNOUT,
/** 信号机 */
SIGNAL,
/** 站台屏蔽门 */
PSD,
TRAIN,
/** 轨道 */
TRACK
}

View File

@ -0,0 +1,17 @@
package club.joylink.rtss.simulation.rt.srd.bo;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* 模拟真实计轴器Axle counter
*/
public class SrAXC extends SrDevice {
AtomicBoolean state = new AtomicBoolean(OFF);
public static final boolean OFF = true;//出清
public static final boolean ON = true;//占用
public SrAXC(String id) {
super(id, DeviceType.AXC);
}
}

View File

@ -0,0 +1,19 @@
package club.joylink.rtss.simulation.rt.srd.bo;
import lombok.Getter;
/**
* 虚拟真实设备抽象父类
*/
@Getter
public abstract class SrDevice {
String id;
DeviceType deviceType;
public SrDevice() {}
public SrDevice(String id, DeviceType deviceType) {
this.id = id;
this.deviceType = deviceType;
}
}

View File

@ -0,0 +1,29 @@
package club.joylink.rtss.simulation.rt.srd.bo;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 模拟真实屏蔽门Platform screen door
*/
public class SrPSD extends SrDevice {
public static final int turnTime = 3000; // 默认开关门时间单位ms
AtomicInteger state = new AtomicInteger(CLOSE_LOCK);
public static final int CLOSE_LOCK = 1;//关闭且锁闭
public static final int CLOSED = 2;//关闭未锁闭
public static final int OPEN = 3;//打开未到位
public static final int OPEN_FINISH = 4;//打开到位
AtomicInteger command = new AtomicInteger();
public static final int NONE = 0;//无动作
public static final int C_OPEN = 1;//控制开门
public static final int C_CLOSE = 2;//控制关门
/**
* 剩余动作时间
*/
int remain;
public SrPSD(String id) {
super(id, DeviceType.PSD);
}
}

View File

@ -0,0 +1,43 @@
package club.joylink.rtss.simulation.rt.srd.bo;
import lombok.Getter;
import lombok.Setter;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 模拟真实信号机
*/
@Getter
@Setter
public class SrSignal extends SrDevice {
/**
* 所在区段
*/
SrTrack track;
/**
* 所在区段偏移量,单位mm
*/
int offset;
AtomicInteger state = new AtomicInteger(CLOSE);
public static final int CLOSE = 0;
public static final int RED = 1;
public static final int GREEN = 2;
public static final int YELLOW = 3;
public static final int RED_YELLOW = 4;
AtomicInteger command = new AtomicInteger(C_NONE);
public static final int C_NONE = -1;
public static final int C_CLOSE = 0;
public static final int C_RED = 1;
public static final int C_GREEN = 2;
public static final int C_YELLOW = 3;
public static final int C_RED_YELLOW = 4;
public SrSignal(String id) {
super(id, DeviceType.SIGNAL);
}
}

View File

@ -0,0 +1,46 @@
package club.joylink.rtss.simulation.rt.srd.bo;
import lombok.Getter;
import lombok.Setter;
/**
* 模拟真实轨道区段
*/
@Getter
@Setter
public class SrTrack extends SrDevice {
/**
* 轨道长度单位mm
*/
private int len;
/**
* 左停车点
*/
private int leftPs;
/**
* 右停车点
*/
private int rightPs;
/**
* 计轴器
*/
private SrAXC axc;
/**
* 左侧轨道可能为null
*/
private SrDevice left;
/**
* 右侧轨道可能为null
*/
private SrDevice right;
/**
* 关联的道岔是道岔区段才会关联否则为null
*/
private SrTurnout turnout;
public SrTrack(String id) {
super(id, DeviceType.TRACK);
}
}

View File

@ -0,0 +1,29 @@
package club.joylink.rtss.simulation.rt.srd.bo;
import lombok.Getter;
import lombok.Setter;
/**
* 模拟真实列车
*/
@Getter
@Setter
public class SrTrain extends SrDevice {
/**
* 列车长度,单位mm
*/
int len;
/**
* 列车速度
*/
int speed;
/**
* 列车位置
*/
TrackPosition position;
public SrTrain(String id) {
super(id, DeviceType.TRAIN);
}
}

View File

@ -0,0 +1,32 @@
package club.joylink.rtss.simulation.rt.srd.bo;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 模拟真实道岔
*/
public class SrTurnout extends SrDevice {
public static final int turnTime = 3000; // 默认转换时间
SrTrack a;
SrTrack b;
SrTrack c;
AtomicInteger state = new AtomicInteger(NORMAL);
public static final int NORMAL = 1;
public static final int REVERSE = 2;
public static final int TURNING = 0;
AtomicInteger command = new AtomicInteger(NONE);
public static final int NONE = 0;
public static final int TN = 1;
public static final int TR = 2;
/**
* 转换剩余时间,单位ms
*/
int remain;
public SrTurnout(String id) {
super(id, DeviceType.TURNOUT);
}
}

View File

@ -0,0 +1,6 @@
package club.joylink.rtss.simulation.rt.srd.bo;
public class TrackPosition {
SrTrack track;
int offset;
}

View File

@ -149,7 +149,7 @@ public class MapSectionNewVO {
private String parentCode;
/**
* 区段类型物理区段/逻辑区段/道岔物理区段/道岔计轴区段04
* 区段类型物理区段01/逻辑区段02/道岔物理区段03/道岔计轴区段04
*/
@ApiModelProperty(value = "区段类型")
@NotNull(message="区段类型不能为Null")

View File

@ -1,11 +1,14 @@
package club.joylink.rtss.wechat;
import club.joylink.rtss.configuration.configProp.WeChatConfig;
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.util.EncryptUtil;
import club.joylink.rtss.vo.CommonJsonResponse;
import club.joylink.rtss.wechat.vo.WxAccessToken;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
@Slf4j
@ -44,22 +47,35 @@ public class MiniProgramAccessTokenManager {
this.expiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000l;
}
@Scheduled(fixedRate=6600000)
public void getAccessTokenFromWx() {
if(!this.weChatConfig.getMini().isAccessTokenTaskOn()) {
log.debug("微信小程序获取access_token任务未开启");
return;
}
try {
String accessToken = this.getAccessToken(true);
log.info("get wechat mini program Access Token is: "+accessToken);
} catch (WxErrorException e) {
log.error("获取access token失败", e);
}
}
// @Scheduled(fixedRate=6600000)
// public void getAccessTokenFromWx() {
// if(!this.weChatConfig.getMini().isAccessTokenTaskOn()) {
// log.debug("微信小程序获取access_token任务未开启");
// return;
// }
// try {
// String accessToken = this.getAccessToken();
// log.info("get wechat mini program Access Token is: "+accessToken);
// } catch (WxErrorException e) {
// log.error("获取access token失败", e);
// }
// }
public String getAccessToken() throws WxErrorException {
return this.getAccessToken(false);
public static final String URL_GET_ACCESS_TOKEN = "https://api.joylink.club/wechatservice/api/accessToken?clientid=%s&secret=%s&checksum=%s";
public static final String clientId = "rtss";
public static final String secret = "joylink-0503";
public String getAccessToken() {
String url = String.format(URL_GET_ACCESS_TOKEN,
clientId, secret, EncryptUtil.md5(String.format("%s:%s", clientId, secret)));
CommonJsonResponse response = this.restTemplate.getForObject(url, CommonJsonResponse.class);
String accessToken = (String) response.getData();
if (!StringUtils.hasText(accessToken)) {
BusinessExceptionAssertEnum.THIRD_SERVICE_CALL_EXCEPTION.assertHasText(accessToken,
String.format("获取access_token失败: %s", response.toJSONString()));
}
return accessToken;
}
public String getAccessToken(boolean forceRefresh) throws WxErrorException {

View File

@ -1,6 +1,5 @@
package club.joylink.rtss.wechat;
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.wechat.constant.CheckMediaType;
import club.joylink.rtss.wechat.vo.WxError;
import lombok.extern.slf4j.Slf4j;
@ -39,20 +38,20 @@ public class MiniProgramServiceImpl implements MiniProgramService {
public static final int Media_Type_Audio = 1;
public static final int Media_Type_Img = 2;
private String getMpAccessToken() {
try {
String accessToken = this.miniProgramAccessTokenManager.getAccessToken();
return accessToken;
} catch (WxErrorException e) {
throw BusinessExceptionAssertEnum.THIRD_SERVICE_CALL_EXCEPTION
.exception(String.format("获取微信小程序access_token异常"), e);
}
}
//
// private String getMpAccessToken() {
// try {
// String accessToken = this.miniProgramAccessTokenManager.getAccessToken();
// return accessToken;
// } catch (WxErrorException e) {
// throw BusinessExceptionAssertEnum.THIRD_SERVICE_CALL_EXCEPTION
// .exception(String.format("获取微信小程序access_token异常"), e);
// }
// }
@Override
public WxError msgSecCheck(String content) {
String accessToken = this.getMpAccessToken();
String accessToken = this.miniProgramAccessTokenManager.getAccessToken();
String url = String.format(URL_MSG_SEC_CHECK, accessToken);
log.info(String.format("需要微信小程序检测的内容:[%s]", content));
Map<String, String> params = new HashMap<>();
@ -79,7 +78,7 @@ public class MiniProgramServiceImpl implements MiniProgramService {
FileSystemResource resource = new FileSystemResource(tempFilePath);
body.add("media", resource);
HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(body, headers);
String accessToken = this.getMpAccessToken();
String accessToken = this.miniProgramAccessTokenManager.getAccessToken();
String url = String.format(URL_IMG_SEC_CHECK, accessToken);
// 调用接口
ResponseEntity<WxError> responseEntity = this.restTemplate.postForEntity(url, httpEntity, WxError.class);
@ -90,7 +89,7 @@ public class MiniProgramServiceImpl implements MiniProgramService {
@Override
public WxError imgSecCheckAsnc(String mediaUrl, CheckMediaType mediaType) {
String accessToken = this.getMpAccessToken();
String accessToken = this.miniProgramAccessTokenManager.getAccessToken();
String url = String.format(URL_MEDIA_SEC_CHECK, accessToken);
Map<String, Object> params = new HashMap<>();
params.put("media_url", mediaUrl);