模拟设备状态变更接口

This commit is contained in:
tiger_zhou 2023-07-04 15:15:47 +08:00
parent a5c2b0a202
commit e2bb76fd47
7 changed files with 285 additions and 46 deletions

View File

@ -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) {

View File

@ -52,21 +52,21 @@ public final class DeviceStatusProto {
*/
PLATFORM(7),
/**
* <code>SCADA = 8;</code>
* <code>SCADA = 9;</code>
*/
SCADA(8),
SCADA(9),
/**
* <code>WATERPROOF_DOOR = 9;</code>
* <code>WATERPROOF_DOOR = 11;</code>
*/
WATERPROOF_DOOR(9),
WATERPROOF_DOOR(11),
/**
* <code>WORK_AREA = 10;</code>
* <code>WORK_AREA = 12;</code>
*/
WORK_AREA(10),
WORK_AREA(12),
/**
* <code>GAMA = 11;</code>
* <code>GAMA = 13;</code>
*/
GAMA(11),
GAMA(13),
UNRECOGNIZED(-1),
;
@ -103,21 +103,21 @@ public final class DeviceStatusProto {
*/
public static final int PLATFORM_VALUE = 7;
/**
* <code>SCADA = 8;</code>
* <code>SCADA = 9;</code>
*/
public static final int SCADA_VALUE = 8;
public static final int SCADA_VALUE = 9;
/**
* <code>WATERPROOF_DOOR = 9;</code>
* <code>WATERPROOF_DOOR = 11;</code>
*/
public static final int WATERPROOF_DOOR_VALUE = 9;
public static final int WATERPROOF_DOOR_VALUE = 11;
/**
* <code>WORK_AREA = 10;</code>
* <code>WORK_AREA = 12;</code>
*/
public static final int WORK_AREA_VALUE = 10;
public static final int WORK_AREA_VALUE = 12;
/**
* <code>GAMA = 11;</code>
* <code>GAMA = 13;</code>
*/
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

View File

@ -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, GeneratedMessageV3.Builder> 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("");

View File

@ -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;
}
}

View File

@ -53,12 +53,11 @@ 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();
}
}
return null;
}
@ -82,9 +81,12 @@ public class LineDeviceMessageServer implements IMessageServer {
}
WsLineMessage.Builder msg = WsLineMessage.newBuilder();
fillBuilderFunction((field) -> deviceDataSource.getStatusVOMap().get(field), msg);
if (this.isNotNull(msg)) {
DeviceStatusDataOperate.clearStatusVOMap(DeviceStatusDataRepository.getDeviceStatusData(lineId));
messages.add(new TopicMessage(destination, msg.build().toByteArray()));
}
}
return messages;
}

View File

@ -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<StompSession> 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;

@ -1 +1 @@
Subproject commit 8fd000d45907f94410786c3bd6c1ab37edbe91e8
Subproject commit 1ab5b1ae7fd44e5b31e424407f3b783b40190c95