1 occ 消息解析资源释放
2生成protobuf设备名称解析
3添加消息处理类
4 删除老版本设备解析
This commit is contained in:
tiger_zhou 2023-07-20 11:09:47 +08:00
parent 43cd1bffb0
commit c5cbe04ab8
12 changed files with 136 additions and 130 deletions

View File

@ -5,6 +5,7 @@ import io.netty.buffer.Unpooled;
import java.util.ArrayList;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
@Slf4j
public class FrameSchema {
@ -96,6 +97,33 @@ public class FrameSchema {
return messages;
}
public static List<MessageData> decode2(ByteBuf in) throws Exception {
in.markReaderIndex();
List<FrameSchema> frames = new ArrayList<>();
frameDecode2(in, frames);
if (CollectionUtils.isEmpty(frames)) {
in.resetReaderIndex();
return null;
}
ByteBuf buf = Unpooled.buffer();
for (FrameSchema frame : frames) {
buf.writeBytes(frame.packageData);
frame.packageData.release();
}
try {
List<MessageData> messages = new ArrayList<>();
messageDecode(buf, messages);
return messages;
} catch (Exception e) {
log.error("OCC消息解析异常", e);
return null;
} finally {
buf.release();
}
}
@Deprecated
public static List<MessageData> decode(ByteBuf in) throws Exception {
in.markReaderIndex();
boolean success = true;
@ -103,16 +131,21 @@ public class FrameSchema {
List<FrameSchema> frames = new ArrayList<>();
frameDecode(in, frames);
if (frames.size() > 0) {
//拼装数据包
ByteBuf buf = Unpooled.buffer();
for (FrameSchema frame : frames) {
buf.writeBytes(frame.packageData);
frame.packageData.release();
}
//数据包解析业务
List<MessageData> messages = new ArrayList<>();
try {
messageDecode(buf, messages);
} catch (Exception e) {
log.error("OCC消息解析异常", e);
return null;
} finally {
buf.release();
}
return messages;
} else {
@ -138,7 +171,10 @@ public class FrameSchema {
*/
private static void messageDecode(ByteBuf buf, List<MessageData> messages) throws Exception {
int len = buf.getUnsignedShort(0);
ByteBuf msgBuf = buf.readBytes(len + 2);
byte[] msgData = new byte[len + 2];
buf.readBytes(msgData);
ByteBuf msgBuf = Unpooled.wrappedBuffer(msgData);
// ByteBuf msgBuf = buf.readBytes(len + 2);
int msgId = msgBuf.getUnsignedShort(8);
MessageId messageId = MessageId.of(msgId);
if (messageId.equals(MessageId.UNKNOWN)) {
@ -164,6 +200,7 @@ public class FrameSchema {
* @param frames
* @throws Exception
*/
@Deprecated
static void frameDecode(ByteBuf in, List<FrameSchema> frames) throws Exception {
if (in.readableBytes() < 4) {
throw new Exception("数据不全");
@ -172,8 +209,9 @@ public class FrameSchema {
int totalLength = in.readUnsignedShort();
short flag = in.readUnsignedByte();
int contentLen = totalLength - 1;
if (in.readableBytes() < contentLen) {
throw new Exception("可读内容不足");
int readables = in.readableBytes();
if (readables < contentLen) {
throw new Exception(String.format("可读内容不足 sysId[%s] totalLen[%s] flag[%s] contentLen[%s] readableBytes[%s]", sysId, totalLength, flag, contentLen, readables));
}
frames.add(new FrameSchema(sysId, in.readBytes(contentLen)));
if (flag == Flag_Multi) {
@ -181,6 +219,39 @@ public class FrameSchema {
}
}
/**
* 信息帧解析
*
* @param in
* @param frames
*/
static void frameDecode2(ByteBuf in, List<FrameSchema> frames) {
int totalReadables = in.readableBytes();
if (totalReadables < 4) {
log.error("数据不全,当前可读[{}]", totalReadables);
frames.clear();
return;
}
short sysId = in.readUnsignedByte();
int totalLength = in.readUnsignedShort();
short flag = in.readUnsignedByte();
int contentLen = totalLength - 1;
int readables = in.readableBytes();
if (readables < contentLen) {
log.error("可读内容不足 sysId[{}] totalLen[{}] flag[{}] contentLen[{}] readableBytes[{}]", sysId, totalLength, flag, contentLen, readables);
frames.clear();
return;
}
ByteBuf contentByte = Unpooled.buffer(contentLen);
in.readBytes(contentByte);
// frames.add(new FrameSchema(sysId, in.readBytes(contentLen)));
frames.add(new FrameSchema(sysId, contentByte));
if (flag == Flag_Multi) {
frameDecode2(in, frames);
}
}
public void encode(ByteBuf buf) {
buf.writeByte(this.systemId);
buf.writeShort(this.totalLength);

View File

@ -68,7 +68,9 @@ public abstract class MessageData {
this.version = buf.readUnsignedShort();
this.msgId = MessageId.of(buf.readShort());
this.decode2(buf);
buf.release();
} else {
buf.release();
throw new Exception(
String.format("OCC消息可读字节数小于%sreadableBytes=%s", headerBytes, readableBytes));
}

View File

@ -20,15 +20,14 @@ public class OccMessageDecoder extends ByteToMessageDecoder {
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
connection.lastReceiveMessageTime = System.currentTimeMillis();
List<MessageData> messages = FrameSchema.decode(in);
List<MessageData> messages = FrameSchema.decode2(in);
if (!(messages == null || messages.size() == 0)) {
System.out.println(
String.format(
"收到OCC消息: %s",
JSON.toJSONString(
messages.get(0), Feature.PrettyFormat, Feature.FieldBased, Feature.WriteNulls)));
MockAppContext.publish(messages);
DeviceStatusConvertorManager.doConvertor(messages);
out.add(messages);
}
}

View File

@ -0,0 +1,25 @@
package club.joylink.xiannccda.ats.message;
import club.joylink.xiannccda.ats.message.collect.DeviceStatusConvertorManager;
import club.joylink.xiannccda.mock.message.MockAppContext;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.ReferenceCountUtil;
import java.util.Collections;
import java.util.List;
import org.springframework.util.CollectionUtils;
public class OccMessageHandler extends SimpleChannelInboundHandler<List<MessageData>> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, List<MessageData> msg) throws Exception {
if (CollectionUtils.isEmpty(msg)) {
ReferenceCountUtil.release(msg);
return;
}
MockAppContext.publish(msg);
DeviceStatusConvertorManager.doConvertor(msg);
}
}

View File

@ -58,6 +58,7 @@ public class OccTcpClientConnection {
protected void initChannel(Channel ch) {
ch.pipeline().addLast(new OccMessageEncoder(self));
ch.pipeline().addLast(new OccMessageDecoder(self));
ch.pipeline().addLast(new OccMessageHandler());
}
});

View File

@ -1,108 +0,0 @@
package club.joylink.xiannccda.ats.message.line3;
import club.joylink.xiannccda.ats.message.line3.device.DeviceType;
import club.joylink.xiannccda.dto.protos.LayoutGraphicsProto;
import club.joylink.xiannccda.dto.protos.LayoutGraphicsProto.RtssGraphicStorage;
import club.joylink.xiannccda.dto.protos.LayoutGraphicsProto.Section;
import club.joylink.xiannccda.dto.protos.LayoutGraphicsProto.Signal;
import club.joylink.xiannccda.dto.protos.LayoutGraphicsProto.Turnout;
import com.google.common.collect.Maps;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@Deprecated
public abstract class DeviceNameChanger implements NameChanger {
static Map<DeviceType, DeviceNameChanger> NCC_DEVICE_TYPE_NAME_MAPPER = Maps.newHashMap();
static {
NCC_DEVICE_TYPE_NAME_MAPPER.put(DeviceType.DEVICE_TYPE_SWITCH, new SwitchDevice());
NCC_DEVICE_TYPE_NAME_MAPPER.put(DeviceType.DEVICE_TYPE_SIGNAL, new SignalDevice());
NCC_DEVICE_TYPE_NAME_MAPPER.put(DeviceType.DEVICE_TYPE_TRACK, new TrackDevice());
}
private final static Map<DeviceType, List<String>> DEVICE_NAMES = Maps.newHashMap();
public static void init(LayoutGraphicsProto.RtssGraphicStorage gs) {
for (DeviceNameChanger value : NCC_DEVICE_TYPE_NAME_MAPPER.values()) {
value.collectNames(gs);
}
}
public static String findMatch(DeviceType dt, String name) {
DeviceNameChanger nameChanger = NCC_DEVICE_TYPE_NAME_MAPPER.get(dt);
if (Objects.nonNull(nameChanger)) {
List<String> deviceNames = DEVICE_NAMES.get(dt);
nameChanger.changeDeviceName(name, deviceNames);
}
return name;
}
public static void main(String[] args) {
// X1506_L2
new TrackDevice().changeDeviceName("TP_2DG", List.of("P_2DG"));
new SignalDevice().changeDeviceName("X1506_L2", List.of("X1506-L2"));
}
public static class SwitchDevice extends DeviceNameChanger {
@Override
public void collectNames(RtssGraphicStorage graphicStorage) {
List<String> names = graphicStorage.getTurnoutsList().stream().map(Turnout::getCode).toList();
DEVICE_NAMES.put(DeviceType.DEVICE_TYPE_SWITCH, names);
}
@Override
public String changeDeviceName(String nccDeviceName, List<String> graphicNames) {
if (nccDeviceName.length() < 3) {
return nccDeviceName;
}
String started = nccDeviceName.substring(0, 1);
String head = nccDeviceName.substring(1, 3);
String tail = nccDeviceName.substring(4);
return started + tail + head;
}
}
public static class TrackDevice extends DeviceNameChanger {
@Override
public void collectNames(RtssGraphicStorage graphicStorage) {
List<String> names = graphicStorage.getSectionList().stream().map(Section::getCode).toList();
DEVICE_NAMES.put(DeviceType.DEVICE_TYPE_TRACK, names);
}
@Override
public String changeDeviceName(String nccDeviceName, List<String> graphicNames) {
if (nccDeviceName.length() < 4) {
return nccDeviceName;
}
return super.changeDeviceName(nccDeviceName, graphicNames);
}
}
public static class SignalDevice extends DeviceNameChanger {
@Override
public void collectNames(RtssGraphicStorage graphicStorage) {
List<String> names = graphicStorage.getSignalsList().stream().map(Signal::getCode).toList();
DEVICE_NAMES.put(DeviceType.DEVICE_TYPE_SIGNAL, names);
}
@Override
public String changeDeviceName(String nccDeviceName, List<String> graphicNames) {
if (nccDeviceName.length() <= 3) {
return nccDeviceName;
}
return super.changeDeviceName(nccDeviceName.replaceAll("_", "-"), graphicNames);
}
}
}

View File

@ -27,9 +27,17 @@ public class DeviceNameChangerManage {
final static Table<Integer, DeviceType, List<NameChangerFilter>> CHANGER_TABLE = HashBasedTable.create();
public static String findMatch(DeviceType deviceType, String occName) {
if (Objects.isNull(deviceType)) {
log.error("错误的设备类型 type[{}]", deviceType);
return occName;
}
if (Objects.isNull(occName)) {
log.error("错误的设备名称 occName[{}]", occName);
return occName;
}
List<NameChangerFilter> filters = CHANGER_TABLE.get(3, deviceType);
if (CollectionUtils.isEmpty(filters)) {
log.error("未找到对应的转换的occName:[{}] debiceType[{}]", occName, deviceType);
log.error("未找到对应的转换的occName:[{}] deviceType[{}]", occName, deviceType);
return occName;
}
for (NameChangerFilter filter : filters) {
@ -38,7 +46,7 @@ public class DeviceNameChangerManage {
return newName;
}
}
log.error("不能转换的occName:[{}] debiceType[{}]", occName, deviceType);
log.error("不能转换的occName:[{}] deviceType[{}]", occName, deviceType);
return occName;
}

View File

@ -72,8 +72,9 @@ public class DeviceStatusBitmapResponse extends MessageResponse {
DeviceType dt = deviceTypeEntity.getType();
for (DeviceEntity deviceEntity : deviceTypeEntity.deviceList) {
GeneratedMessageV3.Builder builder = DeviceStatusConvertor.convert(dt, deviceEntity.status);
DeviceStatusConvertor.fillField(builder, "id", deviceEntity.devName);
// DeviceStatusConvertor.fillField(builder, "id", deviceEntity.devName);
String newOccName = DeviceNameChangerManage.findMatch(dt, deviceEntity.devName);
DeviceStatusConvertor.fillField(builder, "id", newOccName);
DeviceStatusConvertor.convertForTrack(deviceEntity.getStatus(), builder);
DeviceStatusConvertor.convertForPlatform(deviceEntity.getStatus(), (Objects.isNull(deviceEntity.getSpare()) ? 0 : deviceEntity.getSpare()), builder);
DeviceStatusConvertor.convertForSwitch(Objects.isNull(deviceEntity.getSpare()) ? 0 : deviceEntity.getSpare(), builder);
@ -117,9 +118,9 @@ public class DeviceStatusBitmapResponse extends MessageResponse {
entity.type = DeviceType.of(buf.readShort());
entity.objCount = buf.readShort();
entity.deviceList = EntityParseUtil.collect(entity.objCount, buf, DeviceEntity.class);
for (DeviceEntity de : entity.deviceList) {
/* for (DeviceEntity de : entity.deviceList) {
de.devName = DeviceNameChangerManage.findMatch(entity.type, de.devName);
}
}*/
return entity;
}
}

View File

@ -82,14 +82,15 @@ public class DeviceStatusChangeResponse extends MessageResponse {
this.devName = EntityParseUtil.convertStr(buf, 24);
this.deviceStatus = buf.readInt();
this.spare = buf.readInt();
this.devName = DeviceNameChangerManage.findMatch(this.type, this.devName);
// this.devName = DeviceNameChangerManage.findMatch(this.type, this.devName);
}
@Override
public List<Builder> generateProto() {
GeneratedMessageV3.Builder builder = DeviceStatusConvertor.convert(this.type, this.deviceStatus);
DeviceStatusConvertor.fillField(builder, "id", this.devName);
// DeviceStatusConvertor.fillField(builder, "id", this.devName);
String occName = DeviceNameChangerManage.findMatch(this.type, this.devName);
DeviceStatusConvertor.fillField(builder, "id", occName);
DeviceStatusConvertor.convertForTrack(this.deviceStatus, builder);
DeviceStatusConvertor.convertForPlatform(this.deviceStatus, Objects.isNull(this.spare) ? 0 : this.spare, builder);
DeviceStatusConvertor.convertForSwitch(Objects.isNull(this.spare) ? 0 : this.spare, builder);

View File

@ -71,8 +71,11 @@ public class TrainIndicationInitResponse extends MessageResponse {
builder.setWindow(window);
if (trainCell.getDevType() != null) {
builder.setDevType(DeviceStatusProto.DeviceType.forNumber(trainCell.getDevType().getVal()));
}
builder.setDevName(StringUtils.defaultString(trainCell.getDevName(), ""));
// builder.setDevName(StringUtils.defaultString(trainCell.getDevName(), ""));
String occName = DeviceNameChangerManage.findMatch(trainCell.getDevType(), trainCell.getDevName());
builder.setDevName(occName);
builder.setTrainIndex(StringUtils.defaultString(trainCell.getTrainIndex(), ""));
builder.setGroupId(StringUtils.defaultString(trainCell.getGroupId(), ""));
@ -225,7 +228,7 @@ public class TrainIndicationInitResponse extends MessageResponse {
this.devType = DeviceType.of(devType);
this.devName = new String(devName, MessageCons.STRING_CHARSET).trim();
this.devName = DeviceNameChangerManage.findMatch(this.devType, this.devName);
// this.devName = DeviceNameChangerManage.findMatch(this.devType, this.devName);
this.trainIndex = new String(trainIndex, MessageCons.STRING_CHARSET).trim();
this.groupId = new String(groupId, MessageCons.STRING_CHARSET).trim();
this.trainId = new String(trainId, MessageCons.STRING_CHARSET).trim();

View File

@ -73,7 +73,7 @@ public class TrainIndicationRemoveResponse extends MessageResponse {
//
this.devType = DeviceType.of(devType);
this.devName = new String(devName, MessageCons.STRING_CHARSET).trim();
this.devName = DeviceNameChangerManage.findMatch(this.devType, this.devName);
// this.devName = DeviceNameChangerManage.findMatch(this.devType, this.devName);
this.trainIndex = new String(trainIndex, MessageCons.STRING_CHARSET).trim();
this.groupId = new String(groupId, MessageCons.STRING_CHARSET).trim();
}
@ -98,7 +98,9 @@ public class TrainIndicationRemoveResponse extends MessageResponse {
if (Objects.nonNull(this.devType)) {
trainRemove.setDeviceType(DeviceStatusProto.DeviceType.forNumber(this.devType.getVal()));
}
trainRemove.setDevName(StringUtils.defaultString(this.devName, ""));
// trainRemove.setDevName(StringUtils.defaultString(this.devName, ""));
String occName = DeviceNameChangerManage.findMatch(this.devType, this.devName);
trainRemove.setDevName(occName);
trainRemove.setTrainIndex(StringUtils.defaultString(this.trainIndex, ""));
trainRemove.setGroupId(StringUtils.defaultString(this.groupId, ""));

View File

@ -144,8 +144,9 @@ public class TrainIndicationUpdateResponse extends MessageResponse {
if (Objects.nonNull(this.devType)) {
train.setDevType(DeviceStatusProto.DeviceType.forNumber(this.devType.getVal()));
}
train.setDevName(StringUtils.defaultString(this.devName, ""));
// train.setDevName(StringUtils.defaultString(this.devName, ""));
String occName = DeviceNameChangerManage.findMatch(this.devType, this.devName);
train.setDevName(occName);
train.setTrainIndex(StringUtils.defaultString(this.trainIndex, ""));
train.setRollingStock(this.getRollingStock());
train.setOtpTime(this.optTime);
@ -213,7 +214,7 @@ public class TrainIndicationUpdateResponse extends MessageResponse {
this.devType = DeviceType.of(devType);
this.devName = new String(devName, MessageCons.STRING_CHARSET).trim();
this.devName = DeviceNameChangerManage.findMatch(this.devType, this.devName);
// this.devName = DeviceNameChangerManage.findMatch(this.devType, this.devName);
this.trainIndex = new String(trainIndex, MessageCons.STRING_CHARSET).trim();
this.groupId = new String(groupId, MessageCons.STRING_CHARSET).trim();
this.trainId = new String(trainId, MessageCons.STRING_CHARSET).trim();