zhanghaijun пре 2 година
родитељ
комит
085ba5c234
18 измењених фајлова са 342 додато и 104 уклоњено
  1. 3 5
      train-common/train-common-core/src/main/java/top/haijunit/common/exception/ServiceException.java
  2. 2 2
      train-common/train-common-mybatis/src/main/java/top/haijunit/mybatis/handler/InjectionMetaObjectHandler.java
  3. 2 4
      train-common/train-common-websocket/src/main/java/top/haijunit/websocket/event/MessageEvent.java
  4. 0 1
      train-server/src/main/java/top/haijunit/train/domain/constant/DirectionEnum.java
  5. 24 0
      train-server/src/main/java/top/haijunit/train/domain/constant/RouteStatusConverter.java
  6. 36 0
      train-server/src/main/java/top/haijunit/train/domain/constant/RouteStatusEnum.java
  7. 34 2
      train-server/src/main/java/top/haijunit/train/domain/entity/RouteEntity.java
  8. 1 1
      train-server/src/main/java/top/haijunit/train/domain/repository/DeviceRepository.java
  9. 25 40
      train-server/src/main/java/top/haijunit/train/listener/MessageEventListener.java
  10. 30 0
      train-server/src/main/java/top/haijunit/train/listener/ReportTimeHandle.java
  11. 35 0
      train-server/src/main/java/top/haijunit/train/listener/TrainApplication.java
  12. 67 0
      train-server/src/main/java/top/haijunit/train/service/DeviceService.java
  13. 42 0
      train-server/src/main/java/top/haijunit/train/simulation/TrainComputerService.java
  14. 0 1
      train-server/src/main/java/top/haijunit/train/simulation/TrainItem.java
  15. 0 38
      train-server/src/main/java/top/haijunit/train/simulation/TrainService.java
  16. 30 0
      train-server/src/main/java/top/haijunit/train/simulation/TrainSimulationHolder.java
  17. 2 1
      train-server/src/main/resources/db/changelog/db-server-train.xml
  18. 9 9
      train-server/src/main/resources/db/changelog/db_route.txt

+ 3 - 5
train-common/train-common-core/src/main/java/top/haijunit/common/exception/ServiceException.java

@@ -22,15 +22,13 @@ public class ServiceException extends RuntimeException {
     private static final long serialVersionUID = 1L;
 
     /** 错误码 */
+    /**
+     * 错误码 {@link cn.hutool.http.HttpStatus#HTTP_INTERNAL_ERROR}
+     */
     private Integer code;
     /** 错误提示 */
     private String message;
 
-    public ServiceException(String message, Integer code) {
-        this.message = message;
-        this.code = code;
-    }
-
     @Override
     public String getMessage() {
         return message;

+ 2 - 2
train-common/train-common-mybatis/src/main/java/top/haijunit/mybatis/handler/InjectionMetaObjectHandler.java

@@ -29,7 +29,7 @@ public class InjectionMetaObjectHandler implements MetaObjectHandler {
                 baseEntity.setUpdateBy(userId);
             }
         } catch (Exception e) {
-            throw new ServiceException("自动注入异常 => " + e.getMessage(), HttpStatus.HTTP_UNAUTHORIZED);
+            throw new ServiceException(HttpStatus.HTTP_UNAUTHORIZED, "自动注入异常 => " + e.getMessage());
         }
     }
 
@@ -44,7 +44,7 @@ public class InjectionMetaObjectHandler implements MetaObjectHandler {
                 baseEntity.setUpdateBy(0L);
             }
         } catch (Exception e) {
-            throw new ServiceException("自动注入异常 => " + e.getMessage(), HttpStatus.HTTP_UNAUTHORIZED);
+            throw new ServiceException(HttpStatus.HTTP_UNAUTHORIZED, "自动注入异常 => " + e.getMessage());
         }
     }
 

+ 2 - 4
train-common/train-common-websocket/src/main/java/top/haijunit/websocket/event/MessageEvent.java

@@ -6,8 +6,6 @@ import lombok.ToString;
 import org.springframework.context.ApplicationEvent;
 import org.springframework.web.socket.WebSocketSession;
 
-import java.time.Clock;
-
 /**
  * @author zhang
  * @date 2023/11/23 23:11
@@ -36,8 +34,8 @@ public class MessageEvent extends ApplicationEvent {
         this.message = message;
     }
 
-    public boolean isOpen() {
-        return this.messageType == MessageType.OPEN;
+    public boolean isMessage() {
+        return this.messageType == MessageType.MESSAGE;
     }
 
     public enum MessageType {

+ 0 - 1
train-server/src/main/java/top/haijunit/train/domain/constant/DirectionEnum.java

@@ -4,7 +4,6 @@ import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonValue;
 import lombok.AllArgsConstructor;
 import lombok.Getter;
-import top.haijunit.train.socket.CommandEnum;
 
 import java.util.Objects;
 

+ 24 - 0
train-server/src/main/java/top/haijunit/train/domain/constant/RouteStatusConverter.java

@@ -0,0 +1,24 @@
+package top.haijunit.train.domain.constant;
+
+import jakarta.persistence.AttributeConverter;
+import jakarta.persistence.Converter;
+
+import java.util.Optional;
+
+/**
+ * @author zhanghaijun
+ * @date 2023/11/27 18:09
+ * @description [一句话描述该类的功能]
+ */
+@Converter(autoApply = true)
+public class RouteStatusConverter implements AttributeConverter<RouteStatusEnum, Integer> {
+    @Override
+    public Integer convertToDatabaseColumn(RouteStatusEnum direction) {
+        return Optional.of(direction).map(RouteStatusEnum::getCode).orElse(RouteStatusEnum.OCCUPY.getCode());
+    }
+
+    @Override
+    public RouteStatusEnum convertToEntityAttribute(Integer code) {
+        return RouteStatusEnum.getByCode(code);
+    }
+}

+ 36 - 0
train-server/src/main/java/top/haijunit/train/domain/constant/RouteStatusEnum.java

@@ -0,0 +1,36 @@
+package top.haijunit.train.domain.constant;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.Objects;
+
+/**
+ * @author zhang
+ * @date 2023/11/20 23:33
+ * @description 进路状态 占用(红光带)、出清/空闲(灰光带)、锁闭(白光带)
+ */
+@Getter
+@AllArgsConstructor
+public enum RouteStatusEnum {
+
+    OCCUPY(1, "占用"),
+    IDLE(2, "出清"),
+    LOCK(3, "锁闭");
+
+    @JsonValue
+    private final Integer code;
+    private final String describe;
+
+    @JsonCreator(mode = JsonCreator.Mode.DELEGATING)
+    public static RouteStatusEnum getByCode(Integer code) {
+        for (RouteStatusEnum genderEnum : values()) {
+            if (Objects.equals(genderEnum.getCode(), code)) {
+                return genderEnum;
+            }
+        }
+        return null;
+    }
+}

+ 34 - 2
train-server/src/main/java/top/haijunit/train/domain/entity/RouteEntity.java

@@ -9,6 +9,7 @@ import jakarta.persistence.GenerationType;
 import jakarta.persistence.Id;
 import lombok.Data;
 import top.haijunit.train.domain.constant.DirectionEnum;
+import top.haijunit.train.domain.constant.RouteStatusEnum;
 import top.haijunit.train.domain.constant.SignalStateEnum;
 import top.haijunit.train.domain.constant.SwitchStateEnum;
 
@@ -37,7 +38,7 @@ public class RouteEntity implements Serializable {
     // 关联信号机
     private String signalIds;
     // 关联信号机状态
-    private SignalStateEnum signalState;
+    private String signalState;
     // 关联区段列表
     private String seleIds;
     // 关联道岔
@@ -48,6 +49,8 @@ public class RouteEntity implements Serializable {
     private BigDecimal trigPosition;
     // 进路方向
     private DirectionEnum direction;
+    // 进路状态
+    private RouteStatusEnum routeStatus;
 
     public ArrayList<Long> getSelectionList() {
         if (StrUtil.isBlank(this.getSeleIds())) {
@@ -70,7 +73,7 @@ public class RouteEntity implements Serializable {
         return StrUtil.split(this.getSwitchState(), "-").stream().map(item -> SwitchStateEnum.getByCode(Convert.toInt(item, SwitchStateEnum.Forward.getCode()))).collect(Collectors.toCollection(ArrayList::new));
     }
 
-    public Map<Long, SwitchStateEnum> getSignalMap() {
+    public Map<Long, SwitchStateEnum> getSwitchMap() {
         ArrayList<Long> switchList = this.getSwitchList();
         ArrayList<SwitchStateEnum> switchStateList = this.getSwitchStateList();
         Map<Long, SwitchStateEnum> map = new HashMap<>();
@@ -79,4 +82,33 @@ public class RouteEntity implements Serializable {
         }
         return map;
     }
+
+    public ArrayList<Long> getSignalList() {
+        if (StrUtil.isBlank(this.getSignalIds())) {
+            return new ArrayList<>();
+        }
+        return StrUtil.split(this.getSignalIds(), "-").stream().map(item -> Convert.toLong(item, 0L)).collect(Collectors.toCollection(ArrayList::new));
+    }
+
+    public ArrayList<SignalStateEnum> getSignalStateList() {
+        if (StrUtil.isBlank(this.getSignalState())) {
+            return new ArrayList<>();
+        }
+        return StrUtil.split(this.getSignalState(), "-").stream().map(item -> SignalStateEnum.getByCode(Convert.toInt(item, SignalStateEnum.RED.getCode()))).collect(Collectors.toCollection(ArrayList::new));
+    }
+
+    public Map<Long, SignalStateEnum> getSignalMap() {
+        ArrayList<Long> signalList = this.getSignalList();
+        ArrayList<SignalStateEnum> signalStateList = this.getSignalStateList();
+        Map<Long, SignalStateEnum> map = new HashMap<>();
+        for (int i = 0; i < signalList.size(); i++) {
+            map.put(signalList.get(i), Optional.of(CollUtil.get(signalStateList, i)).orElse(SignalStateEnum.RED));
+        }
+        return map;
+    }
+
+    /** 是否触发进路 */
+    public boolean isTrigger(BigDecimal kilometer, BigDecimal nextPrePosition) {
+        return kilometer.compareTo(this.getTrigPosition()) >= 0 && kilometer.compareTo(nextPrePosition) < 0;
+    }
 }

+ 1 - 1
train-server/src/main/java/top/haijunit/train/domain/repository/DeviceRepository.java

@@ -14,5 +14,5 @@ import java.util.List;
 @Repository
 public interface DeviceRepository extends JpaRepository<DeviceEntity, Long> {
 
-    // List<DeviceEntity> findByDeviceType(String deviceType);
+    List<DeviceEntity> findByCode(String code);
 }

+ 25 - 40
train-server/src/main/java/top/haijunit/train/listener/MessageEventListener.java

@@ -1,16 +1,15 @@
 package top.haijunit.train.listener;
 
-import cn.hutool.core.convert.Convert;
 import cn.hutool.core.util.StrUtil;
-import cn.hutool.json.JSONObject;
-import cn.hutool.json.JSONUtil;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.configurationprocessor.json.JSONException;
+import org.springframework.boot.configurationprocessor.json.JSONObject;
 import org.springframework.context.ApplicationListener;
 import org.springframework.stereotype.Component;
+import top.haijunit.common.utils.JsonUtils;
 import top.haijunit.train.domain.entity.DeviceEntity;
-import top.haijunit.train.domain.repository.DeviceRepository;
-import top.haijunit.train.simulation.TrainService;
+import top.haijunit.train.service.DeviceService;
 import top.haijunit.train.socket.CommandEnum;
 import top.haijunit.train.socket.SocketDevice;
 import top.haijunit.websocket.event.MessageEvent;
@@ -28,46 +27,32 @@ import java.lang.reflect.InvocationTargetException;
 @RequiredArgsConstructor
 public class MessageEventListener implements ApplicationListener<MessageEvent> {
 
-    private final DeviceRepository deviceRepository;
-    private final TrainService trainService;
+    private final DeviceService deviceService;
 
     @Override
     public void onApplicationEvent(MessageEvent event) {
-        if (event.isOpen()) {
-            // 连接成功,发送列车信息
-            trainService.sendTrainPositionList();
-        } else {
-            messageAccept(event);
-        }
-    }
-
-    private void messageAccept(MessageEvent event) {
-        if (StrUtil.isBlank(event.getMessage())) {
-            return;
-        }
-        JSONObject message = JSONUtil.parseObj(event.getMessage());
-        if (!message.containsKey("cmd")) {
-            return;
-        }
-        CommandEnum commandEnum = CommandEnum.getByCode(Convert.toInt(message.containsKey("cmd"), 0));
-        if (null != commandEnum && null != commandEnum.getClassType()) {
+        if (event.isMessage()) {
+            if (StrUtil.isBlank(event.getMessage())) {
+                return;
+            }
             try {
-                SocketDevice.DeviceBase deviceBase = commandEnum.getClassType().getDeclaredConstructor().newInstance();
-                String code = Convert.toStr(message.get(deviceBase.getCodeName()), "");
-                String status = Convert.toStr(message.get(deviceBase.getStatusName()), "");
-                String other = Convert.toStr(message.get(deviceBase.getOtherName()), "");
-                if (!StrUtil.isAllNotBlank(code, status)) {
-                    return;
+                DeviceEntity device = deviceService.updateDevice(event.getMessage());
+                if (device != null) {
+                    CommandEnum command = device.getCommand();
+                    SocketDevice.DeviceBase deviceBase = command.getClassType().getDeclaredConstructor().newInstance();
+                    // TODO 需要处理指令
+                    JSONObject jsonObject = new JSONObject();
+                    jsonObject.put(deviceBase.getCodeName(), device.getCode());
+                    jsonObject.put(deviceBase.getStatusName(), device.getStatus());
+                    if (StrUtil.isNotBlank(deviceBase.getOtherName())) {
+                        jsonObject.put(deviceBase.getOtherName(), device.getOther());
+                    }
+                    WebSocketUtils.sendMessage(event.getSessionFrom(), "{\"cmd\":" + command.getCode() + ",\"data\":" + JsonUtils.toJsonString(jsonObject) + "}");
                 }
-                DeviceEntity device = new DeviceEntity();
-                device.setCommand(commandEnum);
-                device.setCode(code);
-                device.setStatus(status);
-                device.setOther(other);
-                deviceRepository.save(device);
-                WebSocketUtils.sendMessage(event.getSessionFrom(), JSONUtil.toJsonStr(device));
-            } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
-                throw new RuntimeException(e);
+            } catch (RuntimeException exception) {
+                log.error("消息处理异常: {}", event.getMessage());
+            } catch (JSONException | InvocationTargetException | InstantiationException | IllegalAccessException | NoSuchMethodException e) {
+                log.error("数据类型异常: {}", event.getMessage());
             }
         }
     }

+ 30 - 0
train-server/src/main/java/top/haijunit/train/listener/ReportTimeHandle.java

@@ -0,0 +1,30 @@
+package top.haijunit.train.listener;
+
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+import top.haijunit.train.simulation.TrainItem;
+import top.haijunit.train.simulation.TrainSimulationHolder;
+import top.haijunit.train.socket.CommandEnum;
+import top.haijunit.train.socket.TrainWebSocketUtils;
+
+/**
+ * @author zhanghaijun
+ * @date 2023/11/27 17:50
+ * @description 上报数据得定时器
+ */
+@Component
+public class ReportTimeHandle {
+
+    @Scheduled(fixedRate = 50)
+    public void sendTrainPositionList() {
+        for (TrainItem trainItem : TrainSimulationHolder.getTrainItem()) {
+            this.sendTrainPosition(trainItem);
+        }
+    }
+
+    @Async
+    public void sendTrainPosition(TrainItem train) {
+        TrainWebSocketUtils.sendMessage(CommandEnum.TRAIN, train);
+    }
+}

+ 35 - 0
train-server/src/main/java/top/haijunit/train/listener/TrainApplication.java

@@ -0,0 +1,35 @@
+package top.haijunit.train.listener;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.ApplicationArguments;
+import org.springframework.boot.ApplicationRunner;
+import org.springframework.stereotype.Component;
+import top.haijunit.train.domain.entity.TrainEntity;
+import top.haijunit.train.domain.repository.TrainRepository;
+import top.haijunit.train.simulation.TrainItem;
+import top.haijunit.train.simulation.TrainSimulationHolder;
+
+import java.util.List;
+
+/**
+ * @author zhanghaijun
+ * @date 2023/11/27 17:02
+ * @description [一句话描述该类的功能]
+ */
+@Slf4j
+@Component
+@RequiredArgsConstructor
+public class TrainApplication implements ApplicationRunner {
+
+    private final TrainRepository trainRepository;
+
+    @Override
+    public void run(ApplicationArguments args) throws Exception {
+        List<TrainEntity> list = trainRepository.findAll();
+        for (TrainEntity train : list) {
+            TrainItem trainItem = new TrainItem(train.getId(), train.getName(), train.getTrainLength(), train.getInitKilometer(), train.getInitDirection());
+            TrainSimulationHolder.addTrainItem(trainItem);
+        }
+    }
+}

+ 67 - 0
train-server/src/main/java/top/haijunit/train/service/DeviceService.java

@@ -0,0 +1,67 @@
+package top.haijunit.train.service;
+
+import cn.hutool.core.convert.Convert;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.HttpStatus;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import top.haijunit.common.exception.ServiceException;
+import top.haijunit.train.domain.entity.DeviceEntity;
+import top.haijunit.train.domain.repository.DeviceRepository;
+import top.haijunit.train.socket.CommandEnum;
+import top.haijunit.train.socket.SocketDevice;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.List;
+
+/**
+ * @author zhanghaijun
+ * @date 2023/11/27 17:11
+ * @description [一句话描述该类的功能]
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class DeviceService {
+
+    private final DeviceRepository deviceRepository;
+
+    public DeviceEntity updateDevice(String msgStr) {
+        JSONObject message = JSONUtil.parseObj(msgStr);
+        if (!message.containsKey("cmd")) {
+            throw new ServiceException(500, String.format("cmd指令解析失败,message:%s", msgStr));
+        }
+        CommandEnum commandEnum = CommandEnum.getByCode(Convert.toInt(message.containsKey("cmd"), 0));
+        if (null != commandEnum && null != commandEnum.getClassType()) {
+            try {
+                SocketDevice.DeviceBase deviceBase = commandEnum.getClassType().getDeclaredConstructor().newInstance();
+                String code = Convert.toStr(message.get(deviceBase.getCodeName()), "");
+                String status = Convert.toStr(message.get(deviceBase.getStatusName()), "");
+                String other = Convert.toStr(message.get(deviceBase.getOtherName()), "");
+                if (!StrUtil.isAllNotBlank(code, status)) {
+                    throw new ServiceException(HttpStatus.HTTP_INTERNAL_ERROR, String.format("缺少字段: message:%s, code: %s, status: %s", msgStr, deviceBase.getCodeName(), deviceBase.getStatusName()));
+                }
+                return updateDevice(commandEnum, code, status, other);
+            } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
+                throw new ServiceException(HttpStatus.HTTP_INTERNAL_ERROR, String.format("设备信息解析失败,原因:%s", e.getMessage()));
+            }
+        } else {
+            throw new ServiceException(HttpStatus.HTTP_INTERNAL_ERROR, String.format("未能解析消息内容,message:%s", message));
+        }
+    }
+
+    public DeviceEntity updateDevice(CommandEnum command, String code, String status, String other) {
+        List<DeviceEntity> list = deviceRepository.findByCode(code);
+        deviceRepository.deleteAll(list);
+        DeviceEntity device = new DeviceEntity();
+        device.setCommand(command);
+        device.setCode(code);
+        device.setStatus(status);
+        device.setOther(other);
+        deviceRepository.save(device);
+        return device;
+    }
+}

+ 42 - 0
train-server/src/main/java/top/haijunit/train/simulation/TrainComputerService.java

@@ -0,0 +1,42 @@
+package top.haijunit.train.simulation;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import top.haijunit.train.domain.constant.RouteStatusEnum;
+import top.haijunit.train.domain.entity.RouteEntity;
+import top.haijunit.train.domain.repository.RouteRepository;
+
+import java.math.BigDecimal;
+
+/**
+ * @author zhanghaijun
+ * @date 2023/11/27 17:54
+ * @description [一句话描述该类的功能]
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class TrainComputerService {
+
+    private final RouteRepository routeRepository;
+
+
+    public void run(TrainItem train) {
+        for (RouteEntity route : routeRepository.findAll()) {
+            BigDecimal nextPrePosition = train.getKilometer().add(new BigDecimal(100));
+            if (!route.isTrigger(train.getKilometer(), nextPrePosition)) {
+                continue;
+            }
+            if (!route.getRouteStatus().equals(RouteStatusEnum.IDLE)) {
+                continue;
+            }
+            if (!route.getSwitchList().isEmpty()) {
+                // TODO 出清且包含到拆
+            } else {
+                // TODO 出清且不包括到道岔
+                route.setRouteStatus(RouteStatusEnum.OCCUPY);
+            }
+        }
+    }
+}

+ 0 - 1
train-server/src/main/java/top/haijunit/train/simulation/TrainItem.java

@@ -1,6 +1,5 @@
 package top.haijunit.train.simulation;
 
-import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.Getter;
 import lombok.Setter;

+ 0 - 38
train-server/src/main/java/top/haijunit/train/simulation/TrainService.java

@@ -1,38 +0,0 @@
-package top.haijunit.train.simulation;
-
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.scheduling.annotation.Async;
-import org.springframework.stereotype.Service;
-import top.haijunit.train.domain.entity.TrainEntity;
-import top.haijunit.train.domain.repository.TrainRepository;
-import top.haijunit.train.socket.CommandEnum;
-import top.haijunit.train.socket.TrainWebSocketUtils;
-
-import java.util.List;
-
-/**
- * @author zhanghaijun
- * @date 2023/11/26 20:30
- * @description [一句话描述该类的功能]
- */
-@Slf4j
-@Service
-@RequiredArgsConstructor
-public class TrainService {
-
-    private final TrainRepository trainRepository;
-
-    public void sendTrainPositionList() {
-        List<TrainEntity> list = trainRepository.findAll();
-        for (TrainEntity train : list) {
-            this.sendTrainPosition(train);
-        }
-    }
-
-    @Async
-    public void sendTrainPosition(TrainEntity train) {
-        TrainItem trainItem = new TrainItem(train.getId(), train.getName(), train.getTrainLength(), train.getInitKilometer(), train.getInitDirection());
-        TrainWebSocketUtils.sendMessage(CommandEnum.TRAIN, trainItem);
-    }
-}

+ 30 - 0
train-server/src/main/java/top/haijunit/train/simulation/TrainSimulationHolder.java

@@ -0,0 +1,30 @@
+package top.haijunit.train.simulation;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author zhanghaijun
+ * @date 2023/11/27 16:57
+ * @description 列车仿真数据共享
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class TrainSimulationHolder {
+
+    // 列车数据共享
+    private static final Map<Long, TrainItem> USER_SESSION_MAP = new ConcurrentHashMap<>();
+
+    public static void addTrainItem(TrainItem trainItem) {
+        USER_SESSION_MAP.remove(trainItem.getId());
+        USER_SESSION_MAP.put(trainItem.getId(), trainItem);
+    }
+
+    public static Collection<TrainItem> getTrainItem() {
+        return USER_SESSION_MAP.values();
+    }
+
+}

+ 2 - 1
train-server/src/main/resources/db/changelog/db-server-train.xml

@@ -74,12 +74,13 @@
             </column>
             <column name="name" type="VARCHAR(128)" defaultValue="" remarks="进路名称"/>
             <column name="signal_ids" type="VARCHAR(128)" defaultValue="" remarks="关联信号机"/>
-            <column name="signal_state" type="${number.type}" defaultValueNumeric="0" remarks="关联信号机状态"/>
+            <column name="signal_state" type="VARCHAR(128)" defaultValueNumeric="0" remarks="关联信号机状态"/>
             <column name="sele_ids" type="VARCHAR(128)" defaultValue="" remarks="关联区段列表"/>
             <column name="switch_id" type="VARCHAR(128)" defaultValue="" remarks="关联道岔"/>
             <column name="switch_state" type="VARCHAR(128)" defaultValue="" remarks="关联道岔状态"/>
             <column name="trig_position" type="DECIMAL(10, 2)" defaultValueNumeric="0.00" remarks="触发点位置"/>
             <column name="direction" type="${number.type}" defaultValueNumeric="1" remarks="进路方向"/>
+            <column name="route_status" type="${number.type}" defaultValueNumeric="2" remarks="进路状态"/>
         </createTable>
     </changeSet>
     <changeSet id="load-db_route-data" author="zhanghaijun" failOnError="false" runOnChange="true">

+ 9 - 9
train-server/src/main/resources/db/changelog/db_route.txt

@@ -1,9 +1,9 @@
-id,name,signal_ids,signal_state,sele_ids,switch_id,switch_state,trig_position,direction
-108001,S0306-S0301,101016,3,103025-103032-103031-103010-103009,102007-102004,2-2,7196.89,1
-108002,S0301-S0201,101011,2,103008-103007,-1,-1,6841.26,1
-108003,S0201-S0103,101007,2,103006-103005,-1,-1,3941.26,1
-108004,S0103-S0102,101002,3,103012-103030-103029-103015-103014,102003-102002,2-2,550,1
-108005,S0102-S0106,101002,2,103015-103016-103017-103018,102002-102004,1-1,130,2
-108006,S0106-S0204,101006,2,103019-103020,-1,-1,585,2
-108007,S0204-S0304,101010,2,103021-103022,-1,-1,3641,2
-108008,S0304-S0306,101014,2,103023-103024-103025-103026,102005-102007,1-1,6786,2
+id,name,signal_ids,signal_state,sele_ids,switch_id,switch_state,trig_position,direction,route_status
+108001,S0306-S0301,101016,3,103025-103032-103031-103010-103009,102007-102004,2-2,7196.89,1,2
+108002,S0301-S0201,101011,2,103008-103007,-1,-1,6841.26,1,2
+108003,S0201-S0103,101007,2,103006-103005,-1,-1,3941.26,1,2
+108004,S0103-S0102,101002,3,103012-103030-103029-103015-103014,102003-102002,2-2,550,1,2
+108005,S0102-S0106,101002,2,103015-103016-103017-103018,102002-102004,1-1,130,2,2
+108006,S0106-S0204,101006,2,103019-103020,-1,-1,585,2,2
+108007,S0204-S0304,101010,2,103021-103022,-1,-1,3641,2,2
+108008,S0304-S0306,101014,2,103023-103024-103025-103026,102005-102007,1-1,6786,2,2