diff --git a/src/main/java/club/joylink/xiannccda/ats/message/FrameSchema.java b/src/main/java/club/joylink/xiannccda/ats/message/FrameSchema.java index d5751a4..4ce36b3 100644 --- a/src/main/java/club/joylink/xiannccda/ats/message/FrameSchema.java +++ b/src/main/java/club/joylink/xiannccda/ats/message/FrameSchema.java @@ -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 decode2(ByteBuf in) throws Exception { + in.markReaderIndex(); + List 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 messages = new ArrayList<>(); + messageDecode(buf, messages); + return messages; + } catch (Exception e) { + log.error("OCC消息解析异常", e); + return null; + } finally { + buf.release(); + } + } + + @Deprecated public static List decode(ByteBuf in) throws Exception { in.markReaderIndex(); boolean success = true; @@ -103,16 +131,21 @@ public class FrameSchema { List 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 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 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 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 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); diff --git a/src/main/java/club/joylink/xiannccda/ats/message/MessageData.java b/src/main/java/club/joylink/xiannccda/ats/message/MessageData.java index ac61765..405158d 100644 --- a/src/main/java/club/joylink/xiannccda/ats/message/MessageData.java +++ b/src/main/java/club/joylink/xiannccda/ats/message/MessageData.java @@ -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消息可读字节数小于%s:readableBytes=%s", headerBytes, readableBytes)); } diff --git a/src/main/java/club/joylink/xiannccda/ats/message/OccMessageDecoder.java b/src/main/java/club/joylink/xiannccda/ats/message/OccMessageDecoder.java index b87c9b5..8e6fd54 100644 --- a/src/main/java/club/joylink/xiannccda/ats/message/OccMessageDecoder.java +++ b/src/main/java/club/joylink/xiannccda/ats/message/OccMessageDecoder.java @@ -20,15 +20,14 @@ public class OccMessageDecoder extends ByteToMessageDecoder { @Override protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { connection.lastReceiveMessageTime = System.currentTimeMillis(); - List messages = FrameSchema.decode(in); + List 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); } } diff --git a/src/main/java/club/joylink/xiannccda/ats/message/OccMessageHandler.java b/src/main/java/club/joylink/xiannccda/ats/message/OccMessageHandler.java new file mode 100644 index 0000000..778ce30 --- /dev/null +++ b/src/main/java/club/joylink/xiannccda/ats/message/OccMessageHandler.java @@ -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> { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, List msg) throws Exception { + if (CollectionUtils.isEmpty(msg)) { + ReferenceCountUtil.release(msg); + return; + + } + MockAppContext.publish(msg); + DeviceStatusConvertorManager.doConvertor(msg); + } + +} diff --git a/src/main/java/club/joylink/xiannccda/ats/message/OccTcpClientConnection.java b/src/main/java/club/joylink/xiannccda/ats/message/OccTcpClientConnection.java index 525f3eb..9f63c76 100644 --- a/src/main/java/club/joylink/xiannccda/ats/message/OccTcpClientConnection.java +++ b/src/main/java/club/joylink/xiannccda/ats/message/OccTcpClientConnection.java @@ -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()); } }); diff --git a/src/main/java/club/joylink/xiannccda/ats/message/line3/DeviceNameChanger.java b/src/main/java/club/joylink/xiannccda/ats/message/line3/DeviceNameChanger.java deleted file mode 100644 index ccfb0c2..0000000 --- a/src/main/java/club/joylink/xiannccda/ats/message/line3/DeviceNameChanger.java +++ /dev/null @@ -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 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> 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 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 names = graphicStorage.getTurnoutsList().stream().map(Turnout::getCode).toList(); - DEVICE_NAMES.put(DeviceType.DEVICE_TYPE_SWITCH, names); - } - - @Override - public String changeDeviceName(String nccDeviceName, List 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 names = graphicStorage.getSectionList().stream().map(Section::getCode).toList(); - DEVICE_NAMES.put(DeviceType.DEVICE_TYPE_TRACK, names); - } - - @Override - public String changeDeviceName(String nccDeviceName, List 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 names = graphicStorage.getSignalsList().stream().map(Signal::getCode).toList(); - DEVICE_NAMES.put(DeviceType.DEVICE_TYPE_SIGNAL, names); - } - - @Override - public String changeDeviceName(String nccDeviceName, List graphicNames) { - if (nccDeviceName.length() <= 3) { - return nccDeviceName; - } - return super.changeDeviceName(nccDeviceName.replaceAll("_", "-"), graphicNames); - } - } - -} - diff --git a/src/main/java/club/joylink/xiannccda/ats/message/line3/changer/DeviceNameChangerManage.java b/src/main/java/club/joylink/xiannccda/ats/message/line3/changer/DeviceNameChangerManage.java index b9141c7..e0b3f18 100644 --- a/src/main/java/club/joylink/xiannccda/ats/message/line3/changer/DeviceNameChangerManage.java +++ b/src/main/java/club/joylink/xiannccda/ats/message/line3/changer/DeviceNameChangerManage.java @@ -27,9 +27,17 @@ public class DeviceNameChangerManage { final static Table> 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 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; } diff --git a/src/main/java/club/joylink/xiannccda/ats/message/line3/rep/DeviceStatusBitmapResponse.java b/src/main/java/club/joylink/xiannccda/ats/message/line3/rep/DeviceStatusBitmapResponse.java index ba4867d..f8959d4 100644 --- a/src/main/java/club/joylink/xiannccda/ats/message/line3/rep/DeviceStatusBitmapResponse.java +++ b/src/main/java/club/joylink/xiannccda/ats/message/line3/rep/DeviceStatusBitmapResponse.java @@ -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; } } diff --git a/src/main/java/club/joylink/xiannccda/ats/message/line3/rep/DeviceStatusChangeResponse.java b/src/main/java/club/joylink/xiannccda/ats/message/line3/rep/DeviceStatusChangeResponse.java index 570144d..62ebdba 100644 --- a/src/main/java/club/joylink/xiannccda/ats/message/line3/rep/DeviceStatusChangeResponse.java +++ b/src/main/java/club/joylink/xiannccda/ats/message/line3/rep/DeviceStatusChangeResponse.java @@ -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 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); diff --git a/src/main/java/club/joylink/xiannccda/ats/message/line3/rep/TrainIndicationInitResponse.java b/src/main/java/club/joylink/xiannccda/ats/message/line3/rep/TrainIndicationInitResponse.java index 5ec4005..3ffb71b 100644 --- a/src/main/java/club/joylink/xiannccda/ats/message/line3/rep/TrainIndicationInitResponse.java +++ b/src/main/java/club/joylink/xiannccda/ats/message/line3/rep/TrainIndicationInitResponse.java @@ -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(); diff --git a/src/main/java/club/joylink/xiannccda/ats/message/line3/rep/TrainIndicationRemoveResponse.java b/src/main/java/club/joylink/xiannccda/ats/message/line3/rep/TrainIndicationRemoveResponse.java index 83f2353..77ac897 100644 --- a/src/main/java/club/joylink/xiannccda/ats/message/line3/rep/TrainIndicationRemoveResponse.java +++ b/src/main/java/club/joylink/xiannccda/ats/message/line3/rep/TrainIndicationRemoveResponse.java @@ -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, "")); diff --git a/src/main/java/club/joylink/xiannccda/ats/message/line3/rep/TrainIndicationUpdateResponse.java b/src/main/java/club/joylink/xiannccda/ats/message/line3/rep/TrainIndicationUpdateResponse.java index f1c9a01..85d623c 100644 --- a/src/main/java/club/joylink/xiannccda/ats/message/line3/rep/TrainIndicationUpdateResponse.java +++ b/src/main/java/club/joylink/xiannccda/ats/message/line3/rep/TrainIndicationUpdateResponse.java @@ -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();