嵌套写法示例
2024年3月24日小于 1 分钟
嵌套写法示例
提示
- 在阅读本文之前,建议先阅读 协议格式说明
- 所谓的 嵌套写法 就是将
Header
和Body
分别封装到单独的实体类中。
实体类定义
Rust 命名风格
@Setter
@Getter
@ToString
public class RustStyleDebugEntity02Nested {
// 消息头
@Preset.RustStyle.struct
private Header header;
// 消息体
@Preset.RustStyle.struct(lengthExpression = "header.msgBodyLength()")
private Body body;
// 校验码
@Preset.RustStyle.i8
private byte checkSum;
@Getter
@Setter
@ToString
public static class Header {
// byte[0-2) 消息ID word(16)
@Preset.RustStyle.u16
private int msgId;
// byte[2-4) 消息体属性 word(16)
@Preset.RustStyle.u16
private int msgBodyProps;
// byte[4] 协议版本号
@Preset.RustStyle.u8
private byte protocolVersion;
// byte[5-15) 终端手机号或设备ID bcd[10]
@Preset.RustStyle.str(charset = XtreamConstants.CHARSET_NAME_BCD_8421, length = 10)
private String terminalId;
// byte[15-17) 消息流水号 word(16)
@Preset.RustStyle.u16
private int msgSerialNo;
// byte[17-21) 消息包封装项
@Preset.RustStyle.u32(condition = "hasSubPackage()")
private Long subPackageInfo;
// bit[0-9] 0000,0011,1111,1111(3FF)(消息体长度)
public int msgBodyLength() {
return msgBodyProps & 0x3ff;
}
// bit[13] 0010,0000,0000,0000(2000)(是否有子包)
public boolean hasSubPackage() {
// return ((msgBodyProperty & 0x2000) >> 13) == 1;
return (msgBodyProps & 0x2000) > 0;
}
}
@Getter
@Setter
@ToString
public static class Body {
// 报警标志 DWORD(4)
@Preset.RustStyle.u32
private long alarmFlag;
// 状态 DWORD(4)
@Preset.RustStyle.u32
private long status;
// 纬度 DWORD(4)
@Preset.RustStyle.u32
private long latitude;
// 经度 DWORD(4)
@Preset.RustStyle.u32
private long longitude;
// 高程 WORD(2)
@Preset.RustStyle.u16
private int altitude;
// 速度 WORD(2)
@Preset.RustStyle.u16
private int speed;
// 方向 WORD(2)
@Preset.RustStyle.u16
private int direction;
// 时间 BCD[6] yyMMddHHmmss
@Preset.RustStyle.str(charset = XtreamConstants.CHARSET_NAME_BCD_8421, length = 6)
private String time;
@Preset.RustStyle.list
private List<ExtraItem> extraItems;
}
@Setter
@Getter
@ToString
public static class ExtraItem {
// 附加信息ID BYTE(1~255)
@Preset.RustStyle.u8
private short id;
// 附加信息长度 BYTE(1~255)
@Preset.RustStyle.u8
private short contentLength;
// 附加信息内容 BYTE[N]
@Preset.RustStyle.byte_array(lengthExpression = "getContentLength()")
private byte[] content;
public ExtraItem() {
}
public ExtraItem(short id, short contentLength, byte[] content) {
this.id = id;
this.contentLength = contentLength;
this.content = content;
}
}
}
原始命名风格
@Setter
@Getter
@ToString
public class RawStyleDebugEntity02Nested {
// 消息头
@XtreamField(dataType = BeanPropertyMetadata.FiledDataType.struct)
private Header header;
// 消息体
@XtreamField(dataType = BeanPropertyMetadata.FiledDataType.struct, lengthExpression = "header.msgBodyLength()")
private Body body;
// 校验码
@XtreamField(length = 1)
private byte checkSum;
@Getter
@Setter
@ToString
public static class Header {
// byte[0-2) 消息ID word(16)
@XtreamField(length = 2)
private int msgId;
// byte[2-4) 消息体属性 word(16)
@XtreamField(length = 2)
private int msgBodyProps;
// byte[4] 协议版本号
@XtreamField(length = 1)
private byte protocolVersion;
// byte[5-15) 终端手机号或设备ID bcd[10]
@XtreamField(charset = XtreamConstants.CHARSET_NAME_BCD_8421, length = 10)
private String terminalId;
// byte[15-17) 消息流水号 word(16)
@XtreamField(length = 2)
private int msgSerialNo;
// byte[17-21) 消息包封装项
@XtreamField(length = 4, condition = "hasSubPackage()")
private Long subPackageInfo;
// bit[0-9] 0000,0011,1111,1111(3FF)(消息体长度)
public int msgBodyLength() {
return msgBodyProps & 0x3ff;
}
// bit[13] 0010,0000,0000,0000(2000)(是否有子包)
public boolean hasSubPackage() {
// return ((msgBodyProperty & 0x2000) >> 13) == 1;
return (msgBodyProps & 0x2000) > 0;
}
}
@Getter
@Setter
@ToString
public static class Body {
// 报警标志 DWORD(4)
@XtreamField(length = 4)
private long alarmFlag;
// 状态 DWORD(4)
@XtreamField(length = 4)
private long status;
// 纬度 DWORD(4)
@XtreamField(length = 4)
private long latitude;
// 经度 DWORD(4)
@XtreamField(length = 4)
private long longitude;
// 高程 WORD(2)
@XtreamField(length = 2)
private int altitude;
// 速度 WORD(2)
@XtreamField(length = 2)
private int speed;
// 方向 WORD(2)
@XtreamField(length = 2)
private int direction;
// 时间 BCD[6] yyMMddHHmmss
@XtreamField(charset = XtreamConstants.CHARSET_NAME_BCD_8421, length = 6)
private String time;
@XtreamField(dataType = BeanPropertyMetadata.FiledDataType.sequence)
private List<ExtraItem> extraItems;
}
@Setter
@Getter
@ToString
public static class ExtraItem {
// 附加信息ID BYTE(1~255)
@XtreamField(length = 1)
private short id;
// 附加信息长度 BYTE(1~255)
@XtreamField(length = 1)
private short contentLength;
// 附加信息内容 BYTE[N]
@XtreamField(lengthExpression = "getContentLength()")
private byte[] content;
public ExtraItem() {
}
public ExtraItem(short id, short contentLength, byte[] content) {
this.id = id;
this.contentLength = contentLength;
this.content = content;
}
}
}
JT/T 808 命名风格
@Setter
@Getter
@ToString
public class JtStyleDebugEntity02Nested {
// 消息头
@Preset.JtStyle.Object
private Header header;
// 消息体
@Preset.JtStyle.Object(lengthExpression = "header.msgBodyLength()")
private Body body;
// 校验码
@Preset.JtStyle.Byte
private byte checkSum;
@Getter
@Setter
@ToString
public static class Header {
// byte[0-2) 消息ID word(16)
@Preset.JtStyle.Word
private int msgId;
// byte[2-4) 消息体属性 word(16)
@Preset.JtStyle.Word
private int msgBodyProps;
// byte[4] 协议版本号
@Preset.JtStyle.Byte
private byte protocolVersion;
// byte[5-15) 终端手机号或设备ID bcd[10]
@Preset.JtStyle.Bcd(length = 10)
private String terminalId;
// byte[15-17) 消息流水号 word(16)
@Preset.JtStyle.Word
private int msgSerialNo;
// byte[17-21) 消息包封装项
@Preset.JtStyle.Dword(condition = "hasSubPackage()")
private Long subPackageInfo;
// bit[0-9] 0000,0011,1111,1111(3FF)(消息体长度)
public int msgBodyLength() {
return msgBodyProps & 0x3ff;
}
// bit[13] 0010,0000,0000,0000(2000)(是否有子包)
public boolean hasSubPackage() {
// return ((msgBodyProperty & 0x2000) >> 13) == 1;
return (msgBodyProps & 0x2000) > 0;
}
}
@Getter
@Setter
@ToString
public static class Body {
// 报警标志 DWORD(4)
@Preset.JtStyle.Dword
private long alarmFlag;
// 状态 DWORD(4)
@Preset.JtStyle.Dword
private long status;
// 纬度 DWORD(4)
@Preset.JtStyle.Dword
private long latitude;
// 经度 DWORD(4)
@Preset.JtStyle.Dword
private long longitude;
// 高程 WORD(2)
@Preset.JtStyle.Word
private int altitude;
// 速度 WORD(2)
@Preset.JtStyle.Word
private int speed;
// 方向 WORD(2)
@Preset.JtStyle.Word
private int direction;
// 时间 BCD[6] yyMMddHHmmss
@Preset.JtStyle.Bcd(length = 6)
private String time;
@Preset.JtStyle.List
private List<ExtraItem> extraItems;
}
@Setter
@Getter
@ToString
public static class ExtraItem {
// 附加信息ID BYTE(1~255)
@Preset.JtStyle.Byte
private short id;
// 附加信息长度 BYTE(1~255)
@Preset.JtStyle.Byte
private short contentLength;
// 附加信息内容 BYTE[N]
@Preset.JtStyle.Bytes(lengthExpression = "getContentLength()")
private byte[] content;
public ExtraItem() {
}
public ExtraItem(short id, short contentLength, byte[] content) {
this.id = id;
this.contentLength = contentLength;
this.content = content;
}
}
}
反序列化
public class EntityDecodeTest {
@Test
void testDecode() {
final EntityCodec entityCodec = EntityCodec.DEFAULT;
// buffer 中存储的是要反序列化的数据(这里写死用来演示)
final String hexString = "0200402a01000000000139111122220063000000580000006f01dc9a0707456246231d029a005a240322222633010400001a0a02020058030200595b";
final ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer().writeBytes(XtreamBytes.decodeHex(hexString));
try {
final JtStyleDebugEntity02Nested entity = entityCodec.decode(JtStyleDebugEntity02Nested.class, buffer);
System.out.println(entity);
} finally {
buffer.release();
}
}
}
序列化
public class EntityEncodeTest {
@Test
void testEncode() {
final EntityCodec entityCodec = EntityCodec.DEFAULT;
final ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer();
try {
final JtStyleDebugEntity02Nested instance = new JtStyleDebugEntity02Nested();
// 省略属性赋值
// instance.setXxx(someValue);
// ...
instance.setHeader(...);
// 将 instance 的数据序列化到 buffer 中
entityCodec.encode(instance, buffer);
// 使用 buffer
System.out.println(ByteBufUtil.hexDump(buffer));
} finally {
buffer.release();
}
}
}