diff --git a/src/main/java/club/joylink/xiannccda/ats/message/line3/device/DeviceType.java b/src/main/java/club/joylink/xiannccda/ats/message/line3/device/DeviceType.java index ab13636..a79a1e3 100644 --- a/src/main/java/club/joylink/xiannccda/ats/message/line3/device/DeviceType.java +++ b/src/main/java/club/joylink/xiannccda/ats/message/line3/device/DeviceType.java @@ -5,31 +5,56 @@ import lombok.Getter; @Getter public enum DeviceType { - /** 未知的设备 */ + /** + * 未知的设备 + */ DEVICE_TYPE_UNKNOW(0), - /** 集中站 */ + /** + * 集中站 + */ DEVICE_TYPE_RTU(1), - /** 车站 */ + /** + * 车站 + */ DEVICE_TYPE_STATION(2), - /** 信号机 */ + /** + * 信号机 + */ DEVICE_TYPE_SIGNAL(3), - /** 道岔 */ + /** + * 道岔 + */ DEVICE_TYPE_SWITCH(4), - /** 轨道 */ + /** + * 轨道 + */ DEVICE_TYPE_TRACK(5), - /** 方向 */ + /** + * 方向 + */ DEVICE_TYPE_ENTRY(6), - /** 站台 */ + /** + * 站台 + */ DEVICE_TYPE_PLATFORM(7), - /** 供电区段 */ + /** + * 供电区段 + */ DEVICE_TYPE_SCADA(9), - /** 防淹门 */ + /** + * 防淹门 + */ DEVICE_TYPE_WATERPROOF_DOOR(11), - /** 工作区 */ + /** + * 工作区 + */ DEVICE_TYPE_WORK_AREA(12), - /** 区域自动驾驶 */ + /** + * 区域自动驾驶 + */ DEVICE_TYPE_GAMA(13), ; + @Getter int val; DeviceType(int d) { diff --git a/src/main/java/club/joylink/xiannccda/dto/protos/DeviceStatusProto.java b/src/main/java/club/joylink/xiannccda/dto/protos/DeviceStatusProto.java index 36cd05c..1e32a1c 100644 --- a/src/main/java/club/joylink/xiannccda/dto/protos/DeviceStatusProto.java +++ b/src/main/java/club/joylink/xiannccda/dto/protos/DeviceStatusProto.java @@ -52,21 +52,21 @@ public final class DeviceStatusProto { */ PLATFORM(7), /** - * SCADA = 8; + * SCADA = 9; */ - SCADA(8), + SCADA(9), /** - * WATERPROOF_DOOR = 9; + * WATERPROOF_DOOR = 11; */ - WATERPROOF_DOOR(9), + WATERPROOF_DOOR(11), /** - * WORK_AREA = 10; + * WORK_AREA = 12; */ - WORK_AREA(10), + WORK_AREA(12), /** - * GAMA = 11; + * GAMA = 13; */ - GAMA(11), + GAMA(13), UNRECOGNIZED(-1), ; @@ -103,21 +103,21 @@ public final class DeviceStatusProto { */ public static final int PLATFORM_VALUE = 7; /** - * SCADA = 8; + * SCADA = 9; */ - public static final int SCADA_VALUE = 8; + public static final int SCADA_VALUE = 9; /** - * WATERPROOF_DOOR = 9; + * WATERPROOF_DOOR = 11; */ - public static final int WATERPROOF_DOOR_VALUE = 9; + public static final int WATERPROOF_DOOR_VALUE = 11; /** - * WORK_AREA = 10; + * WORK_AREA = 12; */ - public static final int WORK_AREA_VALUE = 10; + public static final int WORK_AREA_VALUE = 12; /** - * GAMA = 11; + * GAMA = 13; */ - public static final int GAMA_VALUE = 11; + public static final int GAMA_VALUE = 13; public final int getNumber() { @@ -152,10 +152,10 @@ public final class DeviceStatusProto { case 5: return TRACK; case 6: return ENTRY; case 7: return PLATFORM; - case 8: return SCADA; - case 9: return WATERPROOF_DOOR; - case 10: return WORK_AREA; - case 11: return GAMA; + case 9: return SCADA; + case 11: return WATERPROOF_DOOR; + case 12: return WORK_AREA; + case 13: return GAMA; default: return null; } } @@ -19381,8 +19381,8 @@ public final class DeviceStatusProto { "\001(\010*\243\001\n\nDeviceType\022\n\n\006UNKNOW\020\000\022\007\n\003RTU\020\001\022" + "\013\n\007STATION\020\002\022\n\n\006SIGNAL\020\003\022\n\n\006SWITCH\020\004\022\t\n\005" + "TRACK\020\005\022\t\n\005ENTRY\020\006\022\014\n\010PLATFORM\020\007\022\t\n\005SCAD" + - "A\020\010\022\023\n\017WATERPROOF_DOOR\020\t\022\r\n\tWORK_AREA\020\n\022" + - "\010\n\004GAMA\020\013B6\n!club.joylink.xiannccda.dto." + + "A\020\t\022\023\n\017WATERPROOF_DOOR\020\013\022\r\n\tWORK_AREA\020\014\022" + + "\010\n\004GAMA\020\rB6\n!club.joylink.xiannccda.dto." + "protosB\021DeviceStatusProtob\006proto3" }; descriptor = com.google.protobuf.Descriptors.FileDescriptor diff --git a/src/main/java/club/joylink/xiannccda/mock/message/MockDeviceController.java b/src/main/java/club/joylink/xiannccda/mock/message/MockDeviceController.java index 9157077..8293109 100644 --- a/src/main/java/club/joylink/xiannccda/mock/message/MockDeviceController.java +++ b/src/main/java/club/joylink/xiannccda/mock/message/MockDeviceController.java @@ -4,6 +4,7 @@ import club.joylink.xiannccda.ats.message.OccMessageManage; import club.joylink.xiannccda.ats.message.collect.DeviceDataRepository; import club.joylink.xiannccda.ats.message.collect.DeviceDataRepository.DataTypeEnum; import club.joylink.xiannccda.ats.message.line3.DateTimeUtil; +import club.joylink.xiannccda.ats.message.line3.device.DeviceType; import club.joylink.xiannccda.ats.message.line3.req.AlarmAckRequest; import club.joylink.xiannccda.ats.message.line3.req.AlarmAckRequest.MsgTypeEnum; import club.joylink.xiannccda.ats.message.line3.req.LoadDeviceStatusRequest; @@ -14,14 +15,23 @@ import club.joylink.xiannccda.ats.message.line3.req.ReportAskRequest.MsgFlagEnum import club.joylink.xiannccda.dto.protos.DeviceStatusProto; import club.joylink.xiannccda.dto.protos.DeviceStatusProto.Scada; +import club.joylink.xiannccda.dto.protos.DeviceStatusProto.TrainMode; +import club.joylink.xiannccda.dto.protos.LayoutGraphicsProto; +import club.joylink.xiannccda.dto.protos.TrainProto; +import club.joylink.xiannccda.dto.protos.TrainProto.NccWindow; +import club.joylink.xiannccda.dto.protos.TrainProto.TrainRemove; import club.joylink.xiannccda.mock.message.Status.Platform; import club.joylink.xiannccda.mock.message.Status.Rtu; import club.joylink.xiannccda.mock.message.Status.SCDAD; import club.joylink.xiannccda.mock.message.Status.Signal; import club.joylink.xiannccda.mock.message.Status.Switch; import club.joylink.xiannccda.mock.message.Status.Track; +import club.joylink.xiannccda.mock.message.Status.Train; +import club.joylink.xiannccda.mock.message.Status.TrainBlock; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; +import com.google.common.collect.Maps; +import com.google.protobuf.Descriptors.EnumDescriptor; import com.google.protobuf.Descriptors.FieldDescriptor; import com.google.protobuf.GeneratedMessageV3; import io.swagger.v3.oas.annotations.Operation; @@ -30,6 +40,8 @@ import io.swagger.v3.oas.annotations.tags.Tag; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.List; +import java.util.Map; +import java.util.Objects; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.web.bind.annotation.GetMapping; @@ -51,6 +63,24 @@ public class MockDeviceController { @Autowired private OccMessageManage occMessageManage; + @Operation(summary = "train阻塞状态设置变更") + @PostMapping("train/remove/{lineId}") + public void trainRemove(@PathVariable("lineId") String lineId, @RequestBody Status.TrainRemove train) { + this.saveBuild(lineId, train, TrainProto.TrainRemove.newBuilder()); + } + + @Operation(summary = "train阻塞状态设置变更") + @PostMapping("train/Block/{lineId}") + public void trainBlock(@PathVariable("lineId") String lineId, @RequestBody Status.TrainBlock train) { + this.saveBuild(lineId, train, TrainProto.TrainBlock.newBuilder()); + } + + @Operation(summary = "train位置状态设置变更") + @PostMapping("train/offset/{lineId}") + public void changeTrainOffset(@PathVariable("lineId") String lineId, @RequestBody Train train) { + this.saveBuild(lineId, train, TrainProto.TrainInfo.newBuilder()); + } + @Operation(summary = "rtu状态设置变更") @PostMapping("rtu/status/{lineId}") public void changeRtuStatus(@PathVariable("lineId") String lineId, @RequestBody Rtu rtu) { @@ -87,14 +117,52 @@ public class MockDeviceController { this.saveBuild(lineId, scdad, Scada.newBuilder()); } + static Map CLASS_BUILDER_MAP = Maps.newHashMap(); + + static { + CLASS_BUILDER_MAP.put(Status.TrainMode.class, TrainMode.newBuilder()); + CLASS_BUILDER_MAP.put(Status.NccWindow.class, NccWindow.newBuilder()); + } + + + private void setVal(GeneratedMessageV3.Builder builder, String key, Object val) { + FieldDescriptor fieldDesc = builder.getDescriptorForType().findFieldByName(key); + if (val.getClass() == DeviceType.class) { + DeviceType dt = (DeviceType) val; + EnumDescriptor enumD = builder.getDescriptorForType().findEnumTypeByName(key); + + DeviceStatusProto.DeviceType dt2 = DeviceStatusProto.DeviceType.forNumber(dt.getVal()); + builder.setField(fieldDesc, dt2.getValueDescriptor()); + + } else { + builder.setField(fieldDesc, val); + + } + } + + private void saveBuild(String lineId, Object obj, GeneratedMessageV3.Builder builder) { Object jo = JSON.toJSON(obj); + DataTypeEnum dataType = DataTypeEnum.DEVICE; + if (obj instanceof Status.Train || obj instanceof Status.TrainBlock || obj instanceof Status.TrainRemove) { + dataType = DataTypeEnum.TRAIN; + } if (jo instanceof JSONObject jsonObject) { for (String s : jsonObject.keySet()) { - FieldDescriptor fieldDesc = builder.getDescriptorForType().findFieldByName(s); - builder.setField(fieldDesc, jsonObject.get(s)); + Object val = jsonObject.get(s); + GeneratedMessageV3.Builder messsageBuilder = CLASS_BUILDER_MAP.get(val.getClass()); + if (Objects.isNull(messsageBuilder)) { + this.setVal(builder, s, val); + } else { + GeneratedMessageV3.Builder cloneBuilder = messsageBuilder.clone(); + JSONObject jo2 = val instanceof JSONObject ? (JSONObject) val : (JSONObject) JSON.toJSON(val); + for (String s1 : jo2.keySet()) { + Object v = jo2.get(s1); + this.setVal(cloneBuilder, s1, v); + } + } } - DeviceDataRepository.add(lineId, List.of(builder), DataTypeEnum.DEVICE); + DeviceDataRepository.add(lineId, List.of(builder), dataType); } else { throw new RuntimeException(""); diff --git a/src/main/java/club/joylink/xiannccda/mock/message/Status.java b/src/main/java/club/joylink/xiannccda/mock/message/Status.java index 1096284..24f4054 100644 --- a/src/main/java/club/joylink/xiannccda/mock/message/Status.java +++ b/src/main/java/club/joylink/xiannccda/mock/message/Status.java @@ -1,5 +1,7 @@ package club.joylink.xiannccda.mock.message; +import club.joylink.xiannccda.ats.message.line3.device.DeviceType; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.Getter; import lombok.Setter; @@ -154,4 +156,143 @@ public class Status { private String id; } + @Data + public static class Train { + + String groupId; + NccWindow window; + TrainMode trainMode; + @Schema(description = "设备类型 DEVICE_TYPE_UNKNOW;\n" + + " DEVICE_TYPE_RTU;\n" + + " DEVICE_TYPE_STATION;\n" + + " DEVICE_TYPE_SIGNAL;\n" + + " DEVICE_TYPE_SWITCH;\n" + + " DEVICE_TYPE_TRACK;\n" + + " DEVICE_TYPE_ENTRY;\n" + + " DEVICE_TYPE_PLATFORM;\n" + + " DEVICE_TYPE_SCADA;\n" + + " DEVICE_TYPE_WATERPROOF_DOOR;\n" + + " DEVICE_TYPE_WORK_AREA;\n" + + " DEVICE_TYPE_GAMA;") + DeviceType devType; + String devName; + } + + @Data + public static class TrainBlock { + + Integer lineId; + // 列车编组号 + String groupId; + // 表号 + String trainId; + // 方向 + // 0:上行 + // 1:下行 + // 2:未知 + Integer direction; + // 列车所在区间左边车站的站号 + Integer stationIDInUpSide; + // 列车所在区间右边车站的站号 + Integer stationIDInDownSide; + // 集中站站号 + Integer rtuId; + // 列车所在的设备的类型 + @Schema(description = "设备类型 DEVICE_TYPE_UNKNOW;\n" + + " DEVICE_TYPE_RTU;\n" + + " DEVICE_TYPE_STATION;\n" + + " DEVICE_TYPE_SIGNAL;\n" + + " DEVICE_TYPE_SWITCH;\n" + + " DEVICE_TYPE_TRACK;\n" + + " DEVICE_TYPE_ENTRY;\n" + + " DEVICE_TYPE_PLATFORM;\n" + + " DEVICE_TYPE_SCADA;\n" + + " DEVICE_TYPE_WATERPROOF_DOOR;\n" + + " DEVICE_TYPE_WORK_AREA;\n" + + " DEVICE_TYPE_GAMA;") + DeviceType deviceType; + String devName; + // 列车所在的设备的名称 + // 列车阻塞标记 + // 1:列车阻塞 + // 0:列车没有阻塞 + Integer blockFlag; + } + + @Data + public static class TrainRemove { + + Integer lineId; + // 集中站站号 + Integer rtuId; + // NCC车次窗编号 + // 列车在车次窗中的位置 + NccWindow window; + // 列车所在的设备的类型 + @Schema(description = "设备类型 DEVICE_TYPE_UNKNOW;\n" + + " DEVICE_TYPE_RTU;\n" + + " DEVICE_TYPE_STATION;\n" + + " DEVICE_TYPE_SIGNAL;\n" + + " DEVICE_TYPE_SWITCH;\n" + + " DEVICE_TYPE_TRACK;\n" + + " DEVICE_TYPE_ENTRY;\n" + + " DEVICE_TYPE_PLATFORM;\n" + + " DEVICE_TYPE_SCADA;\n" + + " DEVICE_TYPE_WATERPROOF_DOOR;\n" + + " DEVICE_TYPE_WORK_AREA;\n" + + " DEVICE_TYPE_GAMA;") + DeviceType deviceType; + String devName; + // 列车标示号,全线唯一(若无法提供,缺省值为0) + String trainIndex; + // 列车编组号 + String groupId; + } + + @Data + public static class NccWindow { + + Integer nccWindow; + Integer nccWinOffset; + } + + @Data + public static class TrainMode { + + Boolean ipModeTrainTypeManual; + Boolean ipModeTrainTypeHead; + Boolean ipModeTrainTypeSpecial; + Boolean ipModeTrainTypeSchedule; + // Boolean ipModeTrainTypeRoute; +// Boolean ipModeTrainTypeShuttle; +// Boolean ipModeTrainTypeLineup; + Boolean ipModeTrainSchdEarly; + Boolean ipModeTrainSchdLate; + Boolean ipModeTrainSkipstop; + Boolean ipModeTrainCbtcMode; + Boolean ipModeTrainAtpCut; + Boolean ipModeTrainBerthed; + // Boolean ipModeTrainStoped; + Boolean ipModeTrainHolded; + // Boolean ipModeTrainItama; + Boolean ipModeTrainDirUp; + Boolean ipModeTrainDirDown; + Boolean ipModeTrainDirHeadUp; + Boolean ipModeTrainDirHeadDown; + Boolean ipModeTrainDoorOpen; + // Boolean ipModeTrainRsAlarm; +// Boolean ipModeTrainDoorAlarm; + Boolean ipModeTrainEbAlarm; + Boolean ipModeTrainIntegrityAlarm; + Boolean ipModeTrainDriveModeAm; + Boolean ipModeTrainDriveModeCm; + Boolean ipModeTrainDriveModeRmf; + // Boolean ipModeTrainDriveModeDto; + Boolean ipModeTrainDriveModeAtb; + Boolean ipModeTrainDriveBlockAm; + Boolean ipModeTrainDriveBlockCm; + Boolean ipModeTrainDriveModeRmr; +// Boolean ipModeTrainDriveModeWash; + } + } diff --git a/src/main/java/club/joylink/xiannccda/ws/LineDeviceMessageServer.java b/src/main/java/club/joylink/xiannccda/ws/LineDeviceMessageServer.java index 8461490..6e0413c 100644 --- a/src/main/java/club/joylink/xiannccda/ws/LineDeviceMessageServer.java +++ b/src/main/java/club/joylink/xiannccda/ws/LineDeviceMessageServer.java @@ -53,11 +53,10 @@ public class LineDeviceMessageServer implements IMessageServer { builderMap.forEach((k, v) -> messageMap.put(k, v.build())); return messageMap; }, builder); - if (this.isNull(builder)) { - return null; + if (this.isNotNull(builder)) { + WsLineMessage buildMsg = builder.build(); + return buildMsg.toByteArray(); } - WsLineMessage buildMsg = builder.build(); - return buildMsg.toByteArray(); } return null; } @@ -82,8 +81,11 @@ public class LineDeviceMessageServer implements IMessageServer { } WsLineMessage.Builder msg = WsLineMessage.newBuilder(); fillBuilderFunction((field) -> deviceDataSource.getStatusVOMap().get(field), msg); - DeviceStatusDataOperate.clearStatusVOMap(DeviceStatusDataRepository.getDeviceStatusData(lineId)); - messages.add(new TopicMessage(destination, msg.build().toByteArray())); + if (this.isNotNull(msg)) { + DeviceStatusDataOperate.clearStatusVOMap(DeviceStatusDataRepository.getDeviceStatusData(lineId)); + messages.add(new TopicMessage(destination, msg.build().toByteArray())); + } + } return messages; } diff --git a/src/test/java/club/joylink/xiannccda/service/StompTest.java b/src/test/java/club/joylink/xiannccda/service/StompTest.java index b3fc2c4..6bc59f5 100644 --- a/src/test/java/club/joylink/xiannccda/service/StompTest.java +++ b/src/test/java/club/joylink/xiannccda/service/StompTest.java @@ -21,6 +21,9 @@ public class StompTest { @Test public void subscribe() { + + String token = "eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJzZWxmIiwic3ViIjoiOSIsImV4cCI6MTY4ODY5OTQ0OSwiaWF0IjoxNjg4NDQwMjQ5fQ.gYCTq_oPw_31MqnH3VZ71RVm659Lim8z86-VnEV9D4XIvr8GNblkN1cMNC2TH5HkqzKMUDJC_Nn-bH6n1LcJQTwJv1V4kY8cm1rCN8aedxRgq5NGIrDl5K2zLy9qvs-iOHQF8PdK2KC8zWy1RV9t34cuSsUsiCc14-KmvCRXE801YSpzLsOgF0Ulz4fl-CDX5LO2fGyFF6Lv298BOvbocfJ3KghpvocuT2tx5nl2C4tHfLV5XRxD9cQlsoRi_VOQp8Y49mRdhIe-vOv_rkOaRNuINdyAfYTyntKv0IkKj3Rh6y0wERV-ymkfsfgm-0gkeQ9qtwVIBjEK5Btq0LhlSQ"; + StandardWebSocketClient socketClient = new StandardWebSocketClient(); WebSocketStompClient stompClient = new WebSocketStompClient(socketClient); @@ -28,7 +31,7 @@ public class StompTest { WebSocketHttpHeaders headers = new WebSocketHttpHeaders(); StompHeaders headers1 = new StompHeaders(); headers1.set("Authorization", - "Bearer eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJzZWxmIiwic3ViIjoiOSIsImV4cCI6MTY4NzkzODcwNCwiaWF0IjoxNjg3Njc5NTA0fQ.W__1N-IyXIJ4SIPsFviK-1q_0H9lqQsr0uI6VhdpZsPME63Aes8Fr23XItIlVqb14pgWVeVxTnRMKnG8gKzqFj8FTJs6c2jo5wDYX2UTBED3GPBIdzPTNETQATwh2vQNoItxyGcepVzToN4jmjtIScmtly3ppIXmCgYUNtwniWRz_5FAbDyy18cawd7-rr9ex37uahUewdohgrQFDOHDRzxC0M5AGTpfxKIiXHYs-rGdyfqhvhpoy26bM0TTMr8_EpssODLY8EvSLFfQgqtzhlXbrOQWuOjG7fQ4RQa1cKFHzFtQPosIkE3gsvyCRw2BCLERlqmGoAor-3RZ5Mqv_w"); + "Bearer " + token); CompletableFuture future = stompClient.connectAsync("ws://127.0.0.1:9081/ws-default", headers, headers1, handler); @@ -38,7 +41,7 @@ public class StompTest { } catch (Exception e) { e.printStackTrace(); } - stompSession.subscribe("/queue/line/3", new StompFrameHandler() { + stompSession.subscribe("/queue/line/3/device", new StompFrameHandler() { @Override public Type getPayloadType(StompHeaders stompHeaders) { return byte[].class; diff --git a/xian-ncc-da-message b/xian-ncc-da-message index 8fd000d..1ab5b1a 160000 --- a/xian-ncc-da-message +++ b/xian-ncc-da-message @@ -1 +1 @@ -Subproject commit 8fd000d45907f94410786c3bd6c1ab37edbe91e8 +Subproject commit 1ab5b1ae7fd44e5b31e424407f3b783b40190c95